본문 바로가기
Programming/프로그래밍 이론

[프로그래밍 이론] JWT (Json Web Token)

by SpiralMoon 2019. 4. 19.
반응형

 주제 : JWT (Json Web Token).

 

서버가 클라이언트의 권한 및 인증정보가 표현된 JSON을 암호화 후 Token으로 발급하여, 클라이언트가 서버에 통신할 때 Session 없이 상태를 표현할 수 있도록 해주는 인증방식.

 

 Stateless (상태없음)

 

JWT를 왜 사용하는지에 대해서는 Stateful&Stateless 서버의 차이점부터 알아야 한다.

 

▷ Stateful 서버 : 서버가 클라이언트의 상태정보(Session)를 보유 및 유지하며, 상태정보를 바탕으로 클라이언트에게 서비스를 제공한다. 상태정보는 서버 컴퓨터의 메모리 혹은 DB에서 관리된다.

▷ Stateless 서버 : 서버가 클라이언트의 상태정보를 보유하지 않으며 클라이언트측의 요청만으로 서비스를 제공한다. 상태정보라는 공유점이 없기 때문에 확장성이 높다.

 

 Token 인증방식

 

근래의 웹 API 서비스는 대부분 Stateless + Token 인증기반으로 운영된다.

 

Token 인증방식이란 서버가 클라이언트에 권한 및 인증정보를 암호화하여 발급해주고, 클라이언트는 이후에 서비스를 이용할 때 Token을 요청에 담아서 함께 보낸다. 서버에서는 해당 Token이 변조된 것인지 검증한 후 서비스를 제공한다.

즉, Token 인증방식은 Token이라는 인증정보를 클라이언트가 보유한다.

 

▶  JWT의 구조

 

JWT는 Header와 Payload와 Signature 세 부분으로 나뉘며, 각 부분은 마침표(.)로 구별한다.

각 파트에 Base64 알고리즘이 필요한데 JWT에 적용하는 Base64는 padding 문자(=)를 사용하지 않는다.

 

 Header : Token의 암호화 종류(alg)와 타입(typ)이 정의된 JSON을 Base64로 인코딩 한다.

// 인코딩 전
{
	"alg" : "HS256",
	"typ" : "JWT"
}

// Base64 인코딩 후
// eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9

위 형태가 JWT의 가장 대표적인 Header이다.

Payload : 해당 토큰이 포함할 몇 가지 필드(Key-Value)가 담긴 JSON을 Base64로 인코딩 한다.

// 인코딩 전
{
	"iat" : 1554076800000,
	"exp" : 1554681600000,
	"uuid" : "09226aac-5f8c-11e9-8647-d663bd873d93"
}

// Base64 인코딩 후
// eyJpYXQiOjE1NTQwNzY4MDAwMDAsImV4cCI6MTU1NDY4MTYwMDAwMCwidXVpZCI6IjA5MjI2YWFjLTVmOGMtMTFlOS04NjQ3LWQ2NjNiZDg3M2Q5MyJ9

위 형태는 payload의 예시로 Token 발급시간(iat)과 만료시간(exp), 사용자의 UUID(uuid)를 표현한 것이다.

일반적으로 payload에는 Token에 포함될 데이터(JWT에서는 claim이라고 한다.)를 서술하는데, 어떤 데이터를 포함할 것인지는 Token을 제공하는 쪽에서 정해주면 된다. "꼭 어떤 필드를 포함해야된다" 라는 규칙은 없지만, JWT 문서 대부분에서 발급시간과 만료시간은 포함하기를 권장하고 있다.

Signature : 위변조되지 않은 JWT을 검증하는데 쓰이며, 검증은 비밀키를 가지고 있는 쪽(보통 발급자)에서만 가능하다. 발급자가 #Header + 마침표 + Payload# 문자열을 Header의 alg 타입의 방식으로 비밀키를 이용해 해싱한 데이터를 base64로 인코딩한 값이다.

var encodedHeader = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9";
var encodedPayload = "eyJpYXQiOjE1NTQwNzY4MDAwMDAsImV4cCI6MTU1NDY4MTYwMDAwMCwidXVpZCI6IjA5MjI2YWFjLTVmOGMtMTFlOS04NjQ3LWQ2NjNiZDg3M2Q5MyJ9";

var secret = "moon";
var signature = HS256.encode(encodedHeader + "." + encodedPayload, secret).toBase64String();

// signature
// 0mgNdgQZNw_C2QfloguymnakqIpDizuvo0uFRuxDWQo

완성된 JWT : 최종 형태는 Header.Payload.Signature와 같다.

"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE1NTQwNzY4MDAwMDAsImV4cCI6MTU1NDY4MTYwMDAwMCwidXVpZCI6IjA5MjI2YWFjLTVmOGMtMTFlOS04NjQ3LWQ2NjNiZDg3M2Q5MyJ9.0mgNdgQZNw_C2QfloguymnakqIpDizuvo0uFRuxDWQo"

 

▶  참조

JWT 연습 사이트 : 웹에서 직접 JWT를 제작해 볼 수 있다.

JWT 정의 : JWT 정의가 쓰인 문서이며, JWT에 사용하는 Base64는 padding을 사용하지 않는 것 등이 서술되어 있다.

반응형

댓글