You are on page 1of 13

2018. 10. 4. [JWT] JSON Web Token 소개 및 구조 | VELOPERT.

LOG

VELOPERT.LOG
DEVELOPMENT & LIFE LOG

about

dev.log 

thought.log

release.log

review.log

uncategorized.log

 

검색 …

[JWT] JSON Web Token 소개 및 구조


 2016 년 12월 5일  velopert  dev.log / JWT / tech.log  15 Comments
강좌목록
[Vue.JS 2.0] 강좌 목록
지난 포스트에서는 토큰 기반 인증 시스템의 기본적인 [React.JS] 강좌 목록
개념에 대하여 알아보았습니다. 이 포스트를 읽기 전에, [Node.JS] 강좌 목록
토큰 기반 인증 시스템에 대해서 잘 모르시는 분들은 지
난 포스트를 꼭 읽어주세요. [MongoDB] 강좌 목록
이번 포스트에서는, 토큰 기반 인증 시스템의 구현체인 [Serverless] 강좌 목록
JWT (JSON Web Token) 에 대한 소개를 하고, JWT
https://velopert.com/2389 1/13
2018. 10. 4. [JWT] JSON Web Token 소개 및 구조 | VELOPERT.LOG

토큰의 기본 구조를 알아보도록 하겠습니다.


