JSON WEB TOKEN

오영선·2022년 7월 25일
0

특정 사용자가 서버에 접근을 했을 때, 이 사용자가 인증된 사용자인지 구분하기 위해서는 여러 방법을 사용할 수 있는데, 대표적인 방법으로는

서버 기반 인증
토큰 기반 인증

이 있고, 상황에 맞는 방법을 선택해서 사용하고 있다.

JWT란 토큰 기반 인증 방법으로, 인터넷 표준 인증 방식이다.
인증을 진행하는 구조는 Cookie와 비슷하지만 다른 점이 바로 서명된 토큰 이라는 점이다. public/private 키를 쌍으로 사용해 토큰에 서명할 경우 서명된 토크는 서버를 통해 이 토큰이 정상적인 토큰인지 인증할 수 있다.


(출처 : https://yuricoding.tistory.com/107)

  • 클라이언트가 아이디와 비밀번호를 서버에게 전달하며 인증을 요청한다.
  • 서버는 아이디와 비밀번호를 통해 유효한 사용자인지 검증하고, 유효한 사용자인 경우 토큰을 생성해서 응답한다.
  • 클라이언트는 토큰을 저장해두었다가, 인증이 필요한 api에 요청할 때 토큰 정보와 함께 요청한다.
  • 서버는 토큰이 유효한지 검증하고, 유효한 경우에는 응답을 해준다.

JWT는 서버와 클라이언트 간 정보를 주고 받을 때 Http 리퀘스트 헤더에 JSON 토큰을 넣은 후 서버는 별도의 인증 과정없이 헤더에 포함되어 있는 JWT 정보를 통해 인증한다.
(이때 사용되는 JSON 데이터는 URL-Safe 하도록 URL에 포함할 수 있는 문자만으로 만든다.)

JWT는 각각의 구성요소가 점(.)으로 구분이 되어있다.
출처 : https://velopert.com/2389

JWT 는 필요한 모든 정보를 자체적으로 지니고 있다. JWT 시스템에서 발급된 토큰은, 토큰에 대한 기본정보, 전달 할 정보 (로그인시스템에서는 유저 정보를 나타내는 정보) 그리고 토큰이 검증됐다는것을 증명해주는 signature 를 포함한다.


헤더 (Header)

typ: 토큰의 타입(JWT)
alg: 해싱 알고리즘. 해싱 알고리즘으로는 보통 HMAC SHA256 혹은 RSA 가 사용되며, 이 알고리즘은, 토큰을 검증 할 때 사용되는 signature 부분에서 사용된다.

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

내용 (payload)

Payload 부분에는 토큰에 담을 정보가 들어있다. 여기에 담는 정보의 한 ‘조각’ 을 클레임(claim) 이라고 부르고, 클레임은 key-value 의 한 쌍으로 이뤄진다. 한 토큰에는 여러개의 클레임 들을 넣을 수 있다.

클레임의 세 종류 :

registered 클레임,
public 클레임,
private 클레임

1 등록된 (registered) 클레임

토큰에 대한 정보를 담기 위한 클레임들이며, 이미 이름이 등록되어있는 클레임

  • iss: 토큰 발급자 (issuer)
  • sub: 토큰 제목 (subject)
  • aud: 토큰 대상자 (audience)
  • exp: 토큰의 만료시간 (expiraton), 시간은 NumericDate 형식으로 되어있어야 하며 (예: 1480849147370) 언제나 현재 시간보다 이후로 설정되어있어야합니다.
  • nbf: Not Before 를 의미하며, 토큰의 활성 날짜와 비슷한 개념입니다. 여기에도 NumericDate 형식으로 날짜를 지정하며, 이 날짜가 지나기 전까지는 토큰이 처리되지 않습니다.
  • iat: 토큰이 발급된 시간 (issued at), 이 값을 사용하여 토큰의 age 가 얼마나 되었는지 판단 할 수 있습니다.
    jti: JWT의 고유 식별자로서, 주로 중복적인 처리를 방지하기 위하여 사용됩니다. 일회용 토큰에 사용하면 유용합니다.

2 공개 (public) 클레임

공개 클레임들은 충돌이 방지된 (collision-resistant) 이름을 가지고 있어야 합니다. 충돌을 방지하기 위해서는, 클레임 이름을 URI 형식으로 짓습니다.

{
    "https://velopert.com/jwt_claims/is_admin": true
}

#3 비공개 (private) 클레임

양 측간에 (보통 클라이언트 <->서버)간에 통신을 위해 협의하에 사용되는 클레임 이름들입니다. 공개 클레임과는 달리 이름이 중복되어 충돌이 될 수 있으니 주의해야한다.

{
    "iss": "ajufresh@gmail.com", // 등록된(registered) 클레임
    "iat": 1622370878, // 등록된(registered) 클레임
    "exp": 1622372678, // 등록된(registered) 클레임
    "https://shinsunyoung.com/jwt_claims/is_admin": true, // 공개(public) 클레임
    "email": "ajufresh@gmail.com", // 비공개(private) 클레임
    "hello": "안녕하세요!" // 비공개(private) 클레임
}

위 예제 payload 는 3개의 등록된 클레임, 1개의 공개 클레임, 2개의 비공개 클레임으로 이뤄져있습니다.

서명 (signature)

해당 토큰이 조작되었거나 변경되지 않았음을 확인하는 용도로 사용하며, 헤더(header)의 인코딩 값과 정보(payload)의 인코딩값을 합친 후에 주어진 비밀키를 통해 해쉬값을 생성한다.

서명 부분을 만드는 슈도코드(pseudocode)의 구조는 다음과 같습니다.

HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)
이렇게 만든 해쉬를, base64 형태로 나타내면 됩니다 (문자열을 인코딩 하는게 아닌 hex → base64 인코딩을 해야합니다)


1,2,3을 각각 해싱해 합치게 되면 하나의 토큰이 완성된다.

출처 :
https://yuricoding.tistory.com/107
https://velopert.com/2389
https://brunch.co.kr/@jinyoungchoi95/1

0개의 댓글