이전에 cookie와 session에 대하여 알아보았습니다. 이번에는 로그인 인증 등 인증을 하기 위한 방법으로 사용되는 JWT에 대하여 알아보도록 하겠습니다.
cookie와 session에 대하여 궁금하시다면 아래의 링크를 이용해 주세요.
cookie와 session 이해하기 : https://rainbow96bear.tistory.com/entry/express-session%EA%B3%BC-cookie-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0
목차
JWT란?
Payload
JWT를 통한 인증 과정
JWT 생성하기
JWT의 장단점
JWT란?
JWT는 JSON Web Tokens의 약자로, 헤더(Header), 페이로드(payload), 서명(sign) 세 부분으로 구성된 토큰입니다.
헤더에는 토큰의 타입과 서명에 사용되는 hashing 알고리즘 정보가 담겨있고, 페이로드에는 정보들이 포함됩니다.
서버는 JWT를 생성하여 클라이언트에게 발급하고, 클라이언트는 JWT를 이용하여 인증 작업을 진행할 수 있습니다.
이러한 JWT기반의 인증은 JWT를 HTTP 헤더에 실어 서버가 클라이언트를 식별하는 방식입니다.
예시
JWT에 포함되는 header, payload, sign의 예시와 encode 된 JWT의 예시를 보여드리겠습니다.
Header | Payload | Sign |
{ "alg": "HS256", "typ": "JWT" } |
{ "sub": "1234567890", "name": "Rainbowbear", "iat": 1516239022 } |
HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), rainbowbear ) |
위의 내용을 Encode 하면 아래의 내용이 나옵니다.
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IlJhaW5ib3diZWFyIiwiaWF0IjoxNTE2MjM5MDIyfQ.GIYYmzi74hoORcwp3rvcgIt5-lxvXOH4fjz_sDVtW8E
아래의 주소에서 Encoded에 위의 내용을 입력하면 payload를 확인할 수 있습니다.
Payload
Payload는 Registered claims, Public claims, Private claims로 구성되어 있다고 합니다. Registed claims는 미리 정의된 클레임, Public claims는 공개되어도 되는 정보 전달을 위한 클레임, Private claim는 공개되어도 되는 사용자를 구별할 수 있는 클레임입니다.
Registered claim의 예시
iss : 발행자 (issuer)
sub : 제목 (subject)
aud : 토큰의 대상 (audience)
iat : 발행시간 (issued At)
exp : 만료시간 (expiration time)
jti : JWT 고유 식별자 (JWT ID)
예시
{
"iss" : "rainbowbear", // Registered claims
"jti" : "96", // Registered claims
"email" : "rainbow96bear@gmail.com", // Private claims
"language" : "Korean" // Public claims
}
JWT를 통한 인증 과정
JWT로 인증을 구현하는지 설명드리겠습니다.
- 사용자가 로그인 정보를 담아 서버로 요청합니다.
- 서버는 전달받은 정보를 확인하여 올바른 사용자 정보인 경우 Access Token과 Refresh Token을 발급합니다.
- 사용자가 서버에 요청을 보낼 시 Access Token을 이용하여 서버에 요청을 합니다.
- 서버는 Access Token의 정보를 확인하여 올바른 정보라면 응답합니다.
Access Token과 Refresh Token
Access Token : 사용자를 인증하고 리소스에 접근할 권한을 부여하는 토큰입니다.
보통 짧은 유효기간을 가지며, 사용자의 인증 정보와 권한 정보를 포함합니다.
Refresh Token : Access Token의 갱신을 위한 Token으로 Access Token보다 긴 유효기간을 갖습니다. Access Token이 만료되었을 때 Refresh Token이 만료되지 않았다면 Refresh Token의 정보 이용하여 Access Token을 발급받을 수 있습니다.
포함되는 정보로는 사용자 ID, 토큰 발급자 등을 기록하여 Access Token 발행에 사용합니다.
JWT 생성하기
우선 jsonwebtoken package를 설치하여 줍니다.
npm i jsonwebtoken
설치한 package를 이용하여 jwt를 생성합니다.
임시 데이터인 user를 설정하고 jwt를 생성하기 위한 secretKey를 설정합니다. secretKey의 경우 env 파일에 저장하여 사용하는 것을 추천드립니다.
const jwt = require("jsonwebtoken");
const user = {
id: 123,
username: "john_doe",
role: "user",
};
const secretKey = "rainbowbear";
// expiresIn 옵션으로 토큰의 유효기간을 설정
const token1 = jwt.sign(user, secretKey, { expiresIn: "1h" });
const token2 = jwt.sign(user, secretKey, { expiresIn: "30m" });
console.log("JWT Token1 :", token1);
console.log("JWT Token2 :", token2);
const verify1 = jwt.verify(token1, secretKey);
const verify2 = jwt.verify(token2, secretKey);
console.log("verify JWT1 : ", verify1);
console.log("verify JWT2 : ", verify2);
토큰의 만료시간을 비교하기 위하여 2개의 토큰을 생성하고 console을 이용하여 출력한 결과 아래와 같습니다.
JWT Token1 : eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MTIzLCJ1c2
VybmFtZSI6ImpvaG5fZG9lIiwicm9sZSI6InVzZXIiLCJpYXQiOjE2ODk5NDE3MDYsIm
V4cCI6MTY4OTk0NTMwNn0.rvMHiCN5JoGVElzSD-RiEMVJTK3tJZJmFkkM7IAfFuY
JWT Token2 : eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MTIzLCJ1c2
VybmFtZSI6ImpvaG5fZG9lIiwicm9sZSI6InVzZXIiLCJpYXQiOjE2ODk5NDE3MDYsIm
V4cCI6MTY4OTk0MzUwNn0.fahqjOLrTKb8nzkRqyQkPBdDxGPh4V-mIkIHOzbABMY
verify JWT1 : {
id: 123,
username: 'john_doe',
role: 'user',
iat: 1689941706,
exp: 1689945306
}
verify JWT2 : {
id: 123,
username: 'john_doe',
role: 'user',
iat: 1689941706,
exp: 1689943506
}
토큰의 만료시간이 1800 차이가 나는 것을 볼 수 있습니다. 이를 60으로 나누면 30으로 30분을 의미합니다.
이러한 식으로 m, h, d를 이용하여 각각 분, 시, 일로 만료시간을 설정할 수 있습니다.
JWT의 장단점
어떠한 기술이든 장점과 단점이 있습니다. JWT의 장점과 단점을 알아보겠습니다.
장점
서버가 세션을 관리할 필요 없이 토큰이 정보를 가지고 있으므로 확장성과 유연성이 높아집니다.
JWT에 클레임을 포함시킴으로써 서버가 추가적인 데이터베이스 조회 없이도 사용자 정보를 확인할 수 있습니다.
단점
Base64 인코딩으로 인해 세션 기반 인증보다 토큰 크기가 커집니다.
클라이언트에 토큰이 저장되어 XSS 공격에 취약할 수 있습니다.
한 번 발급된 토큰은 만료시간이 지나기 전까지 사용되므로 만료시간 설정이 적절해야 합니다.
'Node.js' 카테고리의 다른 글
[NodeJS] Socket.IO 이해하기 (0) | 2023.03.14 |
---|---|
[NodeJS] mysql sequelize 이해하기 - (관계형 테이블) (0) | 2023.03.13 |
[NodeJS] mysql sequelize 이해하기 - (기본 설정과 테이블 생성) (0) | 2023.03.09 |
[NodeJS] multer 이해하기 (0) | 2023.03.06 |
[NodeJS] express session과 cookie 이해하기 (0) | 2023.03.05 |