JWT(Json Web Token)는 프론트엔드와 백엔드가 분리된 구조에서 인증 정보를 안전하게 주고받기 위한 방식이다.
JWT는 Header, Payload, Signature 세 부분으로 구성되며,
서버는 사용자의 인증이 성공하면 Access Token과 Refresh Token을 발급한다.
Access token 은 약 10분 ~ 30분 정도의 짧은 유효시간을 가지며 , api 요청 시 인증 수단으로 사용된다.
Refresh Token은 1일 ~ 2주 정도의 유효 시간을 가지며, Access Token이 만료가 되었을 때 새로운 Access Token을 발급 받을 때 사용 된다.
Refresh Token은 보안상 DB에 저장하고, 탈취 시를 대비해 블랙리스트 처리 등을 할 수 있도록 관리한다.
eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9 ← Header (Base64 인코딩)
.
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwicm9sZSI6IlVTRVIiLCJleHAiOjE3MTUwMDMyMDB9 ← Payload (Base64 인코딩)
.
YIgIvxf3LgOt4GpNaWYGMmhZi...qRr-4Zc ← Signature (암호화된 서명)
jwt는 이와 같이 3가지의 . 으로 구분된 문자열이 들어 온다.
{
"alg": "RS256", // 사용된 서명 알고리즘
"typ": "JWT", // 토큰 타입 (항상 "JWT")
"kid": "key-2025" // (선택) 공개키 ID - RSA 방식일 때 유용
}
header의 경우 jwt를 어떻게 검증 할 지 알려주는 메타 데이터이다.
alg는 어떤 방식으로 signature을 생성했는지 확인을 한다.
kid는 RSA 방식일 때 공개키 식별을 위해 사용된다(RSA 방식이 아닌 경우 안써도 된다.)
HS256 대칭키 (Secret Key) 같은 키로 서명 & 검증
RS256 비대칭키 (Private/Public) PrivateKey로 서명, PublicKey로 검증
{
"sub": "123456", // 사용자 ID (subject)
"name": "SeokHwan", // 사용자 이름 (custom claim)
"role": "ADMIN", // 사용자 권한 (custom claim)
"iat": 1715100000, // 발급 시간 (issued at)
"exp": 1715103600 // 만료 시간 (expiration)
}
iat와 exp 의 경우 유닉스 타임스탬프로 기입을 하며
유닉스 타임스탬프란 1970년 1월 1일 00:00:00 UTC부터 지난 초(seconds) 를 의미한다.
Signature = sign(
base64UrlEncode(Header) + "." + base64UrlEncode(Payload),
secretOrPrivateKey
)
Header과 Payload를 합쳐서 만들어 Header과 Payload가 변조가 되지 않았는지를 확인하는데 사용된다.
이 서명 검증을 통해 토큰이 유효한지 판단한다.
openssl rand -base64 32
git bash에서 타이핑을 하면 알아서 만들어준다.