MSA에서는 여러가지 이유로 JWT(JSON Web Token)를 사용하는데 이유는 아래와 같다.
인증 및 권한 부여
분산 시스템의 통함
스케일 아웃과 효율성
상태를 저장하지 않는 토큰
분리된 클라이언트와 백엔드
토큰의 유효 기간 설정
이 쯤 되니 안쓰는게 바보같다.
JWT란 Json포맷을 이용하여 사용자에 대한 속성을 저장하는 Claim 기반의 Web Token이다.
JWT는 토큰 자체 정보를 사용하는 Self-Contained 방식으로 정보를 안전하게 전달한다.
주로 회원 인증이나 정보 전달에 사용되는 JWT는 아래의 로직에 따라 처리된다.
애플리케이션이 실행될 때, JWT를 static 변수와 로컬 스토리지에 저장하게 된다.
static 변수에 저장되는 이유는 HTTP통신을 할 때마다 JWT를 HTTP 헤더에 담아서 보내야 하는데, 이를 로컬 스토리지에서 계속 불러오면 오버헤드가 발생하기 때문.
클라이언트에서 JWT를 포함해 요청을 보내면 서버는 허가된 JWT인지를 검사한다. 또한 로그아웃을 할 경우 로컬 스토리지에 저장된 JWT 데이터를 제거한다.
(실제 서비스의 경우에는 로그아웃 시, 사용했던 토큰을 blacklist라는 DB테이블에 넣어 해당 토큰의 접근을 막는 작업을 해줘야 한다.)
Self-Contained는 JWT(JSON Web Token)의 특성 중 하나이다.
Self-Contained Token은 토큰 자체에 필요한 모든 정보가 포함되어 있어, 토큰 검증하기 위해 추가적인 서버상태나 DB조회가 필요로 하지 않는 토큰임
어떤 작업이나 처리에 추가적으로 발생하는 부가적인 비용 또는 부담
JWT는 Header
, Payload
, Signature
의 세부분으로 이루어져 있고, Json 형태인 각 부분은 Base64Url로 인코딩 되어 표현된다.
각각의 부분을 이어주기 위해 .
구분자를 사용하여 구분하고, 추가로 Base64Url은 암호화 문자열이 아니고 같은 문자열에 대해 항상 같은 인코딩 문자열을 반환한다.
토큰의 헤더는 typ과 alg 두 가지 정보로 구성된다.
alg는 헤더를 암호화 하는 것이 아니고, Signature를 해싱하기 위한 알고리즘을 지정하는 것.typ: 토큰의 타입을 지정 ex)JWT
alg: 알고리즘 방식을 지정
토큰의 페이로드에는 토큰에서 사용할 정보의 조각들인 Claim이 담겨있다.
토큰에 포함된 정보를 설명하는 이름-값 쌍을 나타냄.
JWT는 Payload부분에 Claim을 포함하고 있으며, 이러한 클레임 토큰에 관련된 정보를 제공하거나 주장(Claim)한다.
클레임은 토큰의 정보를 서술하며 주로 세가지로 분류됨
Registered Claims(등록된 클레임) : 특정한 의미를 가지며, JWT 표준에 정의된 클레임들이다.
iss
(발급자): 토큰 발급자를 식별합니다.
sub
(주제): 토큰의 주제(대상)를 나타냅니다.
aud
(청취자): 토큰을 받아들일 수 있는 대상을 나타냅니다.
exp
(만료 시간): 토큰의 만료 시간을 나타냅니다.
nbf
(Not Before): 토큰의 사용을 시작하기 전의 시간을 나타냅니다.
iat
(발급 시간): 토큰의 발급 시간을 나타냅니다.
jti
(JWT ID): JWT의 고유 식별자를 나타냅니다.
Public Claims(공개 클레임)
충돌이 발생하지 않도록 URI형식으로 정의된 클레임
{
"https://https://github.com/Junsu97": true
}
Private Claims(사용자 정의 클레임)
공개 클레임과 충돌이 발생할 수 있는 사용자 정의 클레임들. 서버와 클라이언트 간에 사전에 합의된 내용을 담을 수 있다.
{
"token_type": access
}
서명은 토큰을 인코딩하거나 유효성을 검증할 때 사용되는 고유한 암호화 코드이다.
서명은 위에서 만든 헤더와 페이로드의 값을 가각 BASE64Url로 인코딩하고, 인코딩한 값을 비밀 키를 이용해 헤더의 alg에서 정의한 알고리즘으로 해싱을 하고, 이 값을 다시 BASE64Url로 인코딩하여 생성한다.
이렇게 생성된 토큰은 HTTP통신을 할 때 Authorization이라는 key의 value로 사용된다
개발자로서 배울 점이 많은 글이었습니다. 감사합니다.