비밀번호를 바꾸면 왜 모든 기기에서 로그아웃되는가
세션 관련 작업을 이어서 하다가, 원래 있던 구멍 하나를 발견해 막았다.
문제
비밀번호를 바꿔도 기존 세션이 그대로 살아 있었다.
이게 왜 위험한지는 시나리오로 보면 분명하다. 공용 PC에 로그인한 채로 나왔다는 걸 뒤늦게 깨닫고 비밀번호를 바꾼다. 그런데 그 PC의 세션은 멀쩡히 유지된다. 비밀번호를 바꾼 행위가 아무것도 해결하지 못한 것이다.
OWASP의 원칙은 명확하다 — 권한 수준이 바뀌는 모든 지점에서 세션 ID를 갱신하라.
규칙
두 경로를 다르게 처리했다.
경로 | 기존 세션 | 호출자 |
|---|---|---|
| 전부 삭제 | 같은 응답에서 새 세션 발급 |
| 전부 삭제 | 새 세션 없음 — 로그아웃 |
차이가 나는 이유는 단순하다. 비밀번호 변경은 이미 로그인한 사람이 하는 일이니 그 사람까지 튕겨낼 이유가 없다. 재설정은 비밀번호를 잊은 사람이 메일 링크로 들어오는 흐름이라, 애초에 로그인 상태가 아니다.
둘 다 auth/session/SessionInvalidationService를 거친다.
걸려 넘어진 지점
세션을 사용자 기준으로 찾아 지워야 하는데, 이건 FindByIndexNameSessionRepository가 principal name 인덱스로 해준다. 우리는 principal이 이메일이다.
Map<String, ? extends Session> sessions =
sessionRepository.findByPrincipalName(email);
여기에 함정이 있다. 이 인덱스는 세션이 security context를 담고 있을 때만 채워진다. security context 없이 세션만 만드는 로그인 경로가 하나라도 생기면, 그 세션은 인덱스에 안 잡히고 비밀번호를 바꿔도 조용히 살아남는다.
조용히 실패하는 종류의 버그다. 아무 에러도 안 나고, 그냥 안 지워진다.
그래서 PasswordSessionInvalidationIntegrationTests로 끝에서 끝까지 검증하도록 묶어뒀다. 앞으로 로그인 경로를 새로 추가하는 사람은 반드시 security context를 저장해야 한다. 안 그러면 이 테스트가 잡아준다.
정리
비밀번호 변경 → 전부 끊고, 나한테만 새로 발급
비밀번호 재설정 → 전부 끊고, 아무에게도 발급 안 함
새 로그인 경로를 추가한다면 security context 저장은 선택이 아니다
댓글
아직 댓글이 없습니다.