This commit is contained in:
@@ -0,0 +1,119 @@
|
||||
# Back-Channel Logout 처리 시퀀스
|
||||
|
||||
이 문서는 `baron-sso-server-side-demo`가 Baron SSO로부터 `POST /backchannel-logout` 요청을 받았을 때 어떤 순서로 동작하는지 정리합니다.
|
||||
|
||||
## 개요
|
||||
|
||||
이 데모 앱은 Baron SSO가 전송한 `logout_token`을 수신하면, 다음 순서로 처리합니다.
|
||||
|
||||
1. 요청 본문에서 `logout_token`을 읽습니다.
|
||||
2. Baron이 서명한 토큰인지 JWKS로 검증합니다.
|
||||
3. `sid` 또는 `sub`를 기준으로 로컬 세션을 찾습니다.
|
||||
4. `express-session` 저장소에서 해당 세션을 삭제합니다.
|
||||
5. 세션 매핑을 제거하고 `200` 응답을 반환합니다.
|
||||
|
||||
## 시퀀스 다이어그램
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
autonumber
|
||||
participant Baron as Baron SSO
|
||||
participant RP as baron-sso-server-side-demo
|
||||
participant JWKS as Baron Back-Channel JWKS
|
||||
participant Store as express-session Store
|
||||
|
||||
Baron->>RP: POST /backchannel-logout\nlogout_token=<jwt>
|
||||
RP->>RP: logout_token 추출
|
||||
RP->>JWKS: JWKS 조회 후 서명 검증
|
||||
JWKS-->>RP: public key
|
||||
RP->>RP: iss / aud / events / nonce / jti 검증
|
||||
RP->>RP: sid 또는 sub로 세션 매핑 조회
|
||||
RP->>Store: sessionStore.destroy(sessionId)
|
||||
Store-->>RP: 삭제 완료
|
||||
RP->>RP: 세션 매핑 제거
|
||||
RP-->>Baron: 200 OK\n{ success: true }
|
||||
```
|
||||
|
||||
## 실제 구현 위치
|
||||
|
||||
- 요청 수신 및 처리 엔드포인트: [`backchannel-logout.js`](../backchannel-logout.js)
|
||||
- 라우트 등록과 세션 매핑: [`app.js`](../app.js)
|
||||
- 동작 설명: [`README.md`](../README.md)
|
||||
|
||||
## 동작 상세
|
||||
|
||||
### 1. 요청 수신
|
||||
|
||||
`app.js`에서 아래 라우트를 등록합니다.
|
||||
|
||||
```javascript
|
||||
app.post(
|
||||
'/backchannel-logout',
|
||||
backchannelLogoutManager.handleBackchannelLogout,
|
||||
);
|
||||
```
|
||||
|
||||
이 요청은 `application/x-www-form-urlencoded` 형식으로 전달되며, 본문에는 `logout_token`이 포함됩니다.
|
||||
|
||||
### 2. 토큰 추출
|
||||
|
||||
`backchannel-logout.js`는 `req.body.logout_token`을 읽어서 빈 값인지 확인합니다.
|
||||
|
||||
- 값이 없으면 `400 Bad Request`
|
||||
- 값이 있으면 다음 단계로 진행
|
||||
|
||||
### 3. JWT 검증
|
||||
|
||||
데모 앱은 Baron의 백채널 JWKS를 사용해 `logout_token`을 검증합니다.
|
||||
|
||||
검증 항목은 다음과 같습니다.
|
||||
|
||||
- 서명 검증
|
||||
- `iss` 일치
|
||||
- `aud`에 현재 RP `clientId` 포함
|
||||
- `nonce` 미포함
|
||||
- `events`에 back-channel logout 이벤트 포함
|
||||
- `sid` 또는 `sub` 존재
|
||||
- `jti` 존재 및 재사용 방지
|
||||
|
||||
### 4. 세션 탐색
|
||||
|
||||
로그인 성공 시 저장한 `sid` / `sub` 매핑을 이용해 대상 세션을 찾습니다.
|
||||
|
||||
우선순위는 다음과 같습니다.
|
||||
|
||||
1. `sid`로 탐색
|
||||
2. `sid` 매칭이 없으면 `sub`로 fallback
|
||||
|
||||
### 5. 세션 파기
|
||||
|
||||
매칭된 세션 ID가 있으면 `express-session` 저장소에서 직접 삭제합니다.
|
||||
|
||||
```javascript
|
||||
sessionStore.destroy(sessionId, callback);
|
||||
```
|
||||
|
||||
삭제 후에는 세션 ID와 `sid` / `sub` 매핑도 함께 제거합니다.
|
||||
|
||||
### 6. 응답 반환
|
||||
|
||||
정상 처리되면 `200 OK`와 함께 아래 응답을 반환합니다.
|
||||
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"destroyedSessionCount": 1
|
||||
}
|
||||
```
|
||||
|
||||
## 운영 관점 메모
|
||||
|
||||
- 이 데모는 백채널 로그아웃 외에도, 각 요청마다 Baron 세션을 재검증하는 경로를 별도로 가집니다.
|
||||
- `BARON_SESSION_VALIDATION_ENABLED=false`로 두면 재검증을 끄고 백채널 로그아웃만 확인할 수 있습니다.
|
||||
- Baron이 데모 앱에 직접 접근할 수 있어야 백채널 로그아웃이 성공합니다.
|
||||
|
||||
## 관련 파일
|
||||
|
||||
- [`backchannel-logout.js`](../backchannel-logout.js)
|
||||
- [`app.js`](../app.js)
|
||||
- [`README.md`](../README.md)
|
||||
Reference in New Issue
Block a user