현재 프로젝트에서 인증 방식은 JWT였다. 리프레시 토큰을 도입하기 위해 공부해야 할 것들로 Spring Security와 JWT가 있었기에 이번에는 JWT를 알아보기로 했다.
Json Web Token으로, 인증에 필요한 정보를 객체에 담아 비밀 키로 서명한 토큰이다. 인터넷 표준 인증 방식으로 Authentication(인증)/Authorization(인가) 방식을 사용한다.
JWT는 로그인 하고 사용자 인증이 필요한 서비스에서 사용된다.
로그인 시
- 사용자가 로그인을 요청한다.
- 서버에서는 비밀 키를 사용해 Access token(JWT)을 발급한다.
- JWT를 헤더에 담아 클라이언트에게 전달한다.
로그인 후
- 클라이언트 측에서 JWT를 로컬에 저장한다.
- 사용자 인증이 필요할 API를 호출할 때마다 헤더에 JWT를 포함해 전달한다.
- 서버는 헤더의 Access Token(JWT)를 확인하고 신뢰하는 사용자인지 판단 후 API에 대해 응답한다.
크게 header, payload, signature로 나뉜다.
토큰에 담을 정보들이 들어있고, 이러한 정보 하나씩을 claim이라고 한다. claim에도 종류가 세 개 있는데 아래와 같다.
payload는 노출 및 수정이 가능하기에 인증에 필요한 최소한의 정보만 담아야 한다.
header의 인코딩 값과 payload의 인코딩 값을 합친 후 서버가 지정한 비밀 키로 해쉬하여 생성한다. 이는 토큰을 변조하기 어렵게 만들기 위한 과정이다.
payload의 노출 및 수정 가능성에 대해 악용을 방지하기 위함이다. 만약 토큰이 발급된 후 누군가 payload를 수정할 경우, payload에만 조작된 내용이 들어가있지만 signature에는 조작되기 전 payload 기반으로 암호화 된 결과가 들어가 있으므로 조작을 구분해낼 수 있다.
header와 payload는 base64로 인코딩 되어있기에 복호화가 쉽지만, signature은 서버 자체의 비밀 키를 사용하므로 복호화가 어려워 이러한 특징으로 보안적으로 안전하게 사용할 수 있다.
짧막 Stateful(상태유지) VS Stateless(무상태)
- Stateful (상태유지) : 서버가 클라이언트 상태를 저장해둬야 함 (ex:세션)
- Stateless (무상태) : 서버가 클라이언트 상태를 저장하지 않아도 됨 (ex:JWT)
참고
https://velopert.com/2389
https://supertokens.com/blog/what-is-jwt