JWT 토큰

Hyun·2024년 1월 26일
0

기본 지식

목록 보기
3/3
post-thumbnail

지난 글 HTTP의 특징, 쿠키와 세션, 토큰에서 토큰에 대해 알아보았다.

토큰의 특징을 복기해보자.

  • 토큰에는 특수한 수학적 원리가 적용되어 있어 마치 위조 방지 장치가 있는 지폐처럼 해당 서버만이 유효한 토큰을 발행할 수 있다.
  • 토큰 자체가 인증을 위한 정보를 포함하고 있기 때문에, 서버 측에서 따로 토큰과 관련된 정보를 저장할 필요가 없다. 토큰에는 클라이언트나 서버가 필요로 하는 인증, 권한 부여, 사용자 정보 등이 이미 포함되어 있다.
    => 따라서 클라이언트가 토큰을 받아서 쿠키나 스토리지에 저장한 후, 필요할 때마다 요청 헤더에 토큰을 포함시켜 제시하면 서버는 메모리에 토큰 정보를 따로 저장할 필요 없이 자기가 발급한 토큰임을 알아보고 사용자의 요청을 허가한다.
  • 따라서 stateless 하다.

JWT(JSON Web Token)

JWT(JSON Web Token)란 인증에 필요한 정보들을 암호화시킨 JSON 토큰을 의미한다. 그리고 JWT 기반 인증은 JWT 토큰(Access Token)을 HTTP 헤더에 실어 서버가 클라이언트를 식별하는 방식이다.

JWT는 JSON 데이터를 Base64 URL-safe Encode 를 통해 인코딩하여 직렬화한 것이며, 토큰 내부에는 위변조 방지를 위한 전자서명도 들어있다. 따라서 사용자가 JWT 를 서버로 전송하면 서버는 서명을 검증하는 과정을 거치며 검증이 완료되면 요청에 대한 응답을 돌려준다.
*Base64 URL-safe Encode 는 일반적인 Base64 Encode 에서 URL 에서 오류없이 사용하도록 '+', '/' 를 각각 '-', '_' 로 표현한 것이다.

JWT(JSON Web Toke)의 구조

간결한 형태의 JSON Web Token 은 점(.)으로 구분된 세 부분으로 구성되며 다음과 같다

  • Header
  • Payload
  • Signature

따라서 JWT는 일반적으로 다음과 같다.
xxxxx[Header].yyyyy[Payload].zzzzz[Signature]

Header
헤더는 일반적으로 JWT인 토큰 유형과 HMAC SHA256 또는 RSA와 같이, 사용중인 서명 알고리즘의 유형으로 구성된다. 예를 들어 아래의 JSON 은 Base64Url로 인코딩되어 JWT의 첫 번째 부분(헤더)을 구성한다.

{
  "alg": "HS256",
  "typ": "JWT"
}

Payload
토큰의 두 번째 부분은 클레임을 포함하는 Payload이다. 클레임은 entity(일반적으로 user) 및 추가 데이터에 대한 설명이다. 청구 유형에는 registered(등록), public(공개), private(비공개) 세 가지가 있다. 예를 들어 아래의 JSON은 base64Url로 인코딩되어 JWT의 두 번째 부분(페이로드)를 구성한다.

{
  "sub": "1234567890",
  "name": "John Doe",
  "admin": true
}

Signature
서명 부분을 생성하기 위해서는 인코딩된 Header, 인코딩된 Payload, secret key, 그리고 Header에 지정된 알고리즘이 필요하다.

Header 의 인코딩 값과 Payload 의 인코딩 값을 합친 후, 주어진 private key로 해싱하여 서명을 생성한다. 해싱에는 Header에 지정된 알고리즘을 사용하는데, 이때 서버가 자체적으로 사용하는 알고리즘과 일치하는지 확인하는 과정을 거친다.

예를 들어 HMAC SHA256 알고리즘을 사용하는 경우 서명은 다음과 같은 방식으로 생성된다.
*SHA256 알고리즘은 해시 함수로서, 단방향 함수이기 때문에 복호화가 불가능하다.

HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  secret
  )

서명은 메시지가 도중에 변조, 위조되지 않았는지 확인하는데 사용되며, private key 로 서명된 토큰의 경우 JWT의 송신자가 누구인지 확인할 수도 있다.

서버에서 JWT의 유효성을 확인하는 과정은 다음과 같다.

  1. 헤더와 페이로드 디코딩
    클라이언트에서 전송된 JWT의 헤더와 페이로드는 base64 디코딩하여 원래의 JSON 형식으로 변환한다.

  2. 서명 검증
    디코딩된 헤더와 페이로드, 그리고 서버가 JWT 생성에 사용한 secret key 를 사용하여 서명을 검증한다. 서버는 헤더에 명시된 알고리즘에 따라 토큰을 서명했으므로, 해당 알고리즘과 키를 사용하여 서명을 다시 생성하고, 클라이언트에서 전송된 서명과 비교하여 일치 여부를 판단한다.

만약 서명이 일치하면 토큰은 변조되지 않았고 서버가 토큰을 발급한 신뢰할 만한 곳에서 왔다고 판단할 수 있다.

이 과정에서 토큰의 헤더와 페이로드는 공개 정보이며, 서명은 토큰의 무결성을 검증하는데 사용된다. 토큰의 서명을 확인하는 데 사용되는 키는 서버 측에서 안전하게 관리되어야 한다.

서명 검증시 헤더와 페이로드를 디코딩하는 이유

서명을 검증할 때, 왜 토큰의 인코딩된 헤더와 페이로드를 다시 디코딩하여 이것들을 다시 인코딩한 것을 검증에 사용하는지 의문이 들었다.

이유는 다음과 같다.

헤더
헤더에는 토큰을 서명할 때 사용된 알고리즘 정보가 포함되어 있다. 따라서 서버는 디코딩된 헤더에 포함된 알고리즘 정보와, 서버에서 사용하는 알고리즘이 일치하는지 확인한다. 알고리즘이 일치하지 않는 경우에는 서명 검증을 진행할 수 없기 때문에 토큰의 유효성을 검증할 수 없다.

페이로드
페이로드의 디코딩은 서명 검증시 필요한 것은 아니다. 따라서 서명을 검증할 때, 페이로드를 디코딩하지 않고도 서명을 검증할 수 있다. 그러나 페이로드의 클레임(claim)에 접근하기 위해서는 디코딩이 필요하다.

[정리]
서명 검증 시 클라이언트로부터 받은 JWT의 생성 알고리즘과 서버에서 사용하는 JWT 생성 알고리즘이 일치하는지 확인하기 위해 헤더를 디코딩해야한다. 페이로드는 서명 검증 시 필요한 것은 아니지만 페이로드의 클레임(claim)에 접근하기 위해서는 디코딩이 필요하다.

자료 출처
JWT 토큰 인증 이란? (쿠키 vs 세션 vs 토큰)
[JWT] JWT(JSON Web Token) 설명 및 구조

profile
better than yesterday

0개의 댓글