# DevFront OIDC 인증 흐름 및 무한 루프 해결 보고 이 문서는 `devfront` 개발자 포털의 OIDC 인증 구현 방식, 무한 루프 문제의 원인 및 해결 방법, 그리고 클라이언트 자동 등록 원리에 대해 설명합니다. ## 1. DevFront 로그인 동작 플로우 (OIDC Authorization Code Flow) ### 시퀀스 다이어그램 ```mermaid sequenceDiagram actor User participant DF as DevFront (RP) participant HY as Ory Hydra (OP) participant UF as UserFront (Login UI) participant KR as Ory Kratos (Identity) User->>DF: 로그인 버튼 클릭 DF->>HY: 인증 요청 (/oauth2/auth) HY->>UF: 로그인 UI 리다이렉트 UF->>User: 로그인 페이지 표시 User->>UF: 자격 증명 입력 (Email/PW) UF->>KR: 인증 수행 KR-->>UF: 인증 성공 (Session 생성) UF->>HY: 로그인 승인 요청 HY->>User: 권한 동의(Consent) 화면 표시 User->>HY: '허용' 클릭 HY-->>DF: 인증 코드와 함께 리다이렉트 (/auth/callback?code=...) DF->>HY: 토큰 교환 요청 (Code -> ID/Access Token) HY-->>DF: 토큰 발급 Note over DF: [FIX] 백엔드 /api/me 호출 대신
ID Token에서 프로필 정보 직접 추출 DF->>User: 대시보드 및 프로필 표시 ``` ### 단계별 설명 1. **인증 요청 (Login Request)**: * 사용자가 `devfront` (localhost:5174)의 로그인 버튼을 클릭합니다. * `react-oidc-context` 라이브러리가 Hydra의 `/oauth2/auth` 엔드포인트로 사용자를 리다이렉트합니다. * 이때 클라이언트 ID(`devfront`), 리다이렉트 URI, Scope 등을 파라미터로 전달합니다. 2. **사용자 인증 (Authentication)**: * Hydra는 현재 세션이 없음을 확인하고, 설정된 로그인 UI(`userfront`)로 사용자를 보냅니다. * 사용자는 `userfront`에서 아이디/비밀번호를 입력하여 Kratos를 통해 인증을 마칩니다. 3. **권한 동의 (Consent)**: * 인증이 완료되면 Hydra는 사용자에게 `devfront` 앱이 요청한 권한(openid, profile, email 등)을 허용할지 묻는 Consent 화면을 띄웁니다. * 사용자가 '허용'을 누르면 Hydra는 `devfront`가 신뢰할 수 있는 앱임을 기록합니다. 4. **인증 코드 전달 및 토큰 교환 (Callback)**: * Hydra는 사용자를 `devfront`의 콜백 페이지(`http://localhost:5174/auth/callback?code=...`)로 보냅니다. * `devfront`는 이 코드를 Hydra의 토큰 엔드포인트로 보내 **ID Token**과 **Access Token**을 발급받습니다. 5. **사용자 정보 로드 (Profile Recovery)**: * `devfront`는 발급받은 **ID Token**의 Payload를 디코딩하여 사용자 이름, 이메일 등의 프로필 정보를 즉시 화면에 렌더링합니다. --- ## 2. 클라이언트 자동 등록의 원리 사용자가 직접 `devfront`를 클라이언트로 등록하지 않았음에도 로그인이 가능한 이유는 인프라 설정 파일인 `compose.ory.yaml`에 정의된 **`init-rp` 컨테이너** 덕분입니다. ### `init-rp` 서비스의 역할 * Ory 스택(Kratos, Hydra, Keto)이 모두 정상 가동된 직후 실행됩니다. * Hydra Admin API를 호출하여 서비스 운영에 필수적인 기본 클라이언트들을 자동으로 생성합니다. ### 자동 등록된 `devfront` 명세 ```bash hydra clients create --endpoint http://hydra:4445 --id devfront --grant-types authorization_code,refresh_token --response-types code --scope openid,offline_access,profile,email --token-endpoint-auth-method none \ # Public Client (PKCE 사용) --callbacks http://localhost:5174/auth/callback; ``` 이 설정으로 인해 `devfront`라는 ID의 클라이언트가 미리 존재하게 되며, `localhost:5174/auth/callback`으로의 리다이렉션이 안전하게 허용됩니다. --- ## 3. 무한 루프 문제 해결 분석 ### 발생 원인 (Problem) * `devfront`가 로그인 성공 후 사용자 정보를 가져오기 위해 백엔드 API인 `/api/v1/user/me`를 호출했습니다. * 이 API는 백엔드 세션 쿠키를 기반으로 동작하도록 설계되어 있었습니다. * 하지만 브라우저 보안 정책(SameSite/Cross-Domain)으로 인해 `localhost`에서 보낸 요청에는 `sso.example.test` 도메인의 쿠키가 포함되지 않았습니다. * **결과**: 백엔드는 401 Unauthorized를 반환 -> `devfront`는 401을 받으면 다시 로그인을 시도하도록 구현되어 있어 무한 루프가 발생했습니다. ### 해결 방법 (Solution) * **쿠키 의존성 제거**: `AppLayout.tsx`에서 백엔드 호출(`fetchMe`)을 삭제했습니다. * **ID Token 직접 활용**: 이미 OIDC 인증 성공 시점에 전달받은 **ID Token(`auth.user.profile`)**에 필요한 모든 사용자 정보가 들어있으므로, 이를 직접 사용하도록 수정했습니다. * **표준 RP 구조 확립**: 이제 `devfront`는 백엔드의 세션 쿠키를 전혀 사용하지 않으며, API 요청 시에도 `Authorization: Bearer ` 헤더를 사용하여 정당한 권한을 증명합니다.