1. JWT(Json Web Token) 이란?
1 - 1) JSON Web Token (JWT) 은 두 개체에서 JSON 객체를 사용하여 가볍고 자가 수용적인 방식으로 정보를 안전성 있게 전달한다.
1 - 2) 수많은 프로그래밍 언어에서 지원된다.
JWT 는 C, Java, Python, C++, R, C#, PHP, JavaScript, Ruby, Go, Swift 등 대부분의 주류 프로그래밍 언어에서 지원된다.
1 - 3) 자가 수용적 (self-contained)이다.
JWT는 필요한 모든 정보를 자체적으로 지니고 있다.
JWT 시스템에서 발급된 토큰은, 토큰에 대한 기본정보, 전달할 정보 그리고 토큰이 검증됐다는 것을 증명해주는 signature를 포함하고 있다.
1 - 4 ) 쉽게 전달될 수 있습니다
JWT는 자가 수용적이므로, 두 개체 사이에서 손쉽게 전달될 수 있다.
웹서버의 경우 HTTP의 헤더에 넣어서 전달할 수도 있고, URL 의 파라미터로 전달 할 수도 있다.
2. JWT는 어떤 상황에서 유용한가?
2 - 1) 회원 인증
JWT를 사용하는 가장 흔한 시나리오이다.
유저가 로그인을 하면, 서버는 유저의 정보에 기반한 토큰을 발급하여 유저에게 전달한다.
그 후, 유저가 서버에 요청을 할 때마다 JWT를 포함하여 전달한다.
서버가 클라이언트에게서 요청을 받을 때마다, 해당 토큰이 유효하고 인증됐는지 검증을 하고, 유저가 요청한 작업에 권한이 있는지 확인하 여 작업을 처리한다.
또한 서버 측에서는 유저의 세션을 유지할 필요가 없다.
즉 유저가 로그인되어있는지 안되어있는지 신경 쓸 필요가 없고, 유저가 요청을 했을 때 토큰만 확인하면 된다.
즉 세션 관리가 필요 없어서 서버 자원을 많이 아낄 수 있다.
2 - 2) 정보 교환
JWT는 두 개체 사이에서 안정성 있게 정보를 교환하기에 좋은 방법이다.
그 이유는, 정보가 sign 이 되어있기 때문에 정보를 보낸 이 가 바뀌진 않았는지, 또 정보가 도중에 조작되지는 않았는지 검증할 수 있다.
3. JWT의 구조
3 - 1) header(헤더)
Header는 두 가지의 정보를 지니고 있다.
typ: 토큰의 타입 바로 JWT 이다.
alg: 해싱 알고리즘을 지정한다.
해싱 알고리즘으로는 보통 HMAC SHA256 혹은 RSA 가 사용되며, 이 알고리즘은, 토큰을 검증할 때 사용되는 signature 부분에서 사용된다.
3 - 2) payload(내용)
Payload 부분에는 토큰에 담을 정보가 들어있다.
여기에 담는 정보의 한 ‘조각’을 클레임(claim)이라고 부르고, 이는 name : value의 한 쌍으로 이뤄져 있다.
토큰에는 여러 개의 클레임 들을 넣을 수 있다.
클레임의 종류는 다음과 같이 크게 세 분류로 나뉘어있다.
등록된 (registered) 클레임,
공개 (public) 클레임,
비공개 (private) 클레임
#1 등록된 클레임
등록된 클레임들은 서비스에서 필요한 정보들이 아닌, 토큰에 대한 정보들을 담기 위하여 이름이 이미 정해진 클레임들이다.
등록된 클레임의 사용은 모두 선택적 (optional)이며, 이에 포함된 클레임 이름들은 다음과 같다.
- iss: 토큰 발급자 (issuer)
- sub: 토큰 제목 (subject)
- aud: 토큰 대상자 (audience)
- exp: 토큰의 만료시간 (expiraton), 시간은 NumericDate 형식으로 되어있어야 하며 (예: 1480849147370) 언제나 현재 시간보다 이후로 설정되어있어야 한다.
- nbf: Not Before를 의미하며, 토큰의 활성 날짜와 비슷한 개념이다. 여기에도 NumericDate 형식으로 날짜를 지정하며, 이 날짜가 지나기 전까지는 토큰이 처리되지 않는다.
- iat: 토큰이 발급된 시간 (issued at), 이 값을 사용하여 토큰의 age 가 얼마나 되었는지 판단할 수 있다.
- jti: JWT의 고유 식별자로서, 주로 중복적인 처리를 방지하기 위하여 사용된다. 일회용 토큰에 사용하면 유용하다.
#2 공개 클레임
공개 클레임들은 충돌이 방지된 (collision-resistant) 이름을 가지고 있어야 한다.
충돌을 방지하기 위해서는, 클레임 이름을 URI 형식으로 짓는다.
#3 비공개 클레임
등록된 클레임도 아니고, 공개된 클레임들도 아니다.
양 측간에 (보통 클라이언트 <->서버) 협의하에 사용되는 클레임 이름들이다.
공개 클레임과는 달리 이름이 중복되어 충돌이 될 수 있으니 사용할 때에 유의해야 한다.
3 - 3) 서명(signature)
JSON Web Token의 마지막 부분은 바로 서명(signature)이다.signature) 이다.
이 서명은 헤더의 인코딩 값과, 정보의 인코딩 값을 합친 후 주어진 비밀키로 해쉬를 하여 생성한다.
이렇게 만든 해쉬를, base64 형태로 나타내면 된다.
4. JWT 생성
이제 header, payload, signature 세 가지를 직접 인코딩하여 jwt를 만들어보자!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
const crypto = require('crypto');
const header = {
"typ": "JWT",
"alg": "HS256"
};
const payload = {
"iss": "juveloper.com",
"exp": "1485270000000",
"https://juveloper.com/jwt_claims/is_admin": true,
"userId": "11028373727102",
"username": "juveloper"
};
// encode to base64
const encodedHeader = new Buffer(JSON.stringify(header))
.toString('base64')
.replace('=', '');
//header data 'base64'로 인코딩!
const encodedPayload = new Buffer(JSON.stringify(payload))
.toString('base64')
.replace('=', '');
//payload data 'base64;로 인코딩!
const signature = crypto.createHmac('sha256', 'secret')
.update(encodedHeader + '.' + encodedPayload)
.digest('base64')
.replace('=', '');
//signature부분 생성!
console.log(`${encodedHeader}.${encodedPayload}.${signature}`);
//jwt 토큰
|
cs |
생성된 jwt를 다시 디코딩해보자!
JWT.IO
JSON Web Tokens are an open, industry standard RFC 7519 method for representing claims securely between two parties.
jwt.io
의 디버거 기능을 통해 우리가 만들어낸 jwt를 디코딩할 수 있다!
*출처 : velopert.com/2389
'Authentication' 카테고리의 다른 글
OAuth 2.0 (0) | 2020.12.04 |
---|---|
Cookie & Session (0) | 2020.12.04 |