Spring Security
는 다양한 로그인 방식들을 지원한다.
기본적인 폼 기반 로그인부터, 다른 웹서비스의 계정을 통한 OAuth 인증 로그인, JWT 토큰을 이용한 인증 로그인 등이 있다.
이번 프로젝트에서는 JWT 로그인을 구현할 것이므로, JWT가 무엇이고 왜 로그인(인증)할 때 이용하는지에 대해 다뤄보기로 한다.
JWT
는 JSON Web Token
의 약자로, 웹 어플리케이션에 사용자 인증과 데이터 교환에 사용되는 토큰 인증 방식이다.
토큰은 세 부분으로 구성되며 다음과 같은 특징을 갖고 있다.
Header
- 토큰의 타입과 사용하는 암호화 알고리즘 정보 포함.
Payload
- 토큰에 담길 클레임 정보를 포함
- 클레임은 사용자의 정보들을 포함 가능
Signature
- 헤더와 페이로드를 인코딩한 후, 비밀 키를 사용하여 생성되는 값
- 서명을 통해 토큰 변조 여부 확인 가능
- 토큰 기반의 인증 방식으로, 서버에서 세션 관리할 필요 없음.
- 토큰은 클라이언트에서 저장되기에, 서버 간의 상태 공유가 필요 없음.
만약 RESTful API 방식의 프로젝트를 진행중이라면, JWT는 적합한 인증 방식라고 할 수 있다.
이제 서버와 클라이언트를 기준으로 인증 및 인가 과정에 대해 알아보자.
- 클라이언트: 로그인 정보 보냄
- 서버: 인증 완료(DB 조회) 시 토큰 발급
- 서버: 클라이언트로 토큰 보냄
- 클라이언트: 응답받은 토큰 저장.
- 클라이언트: 저장된 토큰과 함께 API 요청
- 서버: 검증 후 응답 보냄
여기까지가 이전 프로젝트에서 다룬 내용이며, 여기에 토큰의 유효기간이 만료되었을 때(검증 실패)를 고려한 Refresh
토큰을 추가해보도록 하겠다.
서버에서 JWT 토큰을 발급하게 할 때 토큰은 설정한 유효기간
을 갖게 된다. 클라이언트에서 보낸 토큰의 유효기간이 지나게 된다면, 서버는 토큰 검증에 실패하게 되어 요청한 응답을 보낼 수 없다. 이렇게 되면 사용자는 다시 로그인해야 하는 번거로움이 생긴다.
이를 방지하기 위해 서버는 인증 완료 시에 클라이언트에 보낼 Access 토큰
과 Access 토큰의 만료시 재발급에 사용할 Refresh 토큰
2가지의 토큰을 발급한다. Refresh 토큰은 오직 Access 토큰의 재발급을 위해 존재한다.
Refresh 토큰을 고려하여 다시 인증 및 인가 과정을 그려보자.
(Access 토큰 = AT
, Refresh 토큰 = RT
)
- 클라이언트: 로그인 정보 보냄
- 서버: 인증 완료(DB 조회) 시
AT
,RT
발급- 서버: 클라이언트로
AT
보냄,RT
는 저장- 클라이언트: 응답받은
AT
저장.
- 클라이언트:
AT
와 함께 API 요청- 서버:
AT
검증 후 응답 보냄
- 서버: 클라이언트로 토큰 재발급 요청
- 클라이언트: 토큰 재발급 API 요청
- 서버: 저장한
RT
조회, 검증- 서버:
AT
,RT
재발급- 서버: 클라이언트로
AT
보냄
- 서버: 클라이언트로 로그인 재요청
여기까지가 앞으로 프로젝트를 통해 구현해 볼 과정들이다.
AT
와 RT
를 다루는 방식에서는 절대적인 정답은 없는 듯하다. 클라이언트에서 AT
와 RT
2개를 가지고 있는 경우도 있고, RT
의 관리 또한, 일반 DB에 저장하는것과 Redis
와 같은 인메모리에 저장하는 방식으로 나뉜다.
다음 포스팅은 Redis
를 통해 refresh 토큰을 관리하는 이유와 방법에 대해 다뤄보기로 한다.