최근 글
JSON Web Token 이 뭘까? 상태 관리 라이브러리의 미
학: Redux 또는 MobX 를
기본 정보 통한 상태 관리
velog서비스 공개 및 앞으
은 웹표준 (RFC 7519) 으로서 두
JSON Web Token (JWT)
로 velopert 블로그의 계
개체에서 JSON 객체를 사용하여 가볍고 자가수용적인 (self- 획
contained) 방식으로 정보를 안전성 있게 전달해줍니다.
길벗) 리액트를 다루는 기
(
수많은 프로그래밍 언어에서 지원됩니다 술 출간 / 집필후기
JWT 는 C, Java, Python, C++, R, C#, PHP, JavaScript, 리액트 기초 동영상 강의
Ruby, Go, Swift 등 대부분의 주류 프로그래밍 언어에서 지원 리뉴얼
됩니다.
create-react-app 에
자가 수용적 (self-contained) 입니다 ESLint 와 Prettier 적용
하기
JWT 는 필요한 모든 정보를 자체적으로 지니고 있습니다.
JWT 시스템에서 발급된 토큰은, 토큰에 대한 기본정보, 전달
할 정보 (로그인시스템에서는 유저 정보를 나타내겠죠?) 그리
고 토큰이 검증됐다는것을 증명해주는 signature 를 포함하고 최근 댓글
있습니다.
쉽게 전달 될 수 있습니다 박진영 (누구든지 하는 리
액트 6편: input 상태 관리
JWT는 자가수용적이므로, 두 개체 사이에서 손쉽게 전달 될 하기)
수 있습니다. 웹서버의 경우 HTTP의 헤더에 넣어서 전달 할
수도 있고, URL 의 파라미터로 전달 할 수도 있습니다. kekeke ( 리덕스(Redux)
를 왜 쓸까? 그리고 리덕스
  를 편하게 사용하기 위한
발악 (ii))
JWT 는 어떤 상황에서 사용될까? JIN (React.js Codelab
2016 – Express와
다음과 같은 상황에서 JWT 가 유용하게 사용 될 수 있습니다: React.js 를 사용한 웹 어

회원 인증: JWT 를 사용하는 가장 흔한 시나리오 입니다. 유저가 플리케이션 만들기 (1))


로그인을 하면, 서버는 유저의 정보에 기반한 토큰을 발급하여 유
https://velopert.com/2389 2/13
2018. 10. 4. [JWT] JSON Web Token 소개 및 구조 | VELOPERT.LOG

저에게 전달해줍니다. 그 후, 유저가 서버에 요청을 할 때 마다 상욱 이 (리액트 컴포넌트


JWT를 포함하여 전달합니다. 서버가 클라이언트에게서 요청을
스타일링 – CSS Module
받을때 마다, 해당 토큰이 유효하고 인증됐는지 검증을 하고, 유 / Sass / styled-
저가 요청한 작업에 권한이 있는지 확인하여 작업을 처리합니다. components)
서버측에서는 유저의 세션을 유지 할 필요가 없습니다. 즉 유저가
로그인되어있는지 안되어있는지 신경 쓸 필요가 없고, 유저가 요 리덕스(Redux)
velopert (
청을 했을때 토큰만 확인하면 되니, 세션 관리가 필요 없어서 서 를 왜 쓸까? 그리고 리덕스
버 자원을 많이 아낄 수 있죠. 를 편하게 사용하기 위한
정보 교류: JWT는 두 개체 사이에서 안정성있게 정보를 교환하 발악 (ii))
기에 좋은 방법입니다. 그 이유는, 정보가 sign 이 되어있기 때문
에 정보를 보낸이가 바뀌진 않았는지, 또 정보가 도중에 조작되지
는 않았는지 검증할 수 있습니다.
 
글 목록
년 9월
의 생김새
2018
JWT
2018 년 7월
JWT는 .  을 구분자로 3가지의 문자열로 되어있습니다. 구 2018 년 6월
조는 다음과 같이 이루어져있습니다:
2018 년 4월
2018 년 3월
2018 년 2월
2018 년 1월
자, 그럼 이렇게 3가지 부분으로 나뉘어져 있는 토큰을 하나하 2017 년 12월
나 파헤쳐봅시다.
2017 년 7월
JWT토큰을 만들때는 JWT 를 담당하는 라이브러리 2017 년 6월
가 자동으로 인코딩 및 해싱 작업을 해줍니다. 하지만
이 포스트에서는 JWT 토큰이 만들어지는 과정을 더 2017 년 5월
잘 파악하기 위해 하나하나 Node.js 환경에서 인코딩 2017 년 4월
및 해싱을 하도록 하겠습니다.
2017 년 3월
2017 년 1월
헤더 (Header) 2016 년 12월
https://velopert.com/2389 3/13
2018. 10. 4. [JWT] JSON Web Token 소개 및 구조 | VELOPERT.LOG

Header 는 두가지의 정보를 지니고 있습니다. 2016 년 11월


typ: 토큰의 타입을 지정합니다. 바로 JWT  이죠. 2016 년 10월
alg: 해싱 알고리즘을 지정합니다.  해싱 알고리즘으로는 보통
2016 년 9월
HMAC SHA256  혹은 RSA  가 사용되며, 이 알고리즘은,
토큰을 검증 할 때 사용되는 signature 부분에서 사용됩니다. 2016 년 8월
한번, 이 예제를 살펴보세요 : 2016 년 7월
{
2016 년 6월
"typ": "JWT",
"alg": "HS256" 2016 년 5월
}
2016 년 4월
위 예제에서는 HMAC SHA256  이 해싱 알고리즘으로 사용
(
2016 년 3월
됩니다)
이 정보를 base64  로 인코딩을 하면 다음과 같습니다. 2016 년 2월
2016 년 1월
Node.js 환경에서 인코딩하기
const header = {
"typ": "JWT",

};
"alg": "HS256"
카테고리
// encode to base64 카테고리 선택
const encodedPayload = new Buffer(JSON.str
.toString('bas

그 밖의 기능
.replace('=',
console.log('payload: ',encodedPayload);

/* Result:
header: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1Ni 로그인
*/
글 RSS
댓글 RSS
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9
WordPress.org

자, 이제 JWT 의 첫번째 파트가 완성되었습니다!

https://velopert.com/2389 4/13
2018. 10. 4. [JWT] JSON Web Token 소개 및 구조 | VELOPERT.LOG

참고: JSON 형태의 객체가 base64 로 인코딩 되는 과


정에서 공백 / 엔터들이 사라집니다. 따라서, 다음과 같
은 문자열을 인코딩을 하게 되죠:
{"alg":"HS256","typ":"JWT"}

정보 (payload)
Payload 부분에는 토큰에 담을 정보가 들어있습니다. 여기에
담는 정보의 한 ‘조각’ 을 클레임(claim) 이라고 부르고, 이는
name / value 의 한 쌍으로 이뤄져있습니다. 토큰에는 여러개
의 클레임 들을 넣을 수 있습니다.
클레임 의 종류는 다음과 같이 크게 세 분류로 나뉘어져있습니
다:
등록된 (registered) 클레임,
공개 (public) 클레임,
비공개 (private) 클레임
그럼, 하나 하나 알아볼까요?
#1 등록된 (registered) 클레임
등록된 클레임들은 서비스에서 필요한 정보들이 아닌, 토큰에
대한 정보들을 담기위하여 이름이 이미 정해진 클레임들입니
다. 등록된 클레임의 사용은 모두 선택적 (optional)이며, 이
에 포함된 클레임 이름들은 다음과 같습니다:
iss : 토큰 발급자 (issuer)
sub : 토큰 제목 (subject)
aud : 토큰 대상자 (audience)
exp : 토큰의 만료시간 (expiraton), 시간은 NumericDate
형식으로 되어있어야 하며 (예: 1480849147370) 언제나 현재
시간보다 이후로 설정되어있어야합니다.

https://velopert.com/2389 5/13
2018. 10. 4. [JWT] JSON Web Token 소개 및 구조 | VELOPERT.LOG

를 의미하며, 토큰의 활성 날짜와 비슷한 개


nbf : Not Before
념입니다. 여기에도 NumericDate 형식으로 날짜를 지정하며,
이 날짜가 지나기 전까지는 토큰이 처리되지 않습니다.
iat : 토큰이 발급된 시간 (issued at), 이 값을 사용하여 토큰
의 age 가 얼마나 되었는지 판단 할 수 있습니다.
jti : JWT의 고유 식별자로서, 주로 중복적인 처리를 방지하
기 위하여 사용됩니다. 일회용 토큰에 사용하면 유용합니다.
#2 공개 (public) 클레임
공개 클레임들은 충돌이 방지된 (collision-resistant) 이름을
가지고 있어야 합니다. 충돌을 방지하기 위해서는, 클레임 이름
을 URI 형식으로 짓습니다.
{
"https://velopert.com/jwt_claims/is_admin":
}

#3 비공개 (private) 클레임


등록된 클레임도아니고, 공개된 클레임들도 아닙니다. 양 측간
에 (보통 클라이언트 <->서버) 협의하에 사용되는 클레임 이름
들입니다. 공개 클레임과는 달리 이름이 중복되어 충돌이 될 수
있으니 사용할때에 유의해야합니다.
{
"username": "velopert"
}

예제 Payload
{
"iss": "velopert.com",
"exp": "1485270000000",
"https://velopert.com/jwt_claims/is_admin":
"userId": "11028373727102",
"username": "velopert"
}

위 예제 payload 는 2개의 등록된 클레임, 1개의 공개 클레


임, 2개의 비공개 클레임으로 이뤄져있습니다.
https://velopert.com/2389 6/13
2018. 10. 4. [JWT] JSON Web Token 소개 및 구조 | VELOPERT.LOG

위 데이터를 로 인코딩을 해볼까요?


base64  

Node.js 환경에서 인코딩하기


const payload = {
"iss": "velopert.com",
"exp": "1485270000000",
"https://velopert.com/jwt_claims/is_ad
"userId": "11028373727102",
"username": "velopert"
};

// encode to base64
const encodedPayload = new Buffer(JSON.str
.toString('bas
.replace('=',

console.log('payload: ',encodedPayload);

/* result
payload: eyJpc3MiOiJ2ZWxvcGVydC5jb20iLCJl
*/

eyJpc3MiOiJ2ZWxvcGVydC5jb20iLCJleHAiOiIxNDg1Mjc

주의: base64 로 인코딩을 할 때 dA==  처럼 뒤에


=  문자가 한두개 붙을 때가 있습니다. 이 문자는 
base64 인코딩의 padding 문자라고 부릅니다.
JWT 토큰은 가끔 URL 의 파라미터로 전달 될 때도 있
는데요, 이 =  문자는, url-safe 하지 않으므로, 제거되
어야 합니다. 패딩이 한개 생길 때도 있고, 두개 생길 때
도 있는데, 전부 지워(제거해줘도 디코딩 할 때 전혀 문
제가 되지 않습니다)

JWT 토큰의 두번째 파트가 완성되었습니다!


 

https://velopert.com/2389 7/13
2018. 10. 4. [JWT] JSON Web Token 소개 및 구조 | VELOPERT.LOG

서명 (signature)
의 마지막 부분은 바로 서명(signature)
JSON Web Token
입니다. 이 서명은 헤더의 인코딩값과, 정보의 인코딩값을
합친후 주어진 비밀키로 해쉬를 하여 생성합니다.
서명 부분을 만드는 슈도코드(pseudocode)의 구조는 다음과
같습니다.
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)

이렇게 만든 해쉬를, base64 형태로 나타내면 됩니다 (문자


열을 인코딩 하는게 아닌 hex → base64 인코딩을 해야
합니다)
 

한번, 이 포스트에서 사용된 예제 헤더와 정보를 해싱 해볼까


요?
먼저, 헤더와 정보의 인코딩 값 사이에 .  을 넣어주고, 합칩니

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3Mi
OiJ2ZWxvcGVydC5jb20iLCJleHAiOiIxNDg1MjcwM
DAwMDAwIiwiaHR0cHM6Ly92ZWxvcGVydC5jb20
vand0X2NsYWltcy9pc19hZG1pbiI6dHJ1ZSwidXNlc
klkIjoiMTEwMjgzNzM3MjcxMDIiLCJ1c2VybmFtZSI
6InZlbG9wZXJ0In0

이 값을 비밀키의 값을  secret  으로 해싱을 하고


base64로 인코딩하면 다음과 같은 값이 나옵니다.

Node.js 환경에서 해싱 및 인코딩하기


const crypto = require('crypto');
const signature = crypto.createHmac('sha25
.update(encodedHeader + '.' +
.digest('base64')
https://velopert.com/2389 8/13
2018. 10. 4. [JWT] JSON Web Token 소개 및 구조 | VELOPERT.LOG

.replace('=', '');

console.log('signature: ',signature);

WE5fMufM0NDSVGJ8cAolXGkyB5RmYwCto1pQwDIqo2w

이 부분 또한 padding 이 생기면 지워줍니다.


오우! 3번째 부분까지 끝났군요. 그러면 지금까지 구한 값들을
.  을 중간자로 다 합쳐주면, 하나의 토큰이 완성됩니다.

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3Mi
OiJ2ZWxvcGVydC5jb20iLCJleHAiOiIxNDg1MjcwM
DAwMDAwIiwiaHR0cHM6Ly92ZWxvcGVydC5jb20
vand0X2NsYWltcy9pc19hZG1pbiI6dHJ1ZSwidXNlc
klkIjoiMTEwMjgzNzM3MjcxMDIiLCJ1c2VybmFtZSI
6InZlbG9wZXJ0In0.WE5fMufM0NDSVGJ8cAolXGk
yB5RmYwCto1pQwDIqo2w

이 값을 https://jwt.io/ 의 디버거에 붙여넣어보세요


(JWT.IO 는 브라우저 상에서 JWT 토큰을 검증하고 생성 할
수 있게 해주는 디버거 서비스입니다)

https://velopert.com/2389 9/13
2018. 10. 4. [JWT] JSON Web Token 소개 및 구조 | VELOPERT.LOG

하단의 텍스트가 파란색으로 Signature Veri ed 라고 뜨면


JWT 토큰이 검증되었다는 것 입니다.

마치면서..
이번 포스트에서는 JWT 의 구조가 어떻게 되어있는지, 그리
고 어떤 과정을 거쳐서 만들어지는지 배웠습니다. 토큰에서 필
요한 정보를 하나하나 인코딩하고 해싱하는것은 그렇게 대단
한 작업은 아니지만 조금은 귀찮기도 합니다. 실제로 JWT 를
서비스에서 사용할때는 우리가 직접 base64 인코딩을하거나
SHA256 해싱을 할 일은 없습니다. JWT 담당 라이브러리에
설정만 해주면 자동으로 손쉽게 만들고, 또 검증도 쉽게해주기
때문이지요.
다음 포스트에서는, Node.js 환경에서 jsonwebtoken
 이라는 패키지를 사용하여 MongoDB를 연동한 Express.js
웹 서버 프레임워크에서 JWT 기반 인증 시스템을 구현해보겠
습니다.

References
JSON Web Token (JWT)
http://self-issued.info/docs/draft-ietf-oauth-
json-web-token.html
JWT – Claims and Signing
http://self-issued.info/docs/draft-jones-json-
web-token-01.html
JSON Web Token Tutorial: An Example in
Laravel and AngularJS
https://www.toptal.com/web/cookie-free-
authentication-with-json-web-tokens-an-
example-in-laravel-and-angularjs
 

https://velopert.com/2389 10/13
2018. 10. 4. [JWT] JSON Web Token 소개 및 구조 | VELOPERT.LOG
 JSON Web Token / jwt / 토큰

 Previous Post

Next Post 

Comments Community 
1 Login

 Recommend 8 t Tweet f Share Sort by Best

Join the discussion…

LOG IN WITH OR SIGN UP WITH DISQUS ?

Name

Choong-Bum Park • 2 years ago


정말 좋은 강의였습니다. 감사합니다.
덕분에 많이 배우고 갑니다.
혹시 https기반의 node.js 통신 강좌는 계획에 없으신지요?
2△ ▽ • Reply • Share ›

Qus • 3 months ago


이해에 많은 도움이 되었습니다. 감사합니다!
1△ ▽ • Reply • Share ›

Dongyon Kang • 2 years ago


좋은 강좌 감사합니다. 이해하는데 큰 도움이 되었습니다. 그런데
혹시 첫번째 예제에서 payload가 아니라 header인가요?
const encodedPayload = new
Buffer(JSON.stringify(payload)) <-- header?
2△ ▽ • Reply • Share ›

Myoungjin, Ko • 9 months ago


좋은 정보 감사합니다.
△ ▽ • Reply • Share ›

장강산 • a year ago


감사합니다
△ ▽ • Reply • Share ›
https://velopert.com/2389 11/13
2018. 10. 4. [JWT] JSON Web Token 소개 및 구조 | VELOPERT.LOG

Hyunseo Kang • 2 years ago


현재 업무에 딱 필요한 정보. 정말 깔끔하고 상세하게 잘 정리하셨
습니다. 항상 많은 도움 됩니다.
△ ▽ • Reply • Share ›

velopert Mod > Hyunseo Kang • 2 years ago


:) 감사합니다
△ ▽ • Reply • Share ›

Sukyong Hong • 2 years ago


관련 좋은글 항상 잘 읽고 있습니다!! ^^
React
저도 마침 JWT 적용하려고 고민중이었는데 많은 도움 얻고 갑니
다.
△ ▽ • Reply • Share ›

velopert Mod > Sukyong Hong • 2 years ago


:) 감사합니다!
△ ▽ • Reply • Share ›

김정환 • 2 years ago


오랜만에 포스팅이 시네요? ㅎㅎ 잘봤습니다
△ ▽ • Reply • Share ›

velopert Mod > 김정환 • 2 years ago


감사합니다!!
△ ▽ • Reply • Share ›

Park Eden • 2 years ago


자세히 들여다보니 재미있네요 ㅎㅎ 잘보고갑니다
△ ▽ • Reply • Share ›

velopert Mod > Park Eden • 2 years ago


어플리케이션 세션관리를 하는데에서 좀 불만을 느끼고 있
었는데 JWT를 최근들어 사용해보니 참 괜찮은것같습니다
ㅎㅎ
△ ▽ • Reply • Share ›

Park Eden > velopert • 2 years ago


나중에 리액트 메모 튜토리얼 번외편 한번 가셔도
되겠는데요? ㅎㅎ
△ ▽ • Reply • Share ›

velopert Mod > Park Eden


• 2 years ago
나중에 리액트에서 예제로 한번 다뤄볼것
같습니다 ㅋㅋ
△ ▽ • Reply • Share ›
https://velopert.com/2389 12/13
2018. 10. 4. [JWT] JSON Web Token 소개 및 구조 | VELOPERT.LOG

ALSO ON VELOPERT.LOG

프레임워크로 서버리 누구든지 하는 리액트 6편: input


Serverless
스 애플리케이션 생성 및 배포하기 상태 관리하기
3 comments • 8 months ago 19 comments • 6 months ago
자문자답]AWS
jerry — [ 민동국 — 변수 값을
DK Min;
에 가셔서 해
CloudFormation 키로 쓸 수 있습니다var sName
당 스택을 제거하시면 됩니 = 'happy' [ sName ] : value

Proudly powered by WordPress | Theme: Annina Free by CrestaProject.

https://velopert.com/2389 13/13

You might also like