진형주@hyoungjoojin · Sep 13, 2026Claude Code(으)로 작성

비밀번호를 바꾸면 왜 모든 기기에서 로그아웃되는가

세션 관련 작업을 이어서 하다가, 원래 있던 구멍 하나를 발견해 막았다.

문제

비밀번호를 바꿔도 기존 세션이 그대로 살아 있었다.

이게 왜 위험한지는 시나리오로 보면 분명하다. 공용 PC에 로그인한 채로 나왔다는 걸 뒤늦게 깨닫고 비밀번호를 바꾼다. 그런데 그 PC의 세션은 멀쩡히 유지된다. 비밀번호를 바꾼 행위가 아무것도 해결하지 못한 것이다.

OWASP의 원칙은 명확하다 — 권한 수준이 바뀌는 모든 지점에서 세션 ID를 갱신하라.

규칙

두 경로를 다르게 처리했다.

경로

기존 세션

호출자

PATCH /auth/password (변경)

전부 삭제

같은 응답에서 새 세션 발급

/auth/password-reset/* (재설정)

전부 삭제

새 세션 없음 — 로그아웃

차이가 나는 이유는 단순하다. 비밀번호 변경은 이미 로그인한 사람이 하는 일이니 그 사람까지 튕겨낼 이유가 없다. 재설정은 비밀번호를 잊은 사람이 메일 링크로 들어오는 흐름이라, 애초에 로그인 상태가 아니다.

둘 다 auth/session/SessionInvalidationService를 거친다.

걸려 넘어진 지점

세션을 사용자 기준으로 찾아 지워야 하는데, 이건 FindByIndexNameSessionRepository가 principal name 인덱스로 해준다. 우리는 principal이 이메일이다.

Map<String, ? extends Session> sessions =
    sessionRepository.findByPrincipalName(email);

여기에 함정이 있다. 이 인덱스는 세션이 security context를 담고 있을 때만 채워진다. security context 없이 세션만 만드는 로그인 경로가 하나라도 생기면, 그 세션은 인덱스에 안 잡히고 비밀번호를 바꿔도 조용히 살아남는다.

조용히 실패하는 종류의 버그다. 아무 에러도 안 나고, 그냥 안 지워진다.

그래서 PasswordSessionInvalidationIntegrationTests로 끝에서 끝까지 검증하도록 묶어뒀다. 앞으로 로그인 경로를 새로 추가하는 사람은 반드시 security context를 저장해야 한다. 안 그러면 이 테스트가 잡아준다.

정리

  • 비밀번호 변경 → 전부 끊고, 나한테만 새로 발급

  • 비밀번호 재설정 → 전부 끊고, 아무에게도 발급 안 함

  • 새 로그인 경로를 추가한다면 security context 저장은 선택이 아니다

댓글

아직 댓글이 없습니다.