Debugging Sparrow

JWT RS256

2019/01/22 jwt hs256 rs256 Google OpenID Connect

RS256 알고리즘을 활용하여 리소스 서버와 인증 서버가 Secret을 공유하지 않고 토큰을 검증하는 방법에 대해서 알아봅니다.

JWT(JSON Web Token)

JWT에 대해선 따로 소개를 하지 않아도 많은 분들이 알고 계실 거라 생각됩니다. 그래도 이 포스트를 읽기 위해 중요하다고 생각하는 특징은 Self-Contained(자가 수용적)이라는 것입니다. 필요한 정보를 자체적으로 담고 있다는 것인데, 토큰이 그 자체로 의미 있는 정보를 담고 있어서 추가적인 작업, 리소스가 필요하지 않습니다. 그런데 JWT를 예제만 보고 현실에서 사용하려다 보면 의문점이 생깁니다. 우리는 Self-Contained의 장점을 충분히 살리고 있는 걸까요?

리소스 서버와 인증 서버가 떨어져 있는 형태

리소스를 주는 리소스 서버와 인증 서버가 같이 있다면 문제가 되지 않습니다. 하지만 리소스 서버와 인증서버가 떨어져 있는 형태(Oauth 등)에서 리소스 서버는 토큰의 무결성을 검증하는 방법에 대해 생각해야 합니다. 검증을 위해선 Key 혹은 Secret이 필요하기 때문입니다. 쉽게 생각할 수 있는 방법으로는 세 가지가 있습니다.

  1. 리소스 서버가 인증서버에게 Key, Secret을 공유 받는다.
  2. 리소스 서버에서 토큰이 올 때마다 인증 서버에 토큰을 검증하는 요청을 한다.
  3. 리소스 서버들의 가장 앞에 API Gateway를 통해 토큰을 검증 후 리소스 서버에 요청을 넘긴다.

1번 접근법은 사실 실제론 고려조차 되지 않습니다. 인증 서버를 직접 구현하는 게 아닌 Google의 OpenID Connect를 이용한다고 했을 때 Google에게 Key, Secret을 공유 받을 수 있을까요? 인증 서버를 직접 구현하더라도 모든 리소스 서버가 Key를 공유 받는다고 하면 리스크가 너무 큽니다.
2번 접근법은 꽤나 그럴듯합니다만, Self-Contained 한 토큰을 인증서버에 요청을 날리는 것 자체가 불필요한 리소스를 쓰는 느낌이 들며 모든 리소스 서버에서 이를 위한 구현을 해야 합니다.
3번 접근법은 API Gateway를 활용하는 아키텍처에서는 2번 접근법의 구현상 단점을 충분히 없애는 것 같지만 마찬가지로 매번 인증서버에 validate 요청을 날리는 오버헤드가 있습니다.

위의 세 가지 모두 제가 Document를 제대로 읽지 않아서 생긴 잘못된 접근법들(제가 실제로 했던)입니다. 예제 코드에서 흔히 HS256(HMAC, SHA-256) 알고리즘을 서명에 사용하고 그것을 그대로 의심 없이 소스에 사용하였기 때문이죠. 즉, JWT의 문제가 아닙니다. HS256 등의 대칭키 알고리즘이 리소스 서버와 인증 서버가 떨어져 있는 형태에 적합하지 않기 때문입니다. RS256(RSASSA-PKCS1-v1_5, SHA-256) 등의 알고리즘을 통해 리소스 서버와 인증 서버가 떨어져 있는 형태에 올바른 방법으로 사용할 수 있습니다.

HS256 vs RS256

RFC7518에 정의된 내용에 따르면 HS256은 SHA-256을 활용하여 해쉬하는 HMAC 알고리즘을 의미합니다. HMAC은 signature 생성에 secret shared key를 이용하기를 이용하기 때문에 리소스 서버와 인증 서버가 떨어져 있는 형태에 적합하지 않습니다. 반면에 RS256은 SHA-256을 해쉬 함수로 사용하는 RSASSA-PKCS1-v1_5 알고리즘입니다. RSASSA-PKCS1-v1_5은 signature 생성에 RSA private key를 이용하고 검증에는 RSA public key를 이용하기 때문에 인증 서버는 secret을 리소스 서버와 공유하지 않아도 됩니다. 즉, 리소스 서버에서는 JWT를 인증 서버에서 주기적으로 업데이트 받은 RSA public key로 검증할 수 있습니다. 즉 리소스 서버는 인증 서버에 요청하지 않고도 Self-Contained 한 토큰을 활용할 수 있습니다.

JWK

RS256을 위해선 공개키가 필요합니다. 그 공개키는 JWK에 나타나 있습니다. RFC7517에 정의된 내용을 통해 JWK에 대해 알 수 있습니다. Google의 예시로도 살펴볼 수 있습니다. Google에서는 이 공개키를 하루에 한 번씩 바꾸므로 Caching을 통해 Google의 인증서버에 토큰 인증을 요청하는 과정 없이 local에서 토큰의 검증이 가능합니다.

느낀점

예제만 보고 따라 하지 말자, Document를 꼼꼼히.


Author: dbgsprw

Link: https://dbgsprw.github.io/2019/01/22/JWT-encrypt-algorithms-HS256-RS256/

Copyright: All articles in this blog are licensed under CC BY-NC-SA 3.0 unless stating additionally.

< PreviousPost
Python3 m option and Import
NextPost >
API Gateway with Zuul 2.0 (2)
CATALOG
  1. 1. JWT(JSON Web Token)
  2. 2. 리소스 서버와 인증 서버가 떨어져 있는 형태
  3. 3. HS256 vs RS256
  4. 4. JWK
  5. 5. 느낀점