[Spring] JWT(Access_Token & Refresh_Token)

한호성·2022년 12월 5일
0

글의목적

이전에 프로젝트에서 JWT(JSON Web Token)을 많이 사용하였다.
JWT의 기본 개념과 왜 Session 방식의 대체로 사용되는지 알아볼 것이다.
JWT로 만들어지는 Access_Token & Refresh_Token의 개념과 활용에 대한 글이다.

JWT 개념정리

JWT란 웹표준 (RFC 7519)으로써, 두 개체에서 JSON 객체를 사용하여 가볍고 자가수용적인 방식으로 정보를 안정성 있게 전달한다.
#cf) 여기서 "자가수용적"이란 JWT 가 필요한 모든 정보를 자체적으로 갖고있다는 것을 의미 (Signature 검증영역 존재)

만들어지는 방식

JWT 는 3가지 영역으로 나뉜다.
Header(헤더) , payload(내용) , signature(서명) 

header = base64_encode(headerJSON)
payload = base64_encode(payloadJSON)
Signature = base64_encode(HMAC_SHA256(header+"."+payload,secret))

JWT = header + "." + payload+"."signature

Session 과의 비교

세션방식의 이해

  1. Client(Browser) 로그인
  2. 서버의 세션 메모리에 해당 정보 저장 (고유의 세션ID 생성 및 쿠키로 반환)
  3. Client(Browser) 쿠키를 쿠키저장소에 가지고 있음
  4. 다음 요청에 session정보 갖고 있는 쿠키를 다시 재전송
  5. 서버는 session id를 확인하고 로그인한 상태의 요청이란걸 인식하여 걸맞게 Response한다.

세션 방식의 단점

  • 저장공간의 용량
    세션은 서버의 메모리 내부에 저장이 된다. 유저가 많아지면 많아질 수록 세션의 데이터가 많아지면서 메모리 부하가 생길 수 있다.
  • 확장성의 문제
    서비스의 규모가 커져서 분산 서버를 해야할 때, 세션을 분산시키는 기술을 따로 설계해야 한다.
    - 각각의 서버가 존재할 경우, 세션도 분산되어 저장되어 있고, 해당 요청이 세션정보가 어느 서버에 존재하는 세션인지 알고 해당 요청을 맞는 서버에 보내는 방식
    - 세션을 따로 DB에 저장하여 각 서버에서 DB에 접근해서 Session을 확인하는 방식

JWT의 활용 (Access Token , Refresh Token)

JWT을 활용할 때,보통 Access Token 과 Refresh Token을 활용한다.

난 이전 프로젝트를 진행할 때, Access Token 만을 활용하였고, 유효시간 또한 마음대로 하루로 정하였다. 이는 Access Token 탈취 됬을 때, 보안적으로 굉장히 위험한 방식이였다.

이런 위험을 최소화 하기 위해서 사용하는 방식은 다음과 같다.

  1. Access Token : 유효시간을 짧게 가져간다.
  2. Refresh Token : 유효시간을 길게 가져간다.

즉, Access Token이 탈취되더라도 자원에 접근할 수 있는 시간이 적기 때문에, 쓸모없는 토큰이 되는 것이다. Refresh Token은 Access Token을 재발급하기 위한 용도로, DB에 따로 저장한다.

만약 내가 저장한다면, Redis에 저장하며 읽기,쓰기 속도에 유리함을 줄 것 같고, TTL(Time to Live)을 지정하여, 알아서 삭제될 수 있도록 설정해줄 것 같다.

우선 JWT를 활용하였을 때, 자체적으로 유저정보가 담겨 있기 때문에, DB에 조회를 하지 않아도 된다는 장점이 있고, 서버가 여러대일 때의 세션 문제를 해결하는 방식이 되었다.

-> 이렇게 JWT 공부를 하고 내 코드를 보았는데, 나는 유저의 정보를 갖고 있음에도, DB에 해당 유저 데이터가 있는지 체크하는 코드가 존재하였다. 이런 식으로 코드를 짠다면, JWT의 장점 중 하나를 의미없게 만드는 방식이라고 생각한다. 수정할 필요가 있다.

작동순서

다음으로 Access Token 과 Refresh Token이 어떤 방식의 순서로 작동하는지 알아보자

다음 그림 4번 과정에서

로그인 성공한 Client에게 Access Token 과 Refresh Token을 전달하는 것을 확인할 수 있다.

Refresh Token을 사용자에게 어떻게 제공할 것인가에 대한 여러가지 의견이 있어서 작성해 본다.

카카오는 재작년 Refresh 토큰을 클라이언트에게 반환하는 것을 보안상의 이유로 막았고, 추가의 인증과정을 통해 Refresh token을 발급받도록 변경하였다.

Refresh Token을 좀 더 보안상 안전하게 저장하고 관리할 것인지에 대해 이야기가 많다. Refresh Token은 유효기간이 대체적으로 길기 때문에 탈취당하면 보안의 위험성이 커지기 때문이다.

Refresh Token을 Client에게 어떤방식으로 내려줄 것인가 그리고 어떻게 Client에서 보관할 것인가 두 가지가 큰 이슈인 거 같다.

지금 내 생각으로는, Client 에 저장할 때에는, HttpOnly와 Secure 설정이 된 쿠키에 저장하고, Client에 내려줄 때에는, RefreshToken이 저장된 DB의 (Index or Primary key )를 암호화해서 넣어두고, Refresh Token으로 Access Token 발급할 때, 복호화해서 Refresh Token이 유효한지 확인할 것 같다. 또, Refresh Token을 한번 사용했다면 다시 만들어서 db에 새로 저장하고 새로 내려줄 것 같다.

Reference

https://llshl.tistory.com/32
https://doogle.link/jwt-%ED%98%B9%EC%9D%80-oauth2-%EC%9D%98-refresh-%ED%86%A0%ED%81%B0%EC%9D%84-%EC%96%B4%EB%94%94%EB%8B%A4-%EC%A0%80%EC%9E%A5%ED%95%B4%EC%95%BC-%ED%95%A0%EA%B9%8C/

profile
개발자 지망생입니다.

0개의 댓글