Skip to content

[oauth] IdP 로그아웃 및 비밀번호 변경 시 세션 무효화 - #437

Open
ZaMan0806 wants to merge 2 commits into
feature/oauth-consent-screenfrom
feature/oauth-logout
Open

[oauth] IdP 로그아웃 및 비밀번호 변경 시 세션 무효화#437
ZaMan0806 wants to merge 2 commits into
feature/oauth-consent-screenfrom
feature/oauth-logout

Conversation

@ZaMan0806

Copy link
Copy Markdown
Collaborator

개요

SSO 로드맵 우선순위 2 — 로그아웃 및 전파의 최소 구현과, 우선순위 5에서 떼어낸 "비밀번호 변경 시 세션 무효화" 를 함께 처리합니다. 로드맵이 이 둘을 묶어 권장한 항목입니다.

스택 PR입니다. base는 #436입니다.

본문

왜 필요한가

로그아웃 기능이 아예 없었습니다. 세션 쿠키가 만료(기본 8시간)될 때까지 유지되어 공용 PC에서 특히 위험합니다.

그리고 비밀번호를 바꿔도 기존 IdP 세션이 그대로 살아있었습니다. 비밀번호 변경은 계정 탈취 대응인 경우가 많은데, 세션이 남아 있으면 공격자가 기존 쿠키로 계속 새 인가를 받을 수 있습니다. 기존 코드는 refresh token만 지우고 있었습니다.

변경 내용

1. POST /v1/oauth/logout

세션을 삭제하고 쿠키를 즉시 만료시킵니다. 세션이 이미 없어도 동일하게 204를 반환합니다 — 존재 여부를 알려주면 쿠키 값만 가진 쪽에 유효한 세션인지 판별할 단서를 주게 되고, 사용자 입장에서 결과는 어차피 같습니다.

2. IdpSessionCookieFactory 도입

브라우저는 name/path/domain이 모두 일치해야 기존 쿠키를 덮어씁니다. 발급과 만료를 각각 따로 조립하면 속성이 어긋나는 순간 로그아웃이 조용히 실패하므로, 두 형태를 같은 자리에서 만들도록 모았습니다.

3. 비밀번호 변경 시 세션 전체 삭제

역방향 조회를 위해 IdpSessionRedisEntity.email@Indexed를 추가했습니다. 같은 모듈의 OauthRefreshTokenRedisEntity가 이미 쓰는 방식과 동일합니다.

검증

  • 신규 테스트 8건 포함 153건 통과, ktlintCheck build 통과
  • 뮤테이션 테스트:
    • 세션 무효화 제거 → 1건 실패
    • 만료 쿠키 Max-Age=0 제거 → 2건 실패
    • 만료 쿠키 Path 불일치 → 1건 실패

Path 검증은 처음에 shouldContain "Path=/" 로 짰다가 뮤테이션이 살아남는 것을 보고 고쳤습니다. Path=/v1도 그 부분 문자열을 포함해 통과해버려서, 속성 단위로 잘라 정확 비교하도록 바꿨습니다.

알려진 한계

이미 발급된 access token은 만료 전까지 유효하므로, 각 SP는 자기 토큰이 만료될 때까지(기본 1시간) 로그인 상태로 보입니다. 완전한 전파(back-channel logout)는 SP별 backchannel_logout_uri 등록이 필요해 SP가 여러 개로 늘어난 뒤 판단하는 것이 낫다고 보고 별도 과제로 남겼습니다.

절충안으로 access token 만료를 15~30분으로 줄이면 로그아웃 후 그 시간 내에 모든 SP가 자연스럽게 수렴합니다(OAUTH_ACCESS_TOKEN_EXPIRATION).

프론트엔드 필요 작업

  • 로그아웃 버튼 → POST /v1/oauth/logout (쿠키가 실려야 하므로 credentials 포함)

로그아웃 기능이 없어 세션 쿠키가 만료(기본 8시간)될 때까지 유지되던
공백을 메운다. 공용 PC에서 특히 문제가 된다.

- POST /v1/oauth/logout 추가. 세션을 삭제하고 쿠키를 즉시 만료시킨다.
  세션이 없어도 동일하게 204를 반환해, 쿠키 값만 가진 쪽에 유효한
  세션인지 판별할 단서를 주지 않는다.
- 쿠키 발급/만료를 IdpSessionCookieFactory로 모았다. 브라우저는
  name/path/domain이 일치해야 기존 쿠키를 덮어쓰므로, 두 형태를 따로
  조립하면 속성이 어긋나는 순간 로그아웃이 조용히 실패한다.
- 비밀번호 변경 시 해당 계정의 IdP 세션을 전부 삭제한다. 기존에는
  refresh token만 지워, 탈취된 세션 쿠키로 새 인가를 계속 받을 수 있었다.
  역방향 조회를 위해 email에 @indexed를 추가했다.

이미 발급된 access token은 만료 전까지 유효하므로, 각 SP는 자기 토큰이
만료될 때까지 로그인 상태로 보인다. 전파(back-channel logout)는 별도 과제다.
@ZaMan0806
ZaMan0806 added this pull request to stack #434 September 9, 2026 14:26

@pr-agent-demo pr-agent-demo Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Overview:
    IdP 세션 로그아웃 API를 추가하고, 세션 쿠키 발급/만료 로직을 IdpSessionCookieFactory로 통일했습니다. 또한 비밀번호 변경 시 해당 계명의 IdP 세션을 모두 삭제하도록 했습니다.

  • Intent:
    공용 PC 등 환경에서 세션이 오래 유지되는 문제를 줄이고, 계정 탈취 후에도 기존 세션 쿠키로 계속 인가되는 것을 막기 위한 보안 강화를 목적으로 합니다.

  • Risk:
    전반적으로 보안 관련 변경이라 중도~높은 주의가 필요합니다. 특히 로그아웃 API의 CSRF 안전성, 쿠키 속성 불일치로 인한 로그아웃 실패 가능성, 그리고 로그아웃 시에도 남아 있는 refresh token/access token의 영향 범위를 검토해야 합니다. 비밀번호 변경 시 email 기준 세션 삭제 로직의 정확성도 확인이 필요합니다.


0 inline comment(s)

@github-actions github-actions Bot added the waiting for review:검토 대기 확인을 대기하고 있습니다 label Sep 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

waiting for review:검토 대기 확인을 대기하고 있습니다

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant