JWT토큰이란?
선택적 서명 및 선택적 암호화를 사용하여 데이터를 만들기 위한 인터넷 표준이다. Json 형태로 웹에서 데이터를 안전하게 전달할때 사용한다.
유저를 인증, 인가하기 위한 토큰 기반이다.
RESTful과 같은 Stateless 환경에서 사용자 데이터를 주고받을 수 있다.
인증 Authentication, 인가 Authorization에서 사용한다.
구조
dot `.`을 기준으로 세 부분으로 나뉘게 된다. BASE64 Url 인코딩 방식을 사용한다.
JWT.IO
JSON Web Tokens are an open, industry standard RFC 7519 method for representing claims securely between two parties.
jwt.io
헤더 Header
서명 시 사용하는 키(kid), 사용할 타입(typ), 서명 암호화 알고리즘(alg)의 정보를 가지고 있다.
{
"alg": "HS256",
"typ": "JWT"
}
alg는 서명 알고리즘 (HMAC SHA256)이며, typ는 토큰의 타입 (JWT)를 나타낸다.
페이로드 Payload
토큰에서 사용할 정보의 조각인 클레임 `claims`를 포함한다.
클레임 : JWT 내에서 사용되는 정보 단위이다. 표준 / 커스텀으로 나뉜다.
페이로드는 사용자의 정보를 담고 있으며, password 는 안된다.
{
"sub": "1234567890",
"name": "John Doe",
"iat": 1516239022
}
sub는 사용자 ID, name은 사용자 이름, iat 는 토큰 발급 시간 issue at 이다.
서명 Signature
JWT의 무결성을 보장한다. 헤더와 페이로드를 인코딩한 후, private_key 비밀키와 함께 지정된 알고리즘을 생성한다.
페이로드 값이 조금이라도 바뀌면, 서명값이 통째로 바뀌기 때문에 안전하다.
작동 방식
- 클라이언트가 서버에 로그인 요청을 보낸다.
- 서버는 사용자를 인증하고 JWT 토큰을 생성하여 클라이언트에게 반환한다.
- 클라이언트는 서버로부터 받은 JWT 토큰을 저장한다(주로 로컬 스토리지 또는 쿠키에 저장).
- 클라이언트가 서버에 요청을 보낼 때마다 JWT 토큰을 포함시킨다.
- 서버는 받은 JWT 토큰을 검증하여 요청을 처리한다.
쿠키, 세션과 비교
쿠키 Cookie : (포춘) 쿠키에 필요한 내용을 직접 넣어서 서버 - 클라이언트가 소통한다. 서버가 저장 X (Stateless = 서버 상태저장하지 않는다.= RESTful) > 보안에 취약하다
세션 Session : 중요한 정보는 서버의 금고 (Session)에 저장해두고, 그 정보가 어디있는지 주소(Session ID)만 적어서 쿠키에 담는다. 보안이 비교적 좋다. > 서버가 저장 O Stateless 하지 않다.
차이점?
JWT는 클라이언트 측에 저장된다. 자체적으로 서명되어 무결성을 보장하고, Stateless 방식이다.
장단점
장점
- 독립성: 서버가 상태를 유지하지 않으므로 확장성이 뛰어나다.
- 확장성: 분산 시스템에서 효율적으로 사용될 수 있다.
- 간편한 사용: 클라이언트와 서버 간에 쉽게 통합될 수 있다.
단점
- 토큰 크기: JWT는 클레임 정보를 포함하므로 토큰 크기가 커질 수 있다.
- 보안 취약점: 잘못된 서명 알고리즘 선택이나 비밀 키 관리 부실로 인해 보안 취약점이 발생할 수 있다
최근에도 많이 사용하지 않는 추세라고 한다.
보안 고려 사항
토큰 유출 방지
HTTPS를 사용하여 전송하고, 로컬 스토리지 대신 HttpOnly 쿠키를 사용하는 것이 좋다
토큰 만료 및 갱신
만료 시간을 설정하여 유효 기간을 관리한다. 토큰이 만료되면 클라이언트는 갱신 토큰을 사용하여 새로운 JWT를 요청한다.
access Token, refresh Toke 관련 내용
실습 예제
`npm i jsonwebtoken`을 사용한다.
jsonwebtoken
JSON Web Token implementation (symmetric and asymmetric). Latest version: 9.0.2, last published: 8 months ago. Start using jsonwebtoken in your project by running `npm i jsonwebtoken`. There are 28040 other projects in the npm registry using jsonwebtoken.
www.npmjs.com
토큰 생성
var jwt = require("jsonwebtoken");
jwt 모듈 호출
var token = jwt.sign({ foo: "bar" },process.env.PRIVATE_KEY);
foo : payload + 환경변수로 암호키 만들어서, 토큰 생성한다.
토큰 검증
var decoded = jwt.verify(token, process.env.PRIVATE_KEY);
성공하면 페이로드 값 확인할 수 있다.
토큰 사용
jwt.verify(token, 'your_secret_key', (err, decoded) => {
if (err) {
return res.status(401).send('Unauthorized');
}
if (decoded.role !== 'admin') {
return res.status(403).send('Forbidden');
}
req.user = decoded;
next();
});
verify 메소드로 토큰의 유효성을 검증하고, 페이로드의 역할이나 권한을 확인한다.