JWT란?

JWT는 정보를 JSOn객체 형태로 주고 받기 위해 표준규약에 따라 생성한 암호화된 문자열(토큰)이다.

Base64 디코딩만 하면 누구나 내용을 확인할 수 있고, 위변조가 불가능 하다는 특징이 있다.

왜 필요한가?

현재 사용자의 인증 방식에는 쿠키, 세션, JWT가 있다. 이들 중 JWT의 필요성을 파악해본다.

쿠키의 문제점

보안 취약점

요청 시 쿠키 값을 그대로 보내는 등 보안이 유지되어야 할정보가 그대로 노출되어 전송이 되거나 쿠키 자체가 유출되면 보안에 문제가 생긴다.

브라우저 지원

웹 브라우저마다 쿠키의 지원 형태가 다르기 때문에 브라우저를 변경 시 사용이 불가능하다.

적은 저장 용량

사이트 당 20개, 모두 합쳐 300개가 최대이며 각 쿠키는 4KB를 넘을 수 없는 등 한번에 하나의 정보만 저장 가능하다.

세션의 문제점

서버 확장시 세션 정보의 동기화 문제

sesson_problem1

서버가 스케일아웃 돼서 여러개가 생기면 각 서버마다 세션 정보가 저장된다.

로그인시 서버1로, 새로고침시 서버2로 접근하면 서버는 인증이 되지 않았다고 판단한다.

서버 / 세션 저장소의 부하

session_problem2

세션을 각 서버에 저장하지 않고 세션 전용 서버, DB에 저장해도 문제가 생긴다. 모든 요청 시 해당 서버에 조회해야 하기 때문에 DB부하를 야기할 수 있다.

웹 / 앱 간의 상이한 세션 처리 로직

session_problem3

기존의 Client 는 웹 브라우저가 유일했으나, 이제는 모바일로 접근하는 경우도 처리해야 한다.

웹 / 앱의 세션 처리 방식이 다르고 또 다른 Client가 생겨나면 그에 맞게 처리해야 한다.

Web Token의 필요성

위의 문제들을 해결할 수 있는 방법이 Web Token이다.

토큰은 서버의 상태를 저장하지 않으며 토큰 자체로도 정보를 가지고 있기 때문에 별도의 인증 서버가 필요 없다.

따라서 요청을 받을 서버 자체에서 인증 프로세스를 수행할 수 있다.

또한, JSON 포맷으로 통신하기 때문에 어떤 Client에서든 Data 통신에 JSON을 이용하면 Token을 이용할 수 있다.

구성

jwt
JWT는 세부분으로 나누어지며 각각 Header, Payload, Signature이다.

Bases64인코딩의 경우 +, /, = 이 포함되지만 JWT는 URI에서 파라미터로 사용할 수 있도록 URL-Safe한 Base64url 인코딩을 사용한다.

토큰의 타입과 해시 암호와 알고리즘으로 구성되어있다.

1
2
3
4
{
  "alg":"HS256",
  "typ":"JWT"
}

type

토큰의 타입 지정 → JWT

alg

해싱 알고리즘을 지정한다. 보통 HMAC, SHA256, RSA가 사용되며 이 알고리즘은 토큰을 검증 할 때 사용되는 signature 부분에서 사용된다.

Payload

토큰에 담을 클레임(claim) 정보를 포함하고 있다.

Payload에 담는 정보의 한 ‘조각’을 클레임이라고 부르고 이는 name : value 한 쌍으로 이루어져있다.

토큰 안에는 여러개의 클레임을 넣을 수 있으며 크게 세 분류로 나눌 수 있다.

  • Registered claim
  • Public claim
  • Private claim

Registered claim

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

등록된 클레임의 사용은 모두 선택적이며, 이에 포함된 클래임 이름들은 아래와 같다.

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

Public claim

공개 클래임은 충돌이 방지된 이름을 가지고 있어야 한다. 충돌을 방지하기 위해서 클레임 이름을 URI 형식으로 짓는다.

1
2
3
{
	"https://goldenblock.com/jwt_claims/is_student": true
}

Private claim

등록이나 공개가 되지 않은 클레임이다.

클라이언트와 서버 협의하에 사용되는 클레임 이름들이다.

공개 클레임과는 달리 이름이 중복되어 충돌 될 수 있으니 주의하여야 한다.

1
2
3
{
	"username" : "velopert"
}

예시

1
2
3
4
5
6
7
{
	"iss": "goldenblock.com",
	"exp": "1485270000000",
	"https://goldenblock.com/jwt_claims/is_student": true,
	"userId": "11028373727102",
	"username": "wjrmffldrhrl"
}

Signature

JWT의 마지막 부분은 바로 서명이다.

이 서명은 헤더의 인코딩 값과, 정보의 인코딩 값을 합친 후 주어진 비밀키로 해쉬를 하여 생성한다.

1
2
3
4
HMACSHA256(
	base64UrlEncode(header) + "." +
	base64UrlEncode(payload),
	secret)

장점과 단점

장점

JWT의 주요한 이점은 사용자 인증에 필요한 모든 정보는 토큰 자체에 포함하기 때문에 별도의 인증 저장소가 필요 없다는 점이다.

또한 아래와 같은 장점이 있다.

  • URL 파라미터와 헤더로 사용
  • 수평 스케일이 용이
  • 디버깅 및 관리가 용이
  • 트래픽에 대한 부담이 낮음
  • REST 서비스로 제공 가능
  • 내장된 만료 기간
  • 독립적인 JWT

단점

  • 토큰은 클라이언트에 저장되기 때문에 데이터베이스에서 사용자 정보를 조작하더라도 토큰에 직접 적용할 수 없다.
  • 더 많은 필드가 추가되면 토큰이 커질 수 있다.
  • 비상태 어플리케이션에서 토큰은 거의 모든 요청에 대해 전송되므로 데이터 트래픽에 영향을 미칠 수 있다.

Reference

what is JWT

[WEB HACKING] JWT(JSON Web Token) 인증방식과 보안테스트/취약성(JWT Test and Vulnerability)

JWT (JSON Web Token) 이해하기와 활용 방안 - Opennaru, Inc.

[JWT] JSON Web Token 소개 및 구조

JWT를 소개합니다. : TOAST Meetup

JWT (JSON Web Token) 이해하기와 활용 방안 - Opennaru, Inc.

[JWT/JSON Web Token] 로그인 / 인증에서 Token 사용하기