[Web] JWT(JSON Web Token) 이란?
Web Token을 이용한 사용자 인증 방식은 기존의 Session/Cookie를 이용한 방식에 비해 서버에서 session을 유지할 필요가 없다는 장점이 있습니다. Token 기반 인증 방식 중 웹 표준(RFC 7519) 방식인 JSON Web Token에 대해서 알아보겠습니다.
JWT에 대해서
JWT는 header.payload.signature의 3가지 부분으로 이루어진 문자열입니다. 각 부분은 base64Url로 인코딩된 JSON 객체입니다.
header
header는 토큰의 유형(typ)과 signature를 만드는데 사용된 알고리즘(alg)정보가 포함됩니다
{
"alg": "HS256",
"typ": "JWT"
}
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
payload
payload에는 토큰에 대한 정보와 client/server간에 주고받고자하는 key-value값이 들어갑니다. 토큰에 대한 정보로는 발급자(iss), 만료시간(exp), 발급된 시간(iat)등이 들어갈 수 있습니다.
{
"name": "seungtaek",
"exp": 1516239022
}
eyJuYW1lIjoic2V1bmd0YWVrIiwiaWF0IjoxNTE2MjM5MDIyfQ
signature
마지막으로 signature에는 다음과 같은 방식으로, 인코딩된 header와 payload를 점(.)을 붙여서 합친 후, 사용자의 비밀키로 header에서 정의한 알고리즘을 통해 암호화 한 값이 들어갑니다.
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)
z_f4BW984TftcNqs74-bMrXgttvqItPEjsqKTAsLXqQ
마지막으로 세 값을 점(.)으로 이은 문자열이 하나의 JWT가 되게 됩니다.
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoic2V1bmd0YWVrIiwiaWF0IjoxNTE2MjM5MDIyfQ.z_f4BW984TftcNqs74-bMrXgttvqItPEjsqKTAsLXqQ
jwt.io에서 JWT에 대한 더 자세한 설명과 직접 JWT를 encoding하고 decoding해볼 수 있습니다.
JWT 생성 예제
Node.js 환경에서 직접 JWT를 생성하고 토큰을 검증하는 방법을 알아보겠습니다.
패키지 설치
header, payload, signature 객체를 만든 후 직접 인코딩하는 방법도 있지만 jsonwebtoken
이라는 패키지를 이용해서 간단하게 JWT를 만들 수 있습니다.
$ npm install jsonwebtoken
다음에서 전체 document를 확인할 수 있습니다.
(https://www.npmjs.com/package/jsonwebtoken)
JWT 생성
jwt.sign(payload, secretOrPrivateKey, [options, callback])
JWT를 생성하는 sign함수는 payload와 secret key를 필수 인자로 받습니다. 여기서 secret key는 하드코딩하는 것이 아닌 .env 파일이나 환경변수 등으로 관리하는 것이 좋습니다.
다음 코드는 콜백을 명시하지 않았으므로 동기적으로 실행되고 encode된 token을 return합니다.
const jwt = require('jsonwebtoken');
const token = jwt.sign({ name: 'seungtaek', age: 26}, 'secret_key');
콜백을 명시해서 비동기로 실행할 수도 있습니다.
jwt.sign({ name: 'seungtaek' }, 'secret_key', (err, token) => {
//do something...
});
다음처럼 간단하게 만료시간을 설정할 수도 있습니다.
jwt.sign({ name: 'seungtaek' }, 'secret_key', { expiresIn: '1h' });
JWT 검증
jwt.verify(token, secretOrPublicKey, [options, callback])
JWT를 검증하는 verify함수는 token과 그 token을 만드는데 사용된 secret key를 필수 인자로 받습니다.
다음 코드는 콜백을 명시하지 않았으므로 동기적으로 실행되고 token이 유효한 경우 decode된 token을 return합니다. 이때 token이 유효하지 않은 경우 error를 던지게 됩니다.
try{
const decoded = jwt.verify(token, 'secret_key');
console.log(decoded.name) // seungtaek
} catch(err) {
//do something
}
콜백을 명시해서 비동기적으로 실행할 수도 있습니다.
jwt.verify(token, 'shhhhh', (err, decoded) => {
console.log(decoded.name) // seungtaek
});
References
https://medium.com/neillab/what-is-jwt-89889759ae37 https://velopert.com/2389