개요
개인 프로젝트에서 토큰 기반 인증 방식을 도입하면서 JWT에 대해 찾아보게 되었고, 이해한 부분들을 이 글에 정리해보려 한다.
JWT
JWT는 Json Web Token의 약자로, 비밀키를 이용하여 서명된 JSON 형태의 데이터이다. 여기에 사용자 인증 정보를 넣어서 토큰을 발급해주면, 추후 인증이 필요한 리소스에 접근 시 사용자가 서버에 토큰을 포함해서 전송하여 서버 층게서는 복잡한 인증 과정 없이 토큰만으로 사용자 인증 및 인가를 진행할 수 있는 것이다.
JWT는 아래와 같이 header, payload, signiture 세 가지 정보를 base64로 인코딩한 값을 dot(.) 사이에 두고 이어 붙인 형태로 생성된다.
xxxxx.yyyyy.zzzzz
그럼 header, payload, signiture에 대해 자세히 알아보자.
Header
Header는 주로 두 가지 파트로 구성된다.
- 토큰의 타입 (JWT)
- 서명에 사용되는 알고리즘 (e.g. HMAC, SHA256, RSA)
예:
{
"alg": "HS256",
"typ": "JWT"
}
Payload
토큰의 두번째 부분이며, 클레임 (claims) 이라는 것을 포함하고 있다. Claim은 대체로 사용자의 정보와 이에 관련한 데이터를 담고 있는 상태를 말한다. 주로 iss (생성자), exp (만료 기간), sub (주체), aud (대상), 등등 여러가지의 유용한 정보를 담고 있다.
예:
{
"sub": "1234567890",
"name": "John Doe",
"admin": true
}
Signature
Header와 payload를 각각 base64로 인코딩한 후 콤마로 이어붙이고 secret key를 더한다. 그리고 이를 header에 명시된 알고리즘으로 암호화한 값을 담는다. 예를 들어, HMAC SHA256 알고리즘을 사용한다면, signiture는 아래와 같은 방법으로 생성된다.
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)
출처: https://jwt.io/introduction
Signiture는 메시지가 변하지 않았다는 것을 증명하기 위해 사용되기도 하고, 토큰이 private key로 서명된 경우에는, 토큰의 전달자를 알아내기 위해 사용될 수 있다.
JWT 공식 사이트에 들어가서 아래와 같이 인코딩된 토큰을 작성하면, 유효한 signiture인지 판별하는 debugger를 제공한다. 궁금하다면 본인만의 JWT을 생성한 후, 테스트해보면 좋을 것 같다 (물론, 민감한 정보를 포함하는 토큰으로 테스트는 절대 삼가하자).
Access Token & Refresh Token
Access Token 작동 원리
위의 방식으로 받은 토큰은 언급했듯이 서버 측 리소스에 접근할 때 클라이언트 본인을 인증할 수 있는 access token으로 동작한다.
클라이언트가 로그인 통해 인증을 성공하면, 서버는 해당 클라이언트에 access token을 전달한다. 그 후에 클라이언트는 서버에 요청 시, HTTP header에 access token을 포함하고, 서버는 이를 통해 해당 요청의 전달자가 누구인지 파악할 수 있다.
그런데, 클라이언트가 토큰을 받은 시점부터 이 토큰은 탈취 당할 위험이 생긴다. 이 토큰을 탈취한 사람은 마치 신뢰할만한 사람인 것처럼 인증을 통과할 수 있고, 위에서 언급한 것처럼 서버는 토큰의 본래 주인인 클라이언트와 탈취한 사람을 구분할 수 없기 때문에 보안에 큰 문제가 생긴다.
따라서, 서버는 클라이언트에게 전달하는 토큰에 유효 기간을 두어야한다. 하지만, 이 유효 기간을 어떻게 설정하느냐에 따라서도 보안에 큰 차이가 생긴다.
만약 유효기간을 매우 짧게 설정한다면, 탈취 당한 토큰이 이미 유효하지 않을 가능성이 커지기 때문에 보안에 조금 더 유리하다는 장점이 있다. 하지만, 토큰을 재발급 받기 위해 클라이언트가 재로그인 해야하는 상황이 자주 생기므로, 사용자 경험적으로 좋지 않고, 서버 또한 더 많은 요청을 처리해야 하는 부담이 생기게 된다. 그렇다고 무작정 토큰의 유효기간을 늘린다면 사용자와 서버의 부담은 줄어들 수 있겠지만, 반대로 보안에는 더 취약해진다는 단점이 생긴다.
Refresh Token 매커니즘
그래서 access token의 유효기간을 짧게 유지하고 이 보다 더 긴 유효기간을 가지는 refresh token을 같이 사용하는 것이다. 이렇게 하면 access token의 유효기간이 만료되어도 refresh token을 이용하면 재로그인을 할 필요 없이 access token을 재발급 받을 수 있다 (물론, refresh token의 유효기간도 만료되면 다시 로그인을 시도해야 한다).
Refresh Token의 문제점
Refresh token도 탈취 당할 위험에 노출이 되어있다. 그렇기 때문에, 이를 사용한다고 보안 문제를 완전히 해결할 수 있는 것은 아니다. 물론 이에 대한 예방책은 존재한다. IETF의 문서에서는 만약 refresh token을 browser-based application에 발급하는 방식을 사용한다면, access token을 재발급할 시 refresh token 또한 반드시 재발급해야 한다고 명시해두었다.
Authorization servers SHOULD NOT issue refresh tokens to browser-based applications.
If an authorization server does choose to issue refresh tokens to browser-based applications, then it MUST issue a new refresh token with every access token refresh response. Doing this mitigates the risk of a leaked refresh token, as a leaked refresh token can be detected if both the attacker and the legitimate client attempt to use the same refresh token.
References
'Network' 카테고리의 다른 글
[Network] 실시간 통신을 위한 여러가지 방식들 (0) | 2024.09.20 |
---|---|
401 Unauthorized vs 403 Forbidden (1) | 2023.12.25 |
[RESTful API] RESTful API란 무엇인가? (0) | 2023.08.03 |