# Descope Federated Apps 연동 PoC (Hydra 1st party 보조) 목표: Hydra를 1st party OIDC 엔진으로 유지하면서 Descope Federated Apps를 통해 외부 IDP(SAML/OIDC)를 빠르게 붙여 BYOID/소셜을 지원한다. Kratos/DB가 SoT가 되고, Hydra 토큰의 subject는 Kratos identity.id로 맞춘다. ## 플로우(로그인) ```mermaid sequenceDiagram participant RP as RP App participant HY as Hydra participant UI as Baron Login UI participant DS as Descope Federated App participant IDP as Ext. IDP (SAML/OIDC) participant KR as Kratos RP->>HY: /oauth2/auth (login_challenge) HY->>UI: redirect to login UI UI-->>UI: 사용자 선택: "Descope Federated App" UI->>DS: redirect to Descope Federated App (idp=azuread 등) DS->>IDP: AuthN (SAML/OIDC) IDP-->>DS: Assertion/Token DS-->>UI: redirect back with session/authorization data UI->>KR: upsert identity (traits from DS) UI->>KR: CreateSession (kratos admin) UI->>HY: AcceptLogin(subject=kratos identity.id, amr=descope-federated-{idp}) HY-->>RP: ID/Access Token 발급 (subject=kratos identity.id) ``` ## 환경 변수/구성 요소 - Hydra: `HYDRA_ADMIN_URL`, `HYDRA_PUBLIC_URL`, 등록된 RP 클라이언트(redirect URI 포함). - Kratos: `KRATOS_ADMIN_URL`, `KRATOS_PUBLIC_URL`, identity schema에 federated trait 필드 포함. - Descope: `DESCOPE_PROJECT_ID`, `DESCOPE_MANAGEMENT_KEY`, `DESCOPE_FEDERATED_APP_ID`, (옵션) `DESCOPE_TENANT`, `DESCOPE_BASE_URL`(self-host 시). - Baron UI/백엔드: Federated 버튼 노출 플래그, callback URL (`/auth/federated/descope/callback` 등), Hydra login_challenge 전달 경로. ## 데이터 매핑/저장 - Kratos identity traits 예: `email`, `email_verified`, `name`, `phone_number`, `department`, `grade`, `federated_identities` 배열. - federated_identities 제안 스키마 - `provider` (예: `descope-federated-azuread`) - `idp_sub` - `idp_email` - `idp_email_verified` - `raw_claims` (JSON, 최소 보관) - `last_login_at` - 최초 로그인: email match로 기존 identity 찾기 → 없으면 생성 → federated slot 추가. - 재로그인: provider+sub 매칭 후 Kratos identity.id 사용. ## 구현 단계 (PoC) 1) **Hydra 클라이언트 준비** - RP별 redirect URI 등록, `skip_consent` 옵션은 false 권장(동의 화면 제공 시). - `ory-net` 네트워크에서 Hydra Admin 접근 허용. 2) **Descope Federated App 설정** - Federated App 생성 후 외부 IDP(SAML/OIDC) 연결. - Callback을 Baron Login UI로 설정(`/auth/federated/descope/callback?login_challenge=...`). - 전달 클레임: `sub`, `email`, `email_verified`, `name`, `groups`(option), `phone_number`. 3) **Login UI/Backend 연결** - 옵션 버튼 “Sign in with (via Descope)” 추가. - Start 엔드포인트: Hydra login_challenge를 받고 Descope Federated App redirect URL 생성 후 302. - Callback 핸들러: - Descope session/token 검증 (관리 키 또는 JWKS). - Kratos identity upsert (traits + federated slot). - Kratos `CreateSession` 호출 → 세션 쿠키 설정. - Hydra `AcceptLogin` 호출(subject=kratos identity.id, amr=`federated:descope-{idp}`) → Hydra redirect. 4) **로그/감사** - Hydra login_challenge, provider, sub, email, amr 기록. - 실패 시 Hydra `RejectLogin`로 일관된 에러 제공. ## 보안/운영 체크 - `email_verified` 필수 검증, 미확인 이메일은 거절 또는 별도 플로우. - 토큰/세션 검증 시 JWKS 캐시 및 만료 확인. - Rate limit: Federated callback, Hydra login_challenge 재사용 방지. - PII 최소 저장: raw_claims는 단기 TTL 또는 축약 저장. - 장애 시 폴백: `IDP_PROVIDER=ory,descope` 설정으로 Descope 기본 로컬 로그인 경로 유지. ## 테스트 시나리오 (PoC) - 성공: Federated 버튼 → 외부 IDP 로그인 → Hydra 토큰 발급, subject=kratos identity.id 확인. - 이메일 검증 실패: email_verified=false인 경우 거절 메시지. - 재로그인: 기존 federated_identities 매칭 후 동일 subject 유지. - 오류: 잘못된 login_challenge, 만료된 Descope 토큰, Hydra RejectLogin 동작 확인. ## 후속 구현(코드) - Ory IDP 어댑터에 Kratos Admin/Hydra Admin 연동 구현 (`InitiatePasswordReset`, `VerifyPasswordResetToken`, `UpdateUserPassword` 포함). - AuthHandler에서 Descope 종속 로직을 IDP 추상화 기반으로 재구성(비밀번호 재설정/가입/로그인 모두). - Login UI에 Federated 버튼 및 상태 처리 추가. - CI에서 ory-stack 기동 + federated mock IDP로 통합 테스트 추가.