본문 바로가기

프로젝트/라꾸라꾸 프로젝트

[JWT] Access Token 재발급 문제

프론트와의 커뮤니케이션

처음에는 어디까지가 프론트의 부분이고, 어디까지가 백엔드의 부분인지 정확하게 알지 못했다. 그냥 api 문서를 보고 어떤 것들을 주고 받는지만 알았다. 하지만 스프링 시큐리티 부분에서 진정한 프론트와의 커뮤니케이션을 하게 되었고 개발을 할 때 프론트가 어디까지 할 수 있는 지 알고 있어야 겠다는 깨달음을 얻었다.

 

🧐Access Token 관련 재발급 문제 

백엔드에서 로그인 기능을 구현하기 위해 JWT를 이용하여 access 토큰을 발행하고 refresh 토큰을 이용하여 accessToken을 재발급하는 방법으로 accessToken의 만료로 인한 재로그인의 불편함을 줄이고자 했다. 

이 글은 Access Token 재발급 문제에 대해서 어떻게 커뮤니케이션을 했는지에 대한 과정을 담고 있다. 

 

문제 상황 1 = 백엔드 내부 로직? vs 프론트에서 처리? 에 대한 고민

(1) 

그냥 재발급 api만 만들고 이것을 어떻게 사용자가 요청해야할 지 고민을 덜 한 것 같다. 다시 생각해보니 직접 사용자가 재발급 요청을 직접 보내는 경우를 본 적이 없는 것 같아서 프론트가 알아서 자동으로 해주는 건지, 백엔드 내부에서 처리해야 하는지 헷갈렸다. 하지만 이 고민이 RestApi가 stateless이라는 특성을 가지고 있다는 것을 간과한 고민이라는 것을 깨달았다. (역시 기본 개념이 매우 중요하다는 것을 깨닫게 되었다)

 

과적으로 백엔드 내부에서 처리하는 것이 아닌 프론트에서 요청을 보내는 과정이 필요하다는 것을 알게 되었다. 

→ 이후 프론트가 어떻게 처리하는지 프론트 입장에서 구글링하기 시작했다.

 

(2)

구글링한 결과 프론트 내부에서 리프레쉬 토큰의 유효시간을 계산해서 자동으로 백엔드에게 재발급 요청을 한다는 것을 발견했다. 이것을 보고 재발급 요청은 프론트에서 처리하는 것이라고 확정하게 되었다.

그리고 프론트에게 요청을 해당 링크를 보내고 자동으로 엑세스 토큰 재발급을 할 수 있는지 여쭤봤다.

 

문제 상황 2  = 자동 재발급 구현 어렵

(1) 처음부터 토큰 방식에 대해서 미리 여쭤봤어야 하는데 토큰 적용이 늦어지는 바람에 프론트에게 늦게 연락하게 되었다.

(다음부터는 처음부터 꼼꼼하고 완벽하게 API 문서(응답 메시지, requestBody 내용)을 작성하고 로그인 방식에 대해서 프론트와 처음부터 논의해야겠다고 깨달았다ㅠ)

그리고 엑세스 토큰 만료 시간을 계산하여 토큰 만료 응답을 받기 전에 자동적으로 요청을 하여 엑세스 토큰을 요청하는 방식이 아닌 엑세스 토큰 만료와 리프레시 토큰 만료 응답을 구분하여 엑세스 토큰 만료 응답을 받으면 재발급 요청을 보내고 리프레쉬 토큰 만료 응답을 받으면 로그인 페이지로 넘어가는 방향으로 가게 되었다.

 

- 참고링크 

https://maruzzing.github.io/study/rnative/axios-interceptors로-토큰-리프레시-하기/

+“쿠키가 보안이 낫다고 해서 local, async, session등의 storge대신 아마 react-cookie나 univeral-cookie를 사용해서 쿠키에 저장하는 방식으로 할 것 같습니다.”라고 말씀하셨다.

 

 

😎프론트 엔드의 질문에 대한 답변

나도 이제 질문을 받게 되었으며 대답을 할 수 있게 되었다! 꺅

