JWT(Json Web Token)는 인증에 필요한 정보들을 토큰에 담아 암호화 시켜 사용하는 토큰이다.
앱은 쿠키,세션이 없어 앱과 서버가 통신, 인증할 때 많이 사용된다.
세션과 다른 점은 서명된 토큰이라는 점 그리고 유저 데이터를 유저가 관리해 서버 부담을 줄일 수 있다는 것이다.
JWT는 사용자 자신은 토큰을 볼 수 있지만 수정은 불가하며 수정은 서버를 통해서만 가능하다.
JWT는 3마디로 나뉜다.
{Header}.{Payload}.{Signature}
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
Header: 데이터 타입, 암호, 알고리즘 정보
Payload: 토큰에 담을 정보
Signature: 서명
Header에는 2가지 정보가 있다.
{
"alg": "HS256",
"typ": "JWT"
}
{
"sub": "1234567890",
"name": "John Doe",
"iat": 1516239022
}
claim은 크게 세가지로 나뉜다.
이름이 정해진 클레임들이며 선택적으로 사용할 수 있다.
공개용 정보를 위해 사용되며 충돌 방지를 위해 URI형식으로 이름을 짓는다.
{"https://google.com": true}
서버와 클라이언트 사이에 임의로 지정한 정보를 저장한다.
{"token_type": "access"}
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret-key
)
JWT는 장점이 많지만 그렇다고 세션보다 모든면에서 우수한 것은 아니다.
데이터 길이가 길어서 인증 요청이 많아지면 네트워크 부하가 발생할 수 있다.
세션은 모든 사용자의 상태를 기억해서 고려할게 많지만 가능하다면 사용자 상태를 제어할 수 있다.
만약에 JWT가 탈취를 당한다면 통제를 할 수 없어 아무런 조치를 할 수 없다.
위의 문제점을 보완하기 위해 access토큰과 refresh토큰을 사용한다.
Access 토큰: 유저의 정보가 담긴 토큰, 토큰으로 사용자 정보에 맞게 응답을 진행한다.
Refresh 토큰: 새로운 access 토큰을 발급해주기 위해 사용하는 토큰이다.
사용자가 서버에 로그인을 요청한다.
서버에서 인증 요청을 받으면, Header, Payload, Signature를 정의하고 이것들을 Base64로 한 번 더 암호화하여 JWT를 생성하고 이를 쿠키에 담아 클라이언트에게 발급한다.
클라이언트는 받은 JWT를 브라우저 저장소에 저장한다.
서버에 요청 시 헤더에 토큰을 담아서 보낸다.
서버는 요청을 받을 때마다 비밀키를 사용해 토큰이 유효한지 검증한다.
만약 액세스 토큰의 시간이 만료되면 리프래시 토큰을 이용해 서버에게 새 엑세스 토큰을 발급 받는다.