forked from baron/baron-sso
multi IDP 모델 적용 scaffolding
This commit is contained in:
93
page_content.txt
Normal file
93
page_content.txt
Normal file
@@ -0,0 +1,93 @@
|
||||
# 멀티 IDP 아키텍처 및 마이그레이션 전략
|
||||
|
||||
본 문서는 Primary IDP 변경(예: Descope → Hydra/Authentik) 시 시스템의 유연성을 보장하기 위한 아키텍처 설계 전략을 기술합니다.
|
||||
|
||||
## 핵심 전략
|
||||
|
||||
1. **Broker 패턴 고도화**: 백엔드가 모든 인증 요청을 중계하며, 클라이언트는 특정 IDP에 종속되지 않습니다.
|
||||
2. **추상화 계층 (Abstraction Layer)**: 비즈니스 로직은 `IdentityProvider` 인터페이스에만 의존하며, 구체적인 구현체(Descope, Hydra 등)는 알 필요가 없습니다.
|
||||
3. **식별자 분리 (Identifier Decoupling)**: 외부 IDP의 `sub` 값과 내부 시스템의 `user_id`를 분리하여 매핑합니다.
|
||||
|
||||
## 상세 설계
|
||||
|
||||
### 1. IdentityProvider 인터페이스 확장
|
||||
단순 메타데이터 조회를 넘어, 인증의 핵심 라이프사이클을 모두 포함하도록 인터페이스를 확장해야 합니다.
|
||||
|
||||
```go
|
||||
type IdentityProvider interface {
|
||||
// 메타데이터 및 스키마 검증
|
||||
Name() string
|
||||
GetMetadata() (*IDPMetadata, error)
|
||||
|
||||
// 핵심 인증/인가 기능
|
||||
SignUp(ctx context.Context, user *BrokerUser, password string) (*AuthResult, error)
|
||||
Login(ctx context.Context, loginID, password string) (*AuthResult, error)
|
||||
VerifyToken(ctx context.Context, token string) (*TokenInfo, error)
|
||||
|
||||
// 사용자 관리
|
||||
GetUser(ctx context.Context, id string) (*BrokerUser, error)
|
||||
UpdateUser(ctx context.Context, user *BrokerUser) error
|
||||
DeleteUser(ctx context.Context, id string) error
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Provider Factory 패턴
|
||||
설정(`config.yaml` 또는 환경변수)에 따라 사용할 IDP 구현체를 런타임에 결정합니다.
|
||||
|
||||
```go
|
||||
func NewIdentityProvider(config Config) (domain.IdentityProvider, error) {
|
||||
switch config.IDPType {
|
||||
case "descope":
|
||||
return service.NewDescopeProvider(config.Descope)
|
||||
case "hydra":
|
||||
return service.NewHydraProvider(config.Hydra)
|
||||
case "authentik":
|
||||
return service.NewAuthentikProvider(config.Authentik)
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported IDP type: %s", config.IDPType)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3. 식별자 매핑 (ID Mapping)
|
||||
IDP 변경 시 가장 큰 문제는 사용자 고유 ID(`sub`)가 바뀌는 것입니다. 이를 해결하기 위해 Baron SSO 내부 전용 UUID를 사용하고 매핑 테이블을 둡니다.
|
||||
|
||||
* **User Table (Baron Internal)**: `id` (UUID), `email`, ...
|
||||
* **IDP Link Table**: `baron_user_id`, `idp_provider` (e.g., descope), `idp_subject_id` (e.g., U12345)
|
||||
|
||||
## 구현 예시 (Descope)
|
||||
|
||||
현재 단계에서 즉시 사용 가능한 `DescopeProvider`의 구현 예시입니다.
|
||||
|
||||
```go
|
||||
// DescopeProvider는 IdentityProvider 인터페이스를 구현합니다.
|
||||
type DescopeProvider struct {
|
||||
Client *client.DescopeClient
|
||||
}
|
||||
|
||||
func (d *DescopeProvider) SignUp(ctx context.Context, user *domain.BrokerUser, password string) (*domain.AuthResult, error) {
|
||||
// BrokerUser를 Descope User 객체로 변환
|
||||
descopeUser := &descope.User{
|
||||
Name: user.Name,
|
||||
Email: user.Email,
|
||||
Phone: user.PhoneNumber,
|
||||
CustomAttributes: user.Attributes,
|
||||
}
|
||||
|
||||
// SDK 호출
|
||||
authInfo, err := d.Client.Auth.Password().SignUp(ctx, user.Email, descopeUser, password)
|
||||
if err != nil {
|
||||
return nil, err\n }
|
||||
|
||||
// 결과 반환
|
||||
return &domain.AuthResult{
|
||||
UserID: authInfo.User.UserID,
|
||||
Token: authInfo.SessionToken.JWT,
|
||||
}, nil
|
||||
}
|
||||
```
|
||||
|
||||
## 향후 지원 후보 (Candidates)
|
||||
|
||||
* **Ory Hydra**: 자체적인 OAuth2/OIDC 서버 구축이 필요할 때 적합. 높은 커스터마이징 가능.
|
||||
* **Authentik**: 오픈소스 IDP로, 설치형(Self-hosted) 환경에서 강력한 기능을 제공.
|
||||
Reference in New Issue
Block a user