Token은 Web Application이나 API에서 인증(Authentication)과 인가(Authorization)에 사용되는 디지털 문자열입니다. 사용자의 신원과 권한을 증명하고, 요청의 유효성을 검증하는 역할을 합니다. 인증된 사용자임을 확인하기 위한 고유한 서명을 포함하기 때문에 위조된 요청인지도 확인할 수 있습니다.
cookie처럼 서버가 아닌, 클라이언트에 저장이 되며, 서버는 토큰의 유효성만 검증합니다.
사용자가 아이디/비밀번호 등 자격 정보를 서버에 보내 로그인을 요청합니다. 여기서 서버는 DB등에서 자격 정보를 확인하고, 검증에 성공하면 토큰을 생성해 클라이언트에 전달합니다. 토큰에는 사용자 정보, 만료 시간, 서명 등이 포함되어있습니다.
클라이언트는 토큰을 안전하게(HttpOnly cookie, localStorage, Secure Storage 등) 저장합니다. 이후 모든 요청의 Authorization 헤더 등에 토큰을 포함하여 서버에 전달합니다.
서버는 토큰의 서명, 만료, 권한 등을 검증한 후 요청을 처리합니다. 만약, 토큰이 만료되면 refresh token 등으로 재발급하거나 재로그인이 필요하게 됩니다.
장점
단점
인증에 필요한 정보를 JSON 포맷으로 담고 서명까지 포함해 하나의 문자열로 만든 토큰입니다.
Header.Payload.Signature와 같은 구조를 가지고 있으며, 각각이 Base64Url로 인코딩 되어있고, 점(.)으로 구분됩니다.
| 구조 | 설명 |
|---|---|
| Header | 토큰 타입(JWT)와 서명 알고리즘(HS256, RS256 등) |
| Payload | 실제 인증/인가 정보(Claims), 사용자 정보, 권한, 만료시간 등 |
| Signature | Header와 Payload를 서버의 Secret Key로 서명 |
서버가 로그인 성공시 JWT를 생성합니다. 클라이언트는 JWT를 저장하며, API 요청 시 Authorization 헤더에 JWT를 포함(Bearer {JWT}와 같은 방식)합니다.
서버는 클라이언트로부터 받은 JWT의 서명, 만료, 권한 등을 검증 후 처리합니다.
Header와 Payload는 누구나 디코딩이 가능하므로 민감 정보는 저장하면 안됩니다. Singature와 같은 경우는 서버의 Secret Key로 생성하며 변조 시 서버가 검증에 실패합니다.
Secret Key는 충분히 복잡하고 안전하게 관리해야 합니다.
토큰이 탈취될 우려가 있으므로 HTTPS를 사용, HttpOnly/Secure 쿠키, 짧은 만료시간, Refresh Token의 활용 등이 필요합니다.
Signature부분을 Secret Key로 재계산하여 일치 여부를 확인할 수 있습니다. 이 경우, 만료 시간과 위변조 여부 등을 검증할 수 있으며, 검증 통과시 인증이 성공하고 요청을 처리합니다.
Secret Key로 재계산하기 때문에, secret key가 노출되지 않는 이상, 서버만이 올바른 Signature를 생성할 수 있습니다.
중요한 것은 JWT의 목적은 정보 보호가 아닌, 위조 방지입니다. 그렇기 때문에 Payload에는 절대로 민감 정보를 저장하면 안됩니다.
Access Token은 인증된 사용자의 정보와 권한이 담긴 토큰입니다. 탈취에 대응하기 위한 목적으로 유효 기간이 보통 짧습니다. API 요청시 Authorization 헤더에 포함하여 요청을 보냅니다.
Refresh Token의 경우, 유효 기간이 보다 짧은 Access Token이 만료되었을 때 재발급을 받기 위해 존재하는 토큰입니다. 그렇기 때문에 유효 기간이 Access Token 보다 깁니다. 보통 데이터베이스에 유저 정보와 같이 저장을 하게 됩니다.
하지만 Refresh Token의 경우에도 탈취의 우려가 있으므로, 토큰 재발급 횟수에 제한을 두거나 Refresh Token Rotation을 사용해 탈취를 예방하는 방법을 생각하며 JWT를 사용해야 합니다.
자료 및 코드 출처: 스파르타 코딩클럽