회사 개발자 동료분들 중 한 분께서 로그아웃을 했음에도 자동으로 로그인이 되었다는 이야기로 문제가 시작되었습니다.
네트워크 탭을 확인해보니 로그아웃을 했음에도 refresh 요청이 전달되었고
로그인 유지가 이뤄지고 있었는데요.
원하지 않는 로그인 유지가 이뤄지게 된다면 제 3자가 유저의 계정을 사용해
범죄를 저지르거나 피해를 입힐 수 있는 보안 문제와 직결되어 해결이 시급했습니다.
우선 현 문제를 파악했으니 문제 해결을 위한 프로세스를 크게 2단계로 확립해봤어요.
1) 문제 해결 프로세스
1단계로는 임시로 refresh 요청 시, 백엔드에서 유저 토큰을 비교해 만료된 token이라면 오류를 보내 로그인을 막고
만료되지 않은 token이라면 그대로 로그인을 유지할 수 있도록 처리해달라고 부탁드렸습니다.
2단계로 refresh token이 언제 호출되어지는지, 어디서 호출되어지는지 파악 후
문제가 발생하는 코드를 수정하면 됐습니다.
이제 해결만 하면 되겠네요. 쉬운데요?
왜 refresh는 멋대로 되었던 걸까?
기존 코드에는 백엔드로부터 만료일과 만료 시간을 받아
현재 시간과 비교를 통해 만료 시간이 10분 이하가 된다면
refresh 요청을 보내게 처리하고 있었습니다. 그런데 왜 refresh가 멋대로 동작할까요?
코드를 살펴본 결과, 백엔드에서 설정한 access token의 만료시간과
프론트에서 설정한 access token의 만료시간이 다르다는 점을 알았습니다.
또한 백엔드로부터 토큰 만료 시간도 넘어오지 않았고
클라이언트에서도 2시간이라는 시간을 상수 데이터로 만들어 사용하고 있었는데요.
시간을 변수로 관리하다보니 원하는 시점에
refresh 요청이 이뤄지지 않아 유저는 로그아웃을 했지만 클라이언트에서
일정 시점이 되면 refresh 요청이 이뤄지고 로그인이 되는 문제가 발생했던거였네요.
문제 해결에 접근하기 위한 프로세스
login api와 refresh api 요청 시, 기존에 응답인 access token 이외에
acccess token의 만료시간도 추가를 해달라고 요청을 드렸습니다.
또한 기타 다른 상황을 고려하여 만료시간 10분 전에 요청을 보내는 것은 유지를 하기로 했어요.
Refresh를 위한 시간 설정 방법
서버에서 지정한 토큰 만료 시점은 2시간마다 한 번씩이므로
클라이언트에서는 토큰 만료 전, 1시간 50분마다 refresh 요청을 보내줘야 했습니다.
요청을 보내기 위한 시간은 Date 객체를 사용해 변수로 할당했는데요,
1) 현재 시간과 2) 토큰 만료시간을 ms로 변환했습니다.
//토큰 유효시간(ms) = 토큰 만료시간(2시간) - 현재 시간
const validTime = tokenExpirationTimeInMs - currentTimeInMs;
이제 setTimeout에 사용할 시간을 구할 차례입니다.
저는 2시간에서 10분을 뺀 1시간 50분의 값이 필요하므로
10분을 의미하는 변수를 설정해줬습니다.
const TEN_MINUTES = 10 * 60 * 1000;
이제 서버와 클라이언트의 토큰 만료 시간을 일치시켜줄 수 있게 되었습니다.
하지만 다른 문제가 발생했는데요, 다음 파트로 만나보도록 하겠습니다!
'Error Handling' 카테고리의 다른 글
한 탭에서의 로그아웃이 다른 탭에서는 미적용된다? (0) | 2024.03.28 |
---|---|
storage로 관리하던 token, cookie로 넘기자 (0) | 2024.03.27 |
D3 요소가 연속 렌더링 되는 경우 (0) | 2023.10.05 |
배포 후 naver Maps에서 발생하는 에러 (0) | 2023.04.03 |
Firebase domain 설정 error (0) | 2023.03.27 |