✔︎ JWT(JSON Web Token)
JSON 객체를 사용해서 토큰 자체에 정보들을 저장하고 있는 web token이다.
구성
sub: 토큰 제목
iat: 토큰 발급 시간
exp: 토큰 만료 시간
payload에 담겨진 정보의 한 조각("name": "value")을 claim이라고 한다.
Bearer
일반적으로 토큰은 request header의 Authorization 필드에 담아져 아래와 같은 형식으로 보내진다.
Authorization: [type][access token]
Bearer는 위 형식에서 type에 해당된다.
- Bearer
JWT 혹은 OAuth에 대한 토큰을 사용한다. (RFC 6750)
장점과 단점
- 장점
- 서버단의 별도의 저장소가 필요하지 않다.
- 확장 용이
- URL, Cookie, Header 모두 사용 가능
- 단점
- payload가 많아지면 네트워크 사용량 증가
- 토큰 자체 정보를 담고 있어 취약할 수 있다.
- 서버에서 클라이언트 토큰을 조작할 수 없다.
프로젝트에서 사용
인증을 위해서 다음과 같은 2가지 JWT를 사용하였다.
- Access token
- 실제 인증을 위해서 사용한다. payload에는 사용자 email과 권한 정보를 담았으며 만료시간은 30분으로 설정하였다.
- 발급시 response body에 넣어 클라이언트에게 전달한다. 클라이언트는 요청 header의 Authorizatoin 필드에 토큰을 담아 서버에 보낸다.
- 만료가 되면 요청을 refresh token을 위해 재발급을 요청한다.
- Refresh token
- Access token을 갱신하기 위해서 사용한다. payload에 아무것도 담지 않았으며 만료시간은 7일으로 설정하였다. refresh token은 만료가 되더라도 갱신하지 않는다.
- 발급시 Set-Cookie 헤더에 refreshToken 값을 설정하여 클라이언트에게 전달한다. cookie의 만료 시간은 refresh token의 만료 시간과 동일하다.
✔︎ Spring Security JWT
Spring Security와 JWT를 이용한 인증을 구현해보았다. 다른 기능보다는 JWT를 이용한 인증에 초점을 두었다.
기능
-
회원 가입
사용자의 이름, 이메일, 패스워드를 입력하여 가입한다.
-
로그인
- 이메일과 패스워드를 이용하여 로그인을 진행한다. 로그인이 성공적으로 진행될 경우 access token과 refresh token을 발급한다.
- access token은 30분 refresh token 7일로 만료 시간을 설정한다.
- refresh token의 경우 redis에 expire time을 만료시간과 동일하게 지정하여 저장한다.
- access token은 request body에 refresh token은 Set-Cookie 헤더를 이용하여 클라이언트에게 전달한다.
- 단 httpOnly와 secure=true를 적용한다.
-
토큰 갱신
access token이 만료된 경우 access token과 refresh token을 이용하여 새 access token을 발급한다.
if) 토큰 갱신 시...
❑ access token에 문제가 있는 경우 → 다시 로그인을 하도록 한다.
❑ refresh token임 만료되었거나 문제가 있는 경우 → 다시 로그인을 하도록 한다.
-
로그아웃
access token과 refresh token을 이용하여 로그아웃을 진행한다. redis에 있는 refresh token을 제거하고 access token을 blacklist에 넣는다. 로그아웃에 대한 응답을 보낼 때 Set-Cookie 해더를 이용하여 refreshToken을 제거한다(maxAge = 0).
- blacklist
로그아웃되거나 탈퇴 한 유저의 access token을 token의 남은 유효시간 동안 저장하고 있는 곳이다. 로그아웃 또는 탈퇴 후 유효시간이 남은 access token을 사용하는 것을 방지한다. redis를 이용하여서 구현하였다.
-
기타
인증이 제대로 작동하는지 확인하기 위한 api를 2개 만들었다.
코드
Spring Security JWT 깃허브 레파지토리