https://jwt.io/introduction (공식 문서)
https://velopert.com/2389 (Velog 만드신 분의 블로그)
{{HEADER}}.{{PAYLOAD}}.{{SIGNATURE}}
{{HEADER}}
{
"alg": "HS256",
"typ": "JWT"
}
"HS256"
은 HMAC SHA256
"typ"
: Token type"JWT"
'{"alg": "HS256","typ": "JWT"}'
가 인코딩되는 것.{{PAYLOAD}}
{
"sub": "1234567890",
"name": "John Doe",
"iat": 1516239022
}
iss
: issuersub
: subjectiat
: issued atexp
: expiration time1480849147370
등 NumericDate
형식이어야 한다.nbf
: not beforeaud
: audiencejti
: jwt id{
"http(s)://specific.uri/@unique_recommended_namespace/additional_path": true
}
{
"https://velopert.com/jwt_claims/is_admin": true
}
@unique_recommended_namespace
)를 포함하는 URI{
"username": "ajisai"
}
{
"iss": "velopert.com",
"exp": "1485270000000",
"https://velopert.com/jwt_claims/is_admin": true,
"userId": "11028373727102",
"username": "velopert"
}
Predefined, Public, Private을 혼용해도 된다.
=
가 붙기도 하고 안 붙기도 한다.=
는 query string에 쓰이므로 URL-safe하지 않다.{{SIGNATURE}}
HMACSHA256( //Pseudocode
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret
)
secret
Base64(ENCRYPT(hash(base64(HEADER).base64(PAYLOAD), SECRET))
//Header
const header = {
"typ": "JWT",
"alg": "HS256"
};
const encodedHeader = new Buffer(JSON.stringify(header))
.toString('base64')
.replace('=', ''); //remove padding
//Payload
const payload = {
"iss": "velopert.com",
"exp": "1485270000000",
"https://velopert.com/jwt_claims/is_admin": true,
"userId": "11028373727102",
"username": "velopert"
};
const encodedPayload = new Buffer(JSON.stringify(payload))
.toString('base64')
.replace('=', '');
//Signature
const crypto = require('crypto');
const signature = crypto.createHmac('sha256', 'SECRET')
.update(encodedHeader + '.' + encodedPayload)
.digest('base64')
.replace('=', '');
const jwt = encodedHeader + "." + encodedPayload + "." + signature;
중간중간에 해시나 인코딩은 라이브러리가 해준다면 직접 할 필요는 없다.
401 Unauthorized
가 응답으로 돌아온다.401
이 응답된다.header.payload
를 암호화한 것결론적으로 현재 payload에 포함된 expired date(조작됨)와 signature에 포함된 expired date(조작되지 않았음)가 맞지 않으므로 서버는 access 권한을 주지 않는다.
여기를 참고 바랍니다.