728x90

 

지난 포스팅에서는 토큰 기반 인증 시스템에 대해 알아보았다. 

 

JWT - 토큰 기반 인증

JWT에 대해 알아보기 전에, 모던 웹서비스에 많이 사용되고 있는 '토큰(Token) 기반 인증'에 대해 먼저 알아보자. API를 사용하는 웹서비스를 개발한다면, 토큰을 사용하여 유저들의 인증 작업을 처

dolphinsarah.tistory.com

 

이번 포스팅에서는, 토큰 기반 인증 시스템의 구현체인 JWT(JSON Web Token)에 대한 소개 후,

JWT 토큰의 기본 구조를 알아보자. 

 

 

JSON Web Token이란?

 

JSON Web Token(JWT)은 웹표준으로서, 두 개체에서 JSON 객체를 사용하여

가볍고 자가수용적인(self-contained) 방식으로 정보를 안정성 있게 전달해준다. 

 

  • 수많은 프로그래밍 언어에서 지원된다 - JWT는 C, Java, Python, C++, R, C#, PHP, JavaScript, Ruby, Go, Swift 등 대부분의 주류 프로그래밍 언어에서 지원된다.
  • 자가 수용적(self-contained)이다 - JWT는 필요한 모든 정보를 자체적으로 지니고 있다. JWT 시스템에서 발급된 토큰은, 토큰에 대한 기본 정보, 전달할 정보(로그인 시스템이라면 유저 정보), 그리고 토큰이 검증됐다는 것을 증명해주는 signature를 포함하고 있다. 
  • 쉽게 전달될 수 있다 - JWT는 자가수용적이므로, 두 개체 사이에서 손쉽게 전달될 수 있다. 웹서버의 경우 HTTP의 헤더에 넣어서 전달할 수도 있고, URL의 파라미터로 전달할 수도 있다. 

 

JWT는 어떤 상황에서 사용될까?

 

아래와 같은 상황에서 JWT가 유용하게 사용될 수 있다. 

 

회원 인증

JWT를 사용하는 가장 흔한 시나리오다. 

 

유저가 로그인을 하면, 서버는 유저의 정보에 기반한 토큰을 발급하여 유저에게 전달해준다. 

 

그 후, 유저가 서버에 요청을 할때마다 JWT를 포함하여 전달한다. 

 

서버가 클라이언트에게서 요청을 받을 때마다, 해당 토큰이 유효하고 인증됐는지 검증을 하고, 

유저가 요청한 작업에 관한 권한이 있는지 확인하여 작업을 처리한다. 

 

서버에서는 유저의 세션을 유지할 필요가 없다. 

 

즉, 유저가 로그인되어 있는지 아닌지 신경쓸 필요가 없고, 유저가 요청을 했을 때 토큰만 확인하면 되기 때문에,

세션 관리가 필요 없어서 서버 자원을 많이 아낄 수 있다. 

 

정보 교류

JWT는 두 개체 사이에서 안정성있게 정보를 교환하기에 좋은 방법이다. 

 

그 이유는, 정보가 sign 되어 있기 때문에 정보를 보낸이가 바뀌진 않았는지

정보가 도중에 조작되지는 않았는지 검증할 수 있다. 

 

 

JWT의 생김새 

 

JWT는 .을 구분자로 3가지의 문자열로 되어 있다. 구조는 아래와 같다. 

 

aaaaaa.bbbbbb.cccccc
헤더(header).내용(payload).서명(signature)

 

(JWT 토큰을 만들때는 JWT를 담당하는 라이브러리가 자동으로 인코딩 및 해싱 작업을 해준다.)

 

그럼 위와 같이 3가지 부분으로 나뉘어져 있는 각각에 대해 알아보자. 

 

헤더(Header)

헤더는 두 가지의 정보를 지니고 있다. 

 

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

 

정보(payload)

payload 부분에는 토큰에 담을 정보가 들어 있다. 

 

여기에 담는 '정보의 한 조각'클레임(claim)이라고 부른다. 

 

name/value의 한 쌍으로 이루어져 있다. 

 

그리고 토큰에는 여러 개의 클레임들을 넣을 수 있다. 

 

클레임은 등록된(registered) 클레임, 공개(public) 클레임, 비공개(private) 클레임으로 나뉘어져 있다. 

 

# 등록된(registered) 클레임

 

등록된 클레임들은 서비스에서 필요한 정보들이 아닌, 토큰에 대한 정보들을 담기 위해

이름이 이미 정해진 클레임들이다.

 

등록된 클레임의 사용은 모두 선택적(optional)이며, 이에 포함된 클레임 이름들은 다음과 같다. 

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

 

# 공개(public) 클레임

 

공개 클레임들은 충돌이 방지된(collision-resistant) 이름을 가지고 있어야 한다. 

 

충돌을 방지하기 위해서, 클레임 이름을 아래와 같이 URI(Uniform Resource Identifier) 형식으로 짓는다. 

 

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

 

# 비공개(private) 클레임 

 

등록된 클레임도 아니고, 공개된 클레임도 아니다. 

 

양 측간에(보통 클라이언트 <-> 서버) 협의 하에 사용되는 클레임 이름이다. 

 

공개 클레임과는 달리 이름이 중복되어 충돌이 될 수 있으니, 사용할 때 유의해야 한다. 

 

{
    "username": "dolphinSarah"
}

 

아래 예제 payload는 2개의 등록된 클레임, 1개의 공개 클레임, 2개의 비공개 클레임으로 이루어져 있다. 

 

{
    "iss": "dolphinSarah.com",
    "exp": "1485270000000",
    "https://dolphinSarah.com/jwt_claims/is_admin": true,
    "userId": "11028373727102",
    "username": "dolphinSarah"
}

 

서명(signature)

JSON Web Token의 마지막 부분은 바로 서명(signature)이다. 

 

이 서명은 헤더의 인코딩 값과, 정보의 인코딩 값을 합친 후

주어진 비밀키로 해쉬를 하여 생성한다. 

 

서명 부분을 만드는 pseudo-code의 구조는 다음과 같다. 

 

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

 

이렇게 만든 해쉬를, base64 형태로 나타내면 된다. 

 

 

 

 

위 포스팅은 아래 링크를 참고하여 작성했습니다.

https://velopert.com/2389

728x90

'CS > 네트워크' 카테고리의 다른 글

HTTP 2.0과 특징  (0) 2021.06.11
로드밸런싱  (0) 2021.06.11
JWT - 토큰 기반 인증  (1) 2021.06.04
Authentication과 Authorization의 차이  (0) 2021.05.31
알아두면 좋은 HTTP X 헤더  (0) 2021.05.28

+ Recent posts