diff --git a/docs/backchannel-logout-guide.md b/docs/backchannel-logout-guide.md index 0a0e9988..6d893713 100644 --- a/docs/backchannel-logout-guide.md +++ b/docs/backchannel-logout-guide.md @@ -21,71 +21,6 @@ Baron SSO는 모든 RP에 대해 같은 방식으로 `POST /backchannel-logout` - `server-side-app RP` - `headless login RP`는 `PKCE` 기반 custom login UI 변형 -## Polling과 Session Management - -`polling`에 가장 가까운 OIDC 개념은 **Back-Channel Logout**이 아니라 **OpenID Connect Session Management**입니다. - -이 방식은 RP 서버가 OP 서버를 주기적으로 polling하는 구조가 아니라, **RP 브라우저 화면 안에서 OP의 `check_session_iframe`과 통신하면서 OP 세션 상태 변화 여부를 확인**하는 구조입니다. - -개념적으로는 다음과 같습니다. - -```text -RP 브라우저 화면 - ↓ 주기적으로 확인 -OP check_session_iframe - ↓ -changed / unchanged / error - ↓ -changed면 RP가 재인증 또는 로그아웃 처리 -``` - -즉, 이건 브라우저 기반 front-channel/iframe 방식이지, RP 서버가 OP 서버에 주기적으로 polling하는 Back-Channel Logout 방식은 아닙니다. - -### Session Management를 쓸 때의 의미 - -Session Management를 도입하면 RP는 브라우저를 통해 OP 세션 상태 변화를 감지하고, 상태가 바뀌면 로컬 세션을 정리하거나 재인증을 유도합니다. - -일반적인 흐름은 다음과 같습니다. - -1. 로그인 시 RP가 OP 세션 식별에 필요한 정보를 보관합니다. -2. RP 화면이 `check_session_iframe` 상태를 주기적으로 확인합니다. -3. OP 세션이 바뀌면 `changed`를 받습니다. -4. RP가 로컬 세션을 삭제하거나 재인증을 시작합니다. - -### Session Management 기반 로직 구성 예시 - -```mermaid -sequenceDiagram - autonumber - participant Browser as RP Browser - participant RP as RP App - participant IFrame as OP check_session_iframe - participant Store as RP Session Store - - loop 주기적 확인 - Browser->>IFrame: session state check - IFrame-->>Browser: changed / unchanged / error - alt unchanged - Browser->>RP: 로컬 세션 유지 - else changed - Browser->>RP: 재인증 또는 로그아웃 유도 - RP->>Store: session destroy - RP->>RP: 세션 매핑 제거 - else error - Browser->>RP: 재시도 또는 안전 로그아웃 - end - end -``` - -권장 구성은 다음과 같습니다. - -1. 로그인 시 `sid` 또는 `sub`를 RP 세션에 저장합니다. -2. RP 화면이 `check_session_iframe` 상태를 주기적으로 확인합니다. -3. `changed`가 오면 RP가 로컬 세션을 삭제하거나 재인증을 시작합니다. -4. `error`가 반복되면 안전하게 로그아웃 처리하는 정책을 둘 수 있습니다. - -이 방식은 `Back-Channel Logout`과 별개로 설계하는 것이 좋습니다. - ## 공통 시퀀스 아래 흐름은 세 RP에 공통입니다. diff --git a/docs/pkce-backchannel-logout-guide.md b/docs/pkce-backchannel-logout-guide.md deleted file mode 100644 index 6385ab7a..00000000 --- a/docs/pkce-backchannel-logout-guide.md +++ /dev/null @@ -1,321 +0,0 @@ -# PKCE RP Back-Channel Logout 구현 가이드 - -이 문서는 Baron SSO와 연동하는 PKCE RP가 `Back-Channel Logout`을 지원하려고 할 때 필요한 구현 기준을 정리합니다. - -## 목적 - -PKCE RP도 OIDC `Authorization Code + PKCE` 흐름을 사용하면서 Baron SSO의 원격 세션 종료 이벤트를 받을 수 있어야 합니다. 다만 `Back-Channel Logout`은 브라우저가 아니라 OP(Baron)가 RP 서버로 직접 `logout_token`을 보내는 방식이므로, **순수 frontend-only PKCE 앱만으로는 구현할 수 없습니다.** - -즉, PKCE RP가 `Back-Channel Logout`을 사용하려면 다음 둘을 모두 가져야 합니다. - -1. PKCE 로그인 플로우를 시작하고 callback을 처리하는 RP -2. `logout_token`을 수신하는 서버 endpoint - -## 적용 대상 - -이 가이드는 다음 경우를 대상으로 합니다. - -- 브라우저에서 `Authorization Code + PKCE`를 사용하는 RP -- RP가 자체 세션 또는 BFF 세션을 보유하는 경우 -- RP가 `Back-Channel Logout URI`를 등록하고 Baron의 세션 종료 이벤트를 직접 수신하려는 경우 - -다음 경우는 이 가이드의 직접 대상이 아닙니다. - -- 순수 frontend-only SPA -- 서버 없이 `localStorage`/`sessionStorage`만 사용하는 PKCE 앱 - -이 경우에는 `Back-Channel Logout` 대신 front-channel logout, 세션 재검증, 짧은 token TTL 같은 별도 전략을 사용해야 합니다. - -## devfront 등록 기준 - -PKCE RP는 devfront에서 아래 항목을 등록합니다. - -1. `Type`: `pkce` -2. `Redirect URI`: RP callback URL -3. `Back-Channel Logout URI`: RP 서버 endpoint -4. 필요 시 `SID Claim Required` - -예시: - -```text -Type: pkce -Redirect URI: https://rp.example.com/callback -Back-Channel Logout URI: https://rp.example.com/backchannel-logout -SID Claim Required: off -``` - -로컬 Docker 개발 예시: - -```text -Redirect URI: http://localhost:3333/callback -Back-Channel Logout URI: http://baron-sso-login-demo:3333/backchannel-logout -``` - -주의: - -- `Back-Channel Logout URI`는 **브라우저 기준 주소가 아니라 Baron backend가 실제로 접근 가능한 주소**여야 합니다. -- Docker 환경에서는 `localhost`가 backend 컨테이너 자신을 가리킬 수 있으므로, Docker 서비스명이나 사설 IP를 사용해야 할 수 있습니다. - -## 구현 요구사항 - -PKCE RP는 최소한 아래를 구현해야 합니다. - -### 1. 로그인 후 세션 매핑 저장 - -RP는 callback 이후 아래 정보 중 하나 이상을 로컬 세션과 연결해야 합니다. - -- `sid -> rpSessionId` -- `sub -> rpSessionId` - -권장 순서는 다음과 같습니다. - -1. `sid`를 우선 저장 -2. `sub`도 함께 저장 -3. 한 사용자가 여러 브라우저 세션을 가질 수 있으므로 `1:N` 구조를 가정 - -예시: - -```text -sid: 796f5cf7-37e7-494b-9b4c-26cc0c217a6a -sub: 8150cb83-a905-4b50-bdcf-d22046ecdc30 -rpSessionId: DqKlQ8MbsGnn_jfOus1k03MFRDpuXCrj -``` - -### 2. `POST /backchannel-logout` endpoint - -RP는 Baron이 서버 간으로 호출할 endpoint를 제공해야 합니다. - -예: - -```text -POST /backchannel-logout -Content-Type: application/x-www-form-urlencoded -Body: logout_token= -``` - -RP는 이 endpoint에서: - -1. `logout_token` 존재 여부 확인 -2. JWT 서명 및 claim 검증 -3. `sid` 또는 `sub`로 로컬 세션 탐색 -4. 세션 스토어에서 직접 세션 파기 -5. 성공 시 `2xx` 응답 - -을 수행해야 합니다. - -### 3. `logout_token` 검증 - -RP는 Baron이 노출하는 Back-Channel Logout JWKS로 `logout_token`을 검증해야 합니다. - -현재 Baron의 JWKS endpoint 예시는 다음과 같습니다. - -```text -GET /api/v1/auth/backchannel/jwks.json -``` - -검증 필수 항목: - -1. JWT 서명 검증 -2. `iss`가 Baron OIDC issuer와 일치 -3. `aud`에 현재 RP `client_id` 포함 -4. `iat` 존재 -5. `jti` 존재 -6. `events`에 `http://schemas.openid.net/event/backchannel-logout` 포함 -7. `nonce`가 없어야 함 -8. `sid` 또는 `sub`가 있어야 함 - -추가 권장 항목: - -- `jti` replay 방지 캐시 -- 시계 오차 허용 범위 설정 -- 검증 실패 시 `400` - -## 세션 종료 기준 - -### 권장 순서 - -1. `sid`로 매칭 시도 -2. 매칭 실패 시 `sub`로 fallback - -이 기준은 `SID Claim Required` 정책에 따라 달라집니다. - -### `SID Claim Required = true` - -- `logout_token`에 `sid`가 있어야만 처리 -- `sub` fallback 금지 -- 세션 모델이 `sid` 중심으로 안정적으로 유지되는 RP에 적합 - -### `SID Claim Required = false` - -- `sid`가 있으면 우선 사용 -- `sid` 매칭이 안 되거나 `sid`가 없어도 `sub`로 fallback 가능 -- 실제 운영에서는 이 모드가 더 현실적일 수 있음 - -## 세션 파기 방식 - -`Back-Channel Logout`에서는 현재 브라우저 요청의 `req.session.destroy()`로는 부족합니다. -반드시 **세션 스토어에서 session id를 찾아 직접 파기**해야 합니다. - -예: - -```text -store.destroy(rpSessionId) -``` - -필수 조건: - -- 로그아웃 대상 세션 ID를 매핑 테이블에서 찾을 수 있어야 함 -- 이미 삭제된 세션은 idempotent success 처리 - -## 권장 로그 항목 - -RP는 아래 정도의 로그를 남기는 것을 권장합니다. - -1. 요청 수신 -2. 토큰 검증 성공/실패 -3. `sid`, `sub`, `jti` -4. 매칭된 `rpSessionId` 목록 -5. 세션 파기 성공/실패 수 - -예시: - -```text -[백채널 로그아웃] 요청 수신 -[백채널 로그아웃] 토큰 검증 성공 -[백채널 로그아웃] 세션 탐색 결과 -[백채널 로그아웃] 세션 파기 완료 -[백채널 로그아웃] 처리 완료 -``` - -주의: - -- raw `logout_token` 전체를 로그에 남기지 않습니다. -- access token, refresh token, cookie raw value도 남기지 않습니다. - -## 테스트 체크리스트 - -### 기본 성공 시나리오 - -1. PKCE RP 로그인 -2. callback 후 `sid/sub -> rpSessionId` 매핑 생성 확인 -3. UserFront에서 `세션 종료` -4. Baron이 RP의 `Back-Channel Logout URI`로 POST -5. RP가 `logout_token` 검증 성공 -6. RP 세션 파기 성공 -7. 보호 페이지 접근 시 비로그인 상태 확인 - -### 확인 포인트 - -1. devfront에 `Back-Channel Logout URI`가 실제 저장됐는가 -2. Baron backend가 해당 URI에 실제로 도달 가능한가 -3. RP 로그에 `요청 수신`과 `토큰 검증 성공`이 찍히는가 -4. 세션 스토어에서 실제 세션이 삭제됐는가 -5. `SID Claim Required=true`일 때와 `false`일 때 결과가 의도대로 다른가 - -## 구현 예시 구조 - -Node.js/Express 기준 최소 구조 예시는 다음과 같습니다. - -```text -GET /login -GET /callback -GET /profile -GET /logout -POST /backchannel-logout -``` - -내부 저장 예시: - -```text -sidToSessionIds: Map> -subToSessionIds: Map> -sessionIdToBinding: Map -``` - -실제 분리 예시는 아래 데모 코드를 참고할 수 있습니다. - -- 백채널 로그아웃 모듈: `https://gitea.hmac.kr/kyy/pkce-login-demo/src/branch/main/backchannel-logout.js` -- 데모 앱 엔트리포인트: `https://gitea.hmac.kr/kyy/pkce-login-demo/src/branch/main/app.js` - -이 데모는: - -1. callback 이후 `registerSessionBinding()`으로 `sid/sub -> sessionId`를 등록 -2. `POST /backchannel-logout`에서 `handleBackchannelLogout`를 그대로 연결 -3. 로컬 `/logout` 또는 세션 정리 시 `removeSessionBinding()` 호출 - -구조로 동작합니다. - -## 자주 생기는 문제 - -### 1. `localhost`로는 안 되는데 입력은 저장됨 - -입력 validation을 통과하는 것과 Baron backend가 실제로 그 주소에 도달하는 것은 다릅니다. - -예: - -```text -http://localhost:3333/backchannel-logout -``` - -이 값은 backend 컨테이너 기준으로는 자기 자신을 가리킬 수 있습니다. Docker 환경에서는 Docker 서비스명 또는 사설 IP를 사용해야 할 수 있습니다. - -### 2. `sid`가 로그인 시 값과 다름 - -실제 운영에서는 `logout_token.sid`가 RP가 저장한 `sid`와 항상 같다고 가정하면 안 됩니다. - -따라서: - -1. `sid` 우선 -2. `sub` fallback - -구현을 권장합니다. 다만 보안 정책상 `SID Claim Required=true`를 선택한 경우에는 fallback 없이 `sid`만 사용해야 합니다. - -### 3. 순수 frontend-only PKCE인데 endpoint를 만들 수 없음 - -그 경우는 `Back-Channel Logout` 자체를 구현할 수 없습니다. 최소한 logout 수신용 서버 컴포넌트를 추가해야 합니다. - -## 로직 흐름 - -```mermaid -sequenceDiagram - autonumber - participant Browser as 브라우저 - participant RP as PKCE RP - participant Baron as Baron SSO - participant Store as 세션 스토어 - - Browser->>RP: GET /login 호출 - RP->>Browser: Baron authorize endpoint로 리다이렉트 - Browser->>Baron: Authorization Code + PKCE 로그인 - Baron->>Browser: /callback?code=... 으로 리다이렉트 - Browser->>RP: GET /callback 호출 - RP->>Baron: code_verifier 포함 token 요청 - Baron-->>RP: ID Token / Access Token 반환 - RP->>Store: RP 세션 생성 - RP->>RP: registerSessionBinding(sessionId, sid, sub) - RP-->>Browser: 로그인 완료 응답 - - Browser->>Baron: UserFront 또는 연동 서비스에서 세션 종료 - Baron->>RP: POST /backchannel-logout (logout_token) - RP->>Baron: Back-Channel JWKS로 logout_token 검증 - Baron-->>RP: 서명 / issuer / audience 검증 기준 제공 - RP->>RP: sid 또는 sub로 sessionId 탐색 - RP->>Store: destroy(sessionId) - RP->>RP: removeSessionBinding(sessionId) - RP-->>Baron: 200 OK - - Browser->>RP: GET /profile 호출 - RP-->>Browser: 루트 리다이렉트 또는 비로그인 응답 -``` - -## 권장 결론 - -PKCE RP에서 `Back-Channel Logout`을 쓰려면, 다음 원칙을 따르십시오. - -1. PKCE 로그인 플로우는 그대로 유지 -2. logout 수신용 서버 endpoint 별도 구현 -3. `sid`와 `sub`를 모두 저장 -4. 세션 스토어에서 직접 세션 파기 -5. 로컬 개발 시 Baron backend가 도달 가능한 URI를 사용 - -이 다섯 가지가 갖춰져야 Baron의 원격 세션 종료가 RP 로컬 세션 종료까지 이어집니다. diff --git a/docs/server-side-app-backchannel-logout-guide.md b/docs/server-side-app-backchannel-logout-guide.md deleted file mode 100644 index 93f18761..00000000 --- a/docs/server-side-app-backchannel-logout-guide.md +++ /dev/null @@ -1,322 +0,0 @@ -# Server-Side App RP Back-Channel Logout 구현 가이드 - -이 문서는 Baron SSO와 연동하는 `server-side-app` RP가 `Back-Channel Logout`을 지원하려고 할 때 필요한 구현 기준을 정리합니다. - -## 목적 - -`server-side-app` RP는 confidential client로 동작하면서, Baron SSO의 원격 세션 종료 이벤트를 받아 RP 로컬 세션을 즉시 정리할 수 있어야 합니다. - -즉, `server-side-app` RP는 다음 둘을 모두 구현해야 합니다. - -1. OIDC Authorization Code 로그인과 callback 처리 -2. `logout_token`을 수신하는 `Back-Channel Logout URI` - -## 적용 대상 - -이 가이드는 다음 경우를 대상으로 합니다. - -- `server-side-app` 타입 RP -- confidential client -- `client_secret_basic` 또는 `client_secret_post`를 사용하는 RP -- 자체 서버 세션 또는 BFF 세션을 보유하는 RP - -다음 경우는 이 가이드의 직접 대상이 아닙니다. - -- 순수 frontend-only SPA -- public client 기반 PKCE 앱 - -## devfront 등록 기준 - -`server-side-app` RP는 devfront에서 아래 항목을 등록합니다. - -1. `Type`: `server-side-app` -2. `Redirect URI`: RP callback URL -3. `Back-Channel Logout URI`: RP 서버 endpoint -4. 필요 시 `SID Claim Required` - -예시: - -```text -Type: server-side-app -Redirect URI: http://localhost:4444/callback -Back-Channel Logout URI: http://172.16.9.208:4444/backchannel-logout -SID Claim Required: off -``` - -주의: -- `Back-Channel Logout URI`는 **브라우저 기준 주소가 아니라 Baron backend가 실제로 접근 가능한 주소**여야 합니다. -- Docker 환경에서는 `localhost`가 backend 컨테이너 자신을 가리킬 수 있으므로, 필요하면 사설 IP 또는 Docker 서비스명을 사용해야 합니다. - -## 구현 요구사항 - -`server-side-app` RP는 최소한 아래를 구현해야 합니다. - -### 1. confidential client 구성 - -RP는 일반적으로 아래 중 하나의 인증 방식을 사용합니다. - -1. `client_secret_basic` -2. `client_secret_post` - -즉 token 교환 시: - -- `client_id` -- `client_secret` - -가 함께 사용됩니다. - -PKCE와 달리 `code_verifier`, `code_challenge`는 필수가 아닙니다. - -### 2. 로그인 후 세션 매핑 저장 - -RP는 callback 이후 아래 정보 중 하나 이상을 로컬 세션과 연결해야 합니다. - -- `sid -> rpSessionId` -- `sub -> rpSessionId` - -권장 순서는 다음과 같습니다. - -1. `sid`를 우선 저장 -2. `sub`도 함께 저장 -3. 한 사용자가 여러 브라우저 세션을 가질 수 있으므로 `1:N` 구조를 가정 - -예시: - -```text -sid: 796f5cf7-37e7-494b-9b4c-26cc0c217a6a -sub: 8150cb83-a905-4b50-bdcf-d22046ecdc30 -rpSessionId: DqKlQ8MbsGnn_jfOus1k03MFRDpuXCrj -``` - -### 3. `POST /backchannel-logout` endpoint - -RP는 Baron이 서버 간으로 호출할 endpoint를 제공해야 합니다. - -예: - -```text -POST /backchannel-logout -Content-Type: application/x-www-form-urlencoded -Body: logout_token= -``` - -RP는 이 endpoint에서: - -1. `logout_token` 존재 여부 확인 -2. JWT 서명 및 claim 검증 -3. `sid` 또는 `sub`로 로컬 세션 탐색 -4. 세션 스토어에서 직접 세션 파기 -5. 성공 시 `2xx` 응답 - -을 수행해야 합니다. - -### 4. `logout_token` 검증 - -RP는 Baron이 노출하는 Back-Channel Logout JWKS로 `logout_token`을 검증해야 합니다. - -현재 Baron의 JWKS endpoint 예시는 다음과 같습니다. - -```text -GET /api/v1/auth/backchannel/jwks.json -``` - -검증 필수 항목: - -1. JWT 서명 검증 -2. `iss`가 Baron OIDC issuer와 일치 -3. `aud`에 현재 RP `client_id` 포함 -4. `iat` 존재 -5. `jti` 존재 -6. `events`에 `http://schemas.openid.net/event/backchannel-logout` 포함 -7. `nonce`가 없어야 함 -8. `sid` 또는 `sub`가 있어야 함 - -추가 권장 항목: - -- `jti` replay 방지 캐시 -- 시계 오차 허용 범위 설정 -- 검증 실패 시 `400` - -## 세션 종료 기준 - -### 권장 순서 - -1. `sid`로 매칭 시도 -2. 매칭 실패 시 `sub`로 fallback - -이 기준은 `SID Claim Required` 정책에 따라 달라집니다. - -### `SID Claim Required = true` - -- `logout_token`에 `sid`가 있어야만 처리 -- `sub` fallback 금지 -- `sid` 중심 세션 모델을 운영하는 RP에 적합 - -### `SID Claim Required = false` - -- `sid`가 있으면 우선 사용 -- `sid` 매칭이 안 되거나 `sid`가 없어도 `sub`로 fallback 가능 -- 실제 운영에서는 이 모드가 더 유연할 수 있음 - -## 세션 파기 방식 - -`Back-Channel Logout`에서는 현재 브라우저 요청의 `req.session.destroy()`로는 부족합니다. -반드시 **세션 스토어에서 session id를 찾아 직접 파기**해야 합니다. - -예: - -```text -store.destroy(rpSessionId) -``` - -필수 조건: - -- 로그아웃 대상 세션 ID를 매핑 테이블에서 찾을 수 있어야 함 -- 이미 삭제된 세션은 idempotent success 처리 - -## 권장 로그 항목 - -RP는 아래 정도의 로그를 남기는 것을 권장합니다. - -1. 요청 수신 -2. 토큰 검증 성공/실패 -3. `sid`, `sub`, `jti` -4. 매칭된 `rpSessionId` 목록 -5. 세션 파기 성공/실패 수 - -예시: - -```text -[백채널 로그아웃] 요청 수신 -[백채널 로그아웃] 토큰 검증 성공 -[백채널 로그아웃] 세션 탐색 결과 -[백채널 로그아웃] 세션 파기 완료 -[백채널 로그아웃] 처리 완료 -``` - -주의: -- raw `logout_token` 전체를 로그에 남기지 않습니다. -- access token, refresh token, cookie raw value도 남기지 않습니다. - -## 테스트 체크리스트 - -### 기본 성공 시나리오 - -1. server-side-app RP 로그인 -2. callback 후 `sid/sub -> rpSessionId` 매핑 생성 확인 -3. UserFront에서 `세션 종료` -4. Baron이 RP의 `Back-Channel Logout URI`로 POST -5. RP가 `logout_token` 검증 성공 -6. RP 세션 파기 성공 -7. 보호 페이지 접근 시 비로그인 상태 확인 - -### 확인 포인트 - -1. devfront에 `Back-Channel Logout URI`가 실제 저장됐는가 -2. Baron backend가 해당 URI에 실제로 도달 가능한가 -3. RP 로그에 `요청 수신`과 `토큰 검증 성공`이 찍히는가 -4. 세션 스토어에서 실제 세션이 삭제됐는가 -5. `SID Claim Required=true`일 때와 `false`일 때 결과가 의도대로 다른가 - -## 구현 예시 구조 - -Node.js/Express 기준 최소 구조 예시는 다음과 같습니다. - -```text -GET /login -GET /callback -GET /profile -GET /logout -POST /backchannel-logout -``` - -내부 저장 예시: - -```text -sidToSessionIds: Map> -subToSessionIds: Map> -sessionIdToBinding: Map -``` - -실제 분리 예시는 아래 데모 코드를 참고할 수 있습니다. - -- 백채널 로그아웃 모듈: `/home/kyy/workspace/baron-sso-server-side-demo/backchannel-logout.js` -- 데모 앱 엔트리포인트: `/home/kyy/workspace/baron-sso-server-side-demo/app.js` - -이 데모는: - -1. callback 이후 `registerSessionBinding()`으로 `sid/sub -> sessionId`를 등록 -2. `POST /backchannel-logout`에서 `handleBackchannelLogout`를 그대로 연결 -3. 로컬 `/logout` 또는 세션 정리 시 `removeSessionBinding()` 호출 - -구조로 동작합니다. - -## 자주 생기는 문제 - -### 1. `localhost`로는 안 되는데 입력은 저장됨 - -입력 validation을 통과하는 것과 Baron backend가 실제로 그 주소에 도달하는 것은 다릅니다. - -예: - -```text -http://localhost:4444/backchannel-logout -``` - -이 값은 backend 컨테이너 기준으로는 자기 자신을 가리킬 수 있습니다. Docker 환경에서는 Docker 서비스명 또는 사설 IP를 사용해야 할 수 있습니다. - -### 2. `sid`가 로그인 시 값과 다름 - -실제 운영에서는 `logout_token.sid`가 RP가 저장한 `sid`와 항상 같다고 가정하면 안 됩니다. - -따라서: - -1. `sid` 우선 -2. `sub` fallback - -구현을 권장합니다. 다만 보안 정책상 `SID Claim Required=true`를 선택한 경우에는 fallback 없이 `sid`만 사용해야 합니다. - -### 3. `client_secret` 또는 auth method가 잘못되어 callback에서 실패함 - -`server-side-app`은 confidential client이므로 아래 값이 정확해야 합니다. - -1. `client_id` -2. `client_secret` -3. `token_endpoint_auth_method` -4. `redirect_uri` - -이 중 하나라도 다르면 authorization code 교환 단계에서 실패할 수 있습니다. - -## 시퀀스 다이어그램 - -```mermaid -sequenceDiagram - autonumber - participant Browser as 브라우저 - participant RP as Server-Side RP - participant Baron as Baron SSO - participant Store as 세션 스토어 - - Browser->>RP: GET /login 호출 - RP->>Browser: Baron authorize endpoint로 리다이렉트 - Browser->>Baron: Authorization Code 로그인 - Baron->>Browser: /callback?code=... 으로 리다이렉트 - Browser->>RP: GET /callback 호출 - RP->>Baron: client_secret 포함 token 요청 - Baron-->>RP: ID Token / Access Token 반환 - RP->>Store: RP 세션 생성 - RP->>RP: registerSessionBinding(sessionId, sid, sub) - RP-->>Browser: 로그인 완료 응답 - - Browser->>Baron: UserFront 또는 연동 서비스에서 세션 종료 - Baron->>RP: POST /backchannel-logout (logout_token) - RP->>Baron: Back-Channel JWKS로 logout_token 검증 - Baron-->>RP: 서명 / issuer / audience 검증 기준 제공 - RP->>RP: sid 또는 sub로 sessionId 탐색 - RP->>Store: destroy(sessionId) - RP->>RP: removeSessionBinding(sessionId) - RP-->>Baron: 200 OK - - Browser->>RP: GET /profile 호출 - RP-->>Browser: 루트 리다이렉트 또는 비로그인 응답 -```