조급하면 모래성이 될뿐

HttpOnly 쿠키로 토큰 관리 & 재발급 로직 구현 본문

TroubleShooting/Yapp

HttpOnly 쿠키로 토큰 관리 & 재발급 로직 구현

Pawer0223 2023. 8. 7. 02:57

결론

- accessToken, refreshToken 모두 httpOnly 쿠키로 응답했다. (XSS 공격 방지)

- 하지만 refreshToken을 통한 재발급 로직을 구현하기 위해서 httpOnly옵션의 accessToken 쿠키는 서버에서 추가적으로 신경 써주어야 한다. (FE팀에서 조차 accessToken에 접근할 수 없기 때문에 토큰 만료시점을 알 수 없다..)

 

장점

- XSS 공격 방지할 수 있음.

 

단점

- 쿠키 관리신경 써야 함

- 서버 로직이 복잡해질 수 있음 (비교적..)

 

직면한 문제 1

accessToken 쿠키 만료시간.

 

처음에는 accessToken 쿠키 만료시간을 JWT와 동일하게 주었다. 프론트에서는 토큰 만료 여부를 서버응답에 의존하기 때문에 쿠키가 사라지게 되면 서버에서는 JWT가 만료되었는지 판단할 수 없다.

 

때문에 accessToken 쿠키의 만료시간을 지정하지 않고 세션 쿠키로 사용했다.

 

직면한 문제 2

세션쿠키를 사용하다보니 적절한 시점에 쿠키를 삭제해주지 않는다면 만료된 토큰을 가진 쿠키가 계속 남아있게 된다. 이 때문에 토큰 재발급 시 무한호출되는 문제가 있었다.

 

토큰 재발급 로직은 아래와 같이 처리된다.

 

여기서 3번. 재발급 요청 시 refreshToken 또한 만료된 경우가 존재할 수 있다. 이 경우 만료된 JWT를 가진 쿠키가 계속 남아있다면 재발급이 불가능한 상태로 모든 API에서는 계속 토큰 만료를 확인하고, 응답하면서 무한호출이 발생한다.

 

 

따라서 재발급이 불가능한 경우에는 accessToken 쿠키를 삭제해줘야 했다.

 

직면한 문제 3

쿠키발급 시 domain 값을 api 호출을 할 수 있는 상위도메인이 될 수 있도록 해야 한다. 이유는 웹 브라우저에서 네트워크 요청 시 쿠키를 포함시키기 위해서다.

 

웹 브라우저는 쿠키 도메인값의 하위 url인 경우에만 요청에 쿠키를 포함시킨다. 즉, 쿠키도메인이 상위일때만 요청에 쿠키를 포함 시킨다..

(MDN 참조)

 

- 최초 도메인 값을 신경 쓰지 못했다.

- 그랬더니 배포 후에 로그인 쿠키가 발급해도, FE 서버에서 쿠키가 요청에 포함되지 않았다.

- FE에서 최상위 도메인을 가지고 있는데(service.com) 서버에서 쿠키 발급 시 도메인 값을 지정해주지 않다 보니 쿠키 도메인 값이 요청도메인으로 발급되었다. (domain=service.com)

- api 서버 도메인은 api.service.com이다.

- 그러나 하위도메인에 접근하기 위해서는 쿠키 도메인 앞에. 을 prefix로 붙어주어야 인식한다. (스택오버 플로우 참조)

- .service.com 도메인을 가지는 쿠키를 발급해 주면 된다.

 

서버 처리방식

- filter에서는 accessToken 쿠키를 검증한다.

- 인증이 필요 없는 API가 있을 수도 있다. 처음에는 이 경우는 토큰을 검증하지 않았다. 그러나 FE로직을 이해하니, 만료되면 이전 API요청을 다시 호출하기 때문에 적용해도 괜찮았다. 유저는 토큰이 만료되었는지 알 수 없다. (직접 개발자 도구를 까보지 않는 이상..)

 

ex) 인증이 필요 없는 API 요청 시 498을 응답한다면?

- 토큰 재발급 요청

- 성공 -> 유효한 토큰으로 다시 요청

- 실패 -> 만료된 토큰을 가진 쿠키 삭제 -> 서버에서 쿠키자체가 없으면 비로그인 유저로 판단한다.(인증이 필요 없음)

 

- 재발급 요청 API에서는 토큰 만료시간을 확인하지 않는다. 이 API에서 토큰 만료를 응답하면 프론트 로직에 의해 무한호출이 된다.

- 재발급 요청 시 refreshToken 이 유효하지 않는 경우에는 accessToken을 삭제한다. (maxAge=0으로 발급)

반응형

'TroubleShooting > Yapp' 카테고리의 다른 글

Kotlin AOP 따라해보기  (0) 2023.09.21
JWT 로그인 구현  (0) 2023.07.24
카테고리 목록 캐싱 처리하기  (0) 2023.07.12