그 동안 백리드 분들이 기술적인 질문에 대한 답변을 하실 때마다 ‘멋있고 대단하시다.. 나는 언제쯤 저런 경지가 될까?..’ 라는 생각을 했는데 이제 나도 기술적인 질문에 대한 답변을 할 수 있게 되었다. (뿌듯)

나에게 해주신 소중한 질문 내용과 나의 답변은 다음과 같다.💚

 

(질문 1) 로그인 한 뒤, header의 'Authorization'부분에 accesstoken을 넣어주는 코드를 넣을 예정인데, 현재 헤더에 이 'Authorization'부분이 있는게 맞나요?

 

  😎답변 = 포스트맨으로 'Authorization'부분에 accesstoken을 넣어서 로그인된 유저를 받아오는 것까지 구현완료했습니다!

 

(질문 2) access token 만료 후, refresh token을 통해 access token을 재발급 받는 api에 email이 들어가있는 이유가 있을까요? 프론트단에서는 refresh token만으로도 가능한 것 같아서요!

 

  😎답변 = 재발급을 위해 백으로 요청을 보내면 유저의 아이디(Email)을 키로 하는 데이터가 존재하는지 확인하여 RefreshToken의 유효성을 검증하기 위함입니다!

 

(질문 3) token들이 하나라도 만료된 경우에는 error code가 401인데, 이 중 access token이 만료된 경우의 코드를 알 수 있을까요? 저번에 문의주실때 access token은 프론트단에서 알아서 자동갱신이 된다고 하셨는데 계속 찾아보니 아마 그 갱신도 refresh token을 통해 코드를 짜서 진행시켜야하는 것 같습니다! 즉, refresh token마저 만료된 경우에는 로그인을 재진행하도록 랜딩페이지로 이동시킬 계획입니다 (그래서 같은 401이라도 무엇이 만료되었는지에 따라 분기해야해서 구체적인 에러 코드가 필요해요!)

 

  😎답변 = 현재 프론트에서 자동 갱신을 하여 요청을 보낸다고 생각하여 access token과 refresh token 토큰의 만료 에러 처리 응답이 똑같게 한 상황인데 보아하니 자동 갱신을 하지 않는 것으로 구현하기 위해서는 구분해야되는군요! 알려주셔서 감사합니다! 구분해서 완료되면 바로 알려드리겠습니다!

 

 

(질문 4) 구글링해보니 access token은 시간 단위 / refresh token은 주 단위의 유효기간을 가지는 것 같은데 맞나요! 만약 이 둘의 유효기간이 거기서 거기라면 그냥 재발급없이 바로 로그인을 유도하는 것도 괜찮은 방법이기는 합니다 

 

  😎답변 = 보통의 경우 Access Token 만료기간 : 30분 ~ 1시간 Refresh Token 만료기간 : 3일 ~ 1달“이라고 알고 있습니다! 또한 엑세스 토큰의 유효 기간을 길게한다면 보안상 문제가 생겨서 시간을 길게하는 것은 어려울 것 같습니다. 

 

이렇게 질의응답을 받고 엑세스 토큰의 만료 응답과 리프레쉬 토큰의 만료 응답을 구분하여 코드를 고쳤다.

바꾼 응답 내용은 다음과 같다.

{
    "status": "FORBIDDEN",
    "code": "TOKEN_VALIDATE_FAILURE",
    "message": "access 토큰이 만료되었습니다."
}
{
    "status": "BAD_REQUEST",
    "code": "REFRESHTOKEN_EXPIRED",
    "message": "refresh 토큰이 만료되었습니다.",
    "date": "2022-08-01T22:30:33.870019"
}

 

 

👍이렇게 프론트와 커뮤니케이션을 하면서 알아본 결과 에러 코드와 응답 메시지를 (문자 그대로)기반으로 프론트에서 로직을 짜는 것을 알게 되었다. 그냥 응답의 내용만 중요한 것이라고 생각하여 응답 메시지의 형식이 약간 달라진 것들을 바로 수정하지 않았다.ㅠ

하지만 응답 메시지 글자 자체도 중요하다는 것을 깨닫고 응답 메시지의 수정 사항이 있으면 바로바로 고치고 프론트에게 말씀드려야겠다.