백채널 로그아웃 기능 추가

This commit is contained in:
2026-05-06 13:45:02 +09:00
parent 14bda89d10
commit 74a41e4475
3 changed files with 41 additions and 30 deletions

View File

@@ -48,6 +48,7 @@ docker-compose up --build
- `OIDC_REDIRECT_URI`: 콜백 URL - `OIDC_REDIRECT_URI`: 콜백 URL
- `BARON_API_BASE_URL`: Baron Backend/Public Gateway 기준 URL. 기본적으로 `OIDC_ISSUER_URL`에서 `/oidc`를 제거한 값을 사용합니다. - `BARON_API_BASE_URL`: Baron Backend/Public Gateway 기준 URL. 기본적으로 `OIDC_ISSUER_URL`에서 `/oidc`를 제거한 값을 사용합니다.
- `BARON_BACKCHANNEL_JWKS_URL`: Baron이 서명한 `logout_token` 검증용 JWKS URL. 기본값은 `<BARON_API_BASE_URL>/api/v1/auth/backchannel/jwks.json` 입니다. - `BARON_BACKCHANNEL_JWKS_URL`: Baron이 서명한 `logout_token` 검증용 JWKS URL. 기본값은 `<BARON_API_BASE_URL>/api/v1/auth/backchannel/jwks.json` 입니다.
- `BARON_SESSION_VALIDATION_ENABLED`: `false`로 두면 기존의 요청 시 Baron 세션 재검증을 끄고, Back-Channel Logout만으로 세션 종료를 확인할 수 있습니다. 기본값은 `true`입니다.
## 세션 종료 / 연동 해지 동작 ## 세션 종료 / 연동 해지 동작

11
app.js
View File

@@ -33,7 +33,9 @@ app.set('views', path.join(__dirname, 'views'));
app.use(express.urlencoded({ extended: false })); app.use(express.urlencoded({ extended: false }));
const sessionStore = new session.MemoryStore();
const sessionMiddleware = session({ const sessionMiddleware = session({
store: sessionStore,
name: 'baron.demo.sid', name: 'baron.demo.sid',
secret: process.env.SESSION_SECRET || 'demo-session-secret', secret: process.env.SESSION_SECRET || 'demo-session-secret',
resave: true, resave: true,
@@ -306,6 +308,8 @@ async function setupOIDC() {
const redirectUri = process.env.OIDC_REDIRECT_URI || 'http://localhost:3000/callback'; const redirectUri = process.env.OIDC_REDIRECT_URI || 'http://localhost:3000/callback';
const backchannelJwksUrl = deriveBackchannelJwksUrl(); const backchannelJwksUrl = deriveBackchannelJwksUrl();
const backchannelJwks = createRemoteJWKSet(new URL(backchannelJwksUrl)); const backchannelJwks = createRemoteJWKSet(new URL(backchannelJwksUrl));
const sessionValidationEnabled =
String(process.env.BARON_SESSION_VALIDATION_ENABLED || 'true').toLowerCase() !== 'false';
console.log(`OIDC Issuer 조회: ${issuerUrl}`); console.log(`OIDC Issuer 조회: ${issuerUrl}`);
console.log(`백채널 로그아웃 JWKS 주소: ${backchannelJwksUrl}`); console.log(`백채널 로그아웃 JWKS 주소: ${backchannelJwksUrl}`);
@@ -322,8 +326,10 @@ async function setupOIDC() {
clientId, clientId,
redirectUri, redirectUri,
authorizationEndpoint, authorizationEndpoint,
sessionValidationEnabled,
}); });
if (sessionValidationEnabled) {
app.use(async (req, res, next) => { app.use(async (req, res, next) => {
const skipPaths = new Set(['/login', '/callback', '/logout', '/backchannel-logout']); const skipPaths = new Set(['/login', '/callback', '/logout', '/backchannel-logout']);
if (skipPaths.has(req.path)) { if (skipPaths.has(req.path)) {
@@ -356,6 +362,9 @@ async function setupOIDC() {
return res.redirect('/'); return res.redirect('/');
} }
}); });
} else {
console.log('[시스템] Baron 세션 재검증 미들웨어를 비활성화했습니다. 백채널 로그아웃 테스트 전용 모드입니다.');
}
app.get('/', (req, res) => { app.get('/', (req, res) => {
res.render('index', { user: req.session.user }); res.render('index', { user: req.session.user });
@@ -480,7 +489,7 @@ async function setupOIDC() {
jwks: backchannelJwks, jwks: backchannelJwks,
}); });
const result = await destroySessionsForLogout(sessionMiddleware.store, claims); const result = await destroySessionsForLogout(sessionStore, claims);
console.log('[백채널 로그아웃] 처리 완료', { console.log('[백채널 로그아웃] 처리 완료', {
sid: claims.sid || '(없음)', sid: claims.sid || '(없음)',
sub: claims.sub || '(없음)', sub: claims.sub || '(없음)',

View File

@@ -11,6 +11,7 @@ services:
- OIDC_CLIENT_ID=f5cdd938-a3ae-4e47-ab83-4c13e59949f5 - OIDC_CLIENT_ID=f5cdd938-a3ae-4e47-ab83-4c13e59949f5
- OIDC_REDIRECT_URI=http://localhost:3333/callback - OIDC_REDIRECT_URI=http://localhost:3333/callback
- BARON_API_BASE_URL=https://sso-test.hmac.kr - BARON_API_BASE_URL=https://sso-test.hmac.kr
- BARON_SESSION_VALIDATION_ENABLED=false
extra_hosts: extra_hosts:
- "localhost:host-gateway" - "localhost:host-gateway"
networks: networks: