1. JWT
유저를 인증하고 식별하기 위한 표준 웹 토큰 (Token) 으로 JSON 데이터를 기반으로 하며 서명을 통해 암호화되어 사용된다.
2. JWT의 구조
아래의 문자열은 JWT의 예시이다.
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
JWT는 Header, Payload, Signature 순서로 구성되어 있으며 각각 . 으로 구분된다.
2.1. Header
Header는 eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9 에 해당하며 다음의 JSON 데이터를 Base64Url 인코딩한 값이다.
{
"alg": "HS256",
"typ": "JWT"
}
인코딩되기 전의 JSON 데이터를 살펴보면 JWT를 서명하는 알고리즘(alg)과 토큰의 타입(typ) 데이터가 포함되어 있는 것을 알 수 있다.
2.2. Payload
Payload는 eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ 에 해당하며 다음의 JSON 데이터를 Base64Url 인코딩한 값이다.
{
"sub": "1234567890",
"name": "John Doe",
"iat": 1516239022
}
JSON 데이터에서 key 값을 보면 sub, name, iat 이 있는데 이를 claim 이라고 한다. Payload 부분에는 주로 사용자에 대한 claim 이 포함되는데 claim은 등록된 클레임(registered claim), 공개 클레임(public claim), 비공개 클레임(private claim) 으로 나뉜다. 등록된 클레임은 sub(subject), aud(audience), iss(issuer), exp(expiration time) 가 있다.
위의 데이터 중 name 은 비공개 클레임에 해당하며 공개 클레임의 key 값은 일반적으로 URI 형식으로 정의되어 있다.
2.3. Signature
Signature 부분은 SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c 에 해당하며 Base64Url 인코딩된 Header, Payload 값과 key 값을 이용하여 생성된다. 예를 들어, HS256 알고리즘으로 암호화 되는 경우 다음의 방법으로 Signature 를 생성한다.
HS256(Base64Url(Header)+'.'+Base64Url(Payload), secret_key)
Signature 값은 secret_key 값을 알아내지 않는 이상 사용자가 변조할 수 없으므로 JWT의 무결성을 검증하는 데 사용된다.
3. Signature 암호화 알고리즘
2.3. Signature에서 작성된 내용은 HS256 알고리즘으로 암호화 되는 경우 Signature가 생성되는 방법이다. Signature가 생성되는 방법은 사용되는 암호화 알고리즘에 따라 다르며 암호화 알고리즘은 크게 HS256, RS256 알고리즘이 있다.
3.1. HS256
HS256은 HMAC(Hash-based Message Authentication Code)과 SHA256 (Secure Hash Algorithm 256)을 결합한 암호화 알고리즘이다. HS256 알고리즘은 대칭 키 암호화 방식을 사용한다.
HS256 알고리즘으로 Signature를 생성하는 방법은 위에서 설명한 것과 같다. JWT의 Header와 Payload를 Base64Url 인코딩한 후 . 으로 연결한다. 그리고 연결한 문자열과 암호화 키를 이용하여 암호화한다.
3.2. RS256
RS256은 RSA 와 SHA256 알고리즘을 결합한 암호화 알고리즘으로 공개키(비대칭키) 암호화 방식을 사용한다. 암호화가 진행되는 대략적인 과정은 다음과 같다.
sha_256 = SHA256(Base64Url(Header)+'.'+Base64Url(Payload))
signature = rsa_sign(sha_256, privatekey)
먼저 Base64Url 인코딩된 Header와 Payload를 . 으로 연결한 문자열을 SHA256 알고리즘으로 암호화 하고, 암호화 한 값 을 개인 키를 가지고 RSA 알고리즘으로 서명한다.
4. 참고
- https://jwt.io/introduction
- https://meetup.nhncloud.com/posts/239
- https://velog.io/@ddangle/JWT-%ED%86%A0%ED%81%B0-%EC%95%94%ED%98%B8%ED%99%94-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-HS256%EA%B3%BC-RS256
- https://circle-lab.tistory.com/46