Signature 검증 없이 JWT 파싱하기

고범수·2023년 8월 1일
3

Spring Boot

목록 보기
6/12

현재 상황

Google One Tap Login 을 이용하여 안드로이드 앱에서 ID Token이 발급된 상태이다. Google developer 사이트에 따르면 백엔드에서는 클라이언트에서 전송해오는 ID Token을 검증해야 한다고 한다.

https://developers.google.com/identity/one-tap/android/idtoken-auth?hl=ko


developer 사이트 예시로는 Google에서 제공하는 라이브러리를 이용하여 ID Token을 파싱하고 검증하고 있지만, 백엔드 서버 자체적으로 Access/Refresh Token을 생성할 때 JJWT 라이브러리를 사용하고 있었기 때문에 JWT관련 라이브러리를 둘 씩이나 사용하고 싶지 않았다. 그래서 JJWT를 이용해서 ID Token을 검증하려고 하였다.

Naver, Kakao를 통한 Open ID Connect 로그인을 구현할 예정이기 때문에 Google에서 제공하는 라이브러리가 아닌, 범용 라이브러리를 사용하고 싶었던 마음도 있다.

과정

우선 클라이언트가 OIDC(Open ID Connect)를 통해서 발급받은 ID Token을 Spring Boot로 구현한 서버에서 검증해야 한다. ID Token은 JWT 토큰이고, 비공개 키로 서명이 되어있다. 따라서 해당하는 비공개 키의 대응하는 공개 키로 검증해야 한다. 이 공개 키는 탐색 문서에서 접근방법이 설명되어 있다.



이제 우리는 jwks_uri의 value인 "https://www.googleapis.com/oauth2/v3/certs" 에 공개 키가 있음을 알았다.

위 주소로 접근하면 이 같이 두 개의 공개키에 대한 정보가 JSON 형태로 주어진다. 문서에 따르면 프론트에서 전송되어 온 ID Token의 header에 세팅 되어있는 kid 값과 일치하는 kid 값을 가지는 공개키 정보를 이용하여 ID Token을 검증하면 된다고 한다.

문제

그런데 JJWT 라이브러리로 ID Token을 파싱하여 kid를 얻어내려고 하니 우선 Signing Key를 명시하라는 예외가 터졌다. 여러 방법을 검색해 봤지만 Signing Key 없이(서명 검증 없이) 파싱하는 방법은 지원하지 않는 듯 했다.

대안

그래서 다른 JWT 라이브러리를 찾아본 결과, Nimbus-jose-jwt 를 사용하기로 하였다. 간단한 테스트 코드를 통해 서명 검증 없이 파싱하는 것, 파싱한 뒤 공개 키로 검증하는 것이 모두 가능함을 확인하였다.

https://connect2id.com/products/nimbus-jose-jwt






이제 JJWT 대신 Nimbus-jose-jwt를 이용하여 토큰 검증, 발급 로직을 구현하면 문제 없이 구동될 것으로 예상된다.

ID Token의 검증이 성공하면, ID Token의 Claims에 접근해서 회원 정보를 얻어내고, 가입절차를 진행한다. 로그인 로직도 유사하게 구현하여 자체적으로 Access/Refresh Token을 발급, 클라이언트에 전송하면 Google One Tap Login을 통한 회원 가입/로그인 기능이 구현 완료될 것이다.

참고

Json Web Token의 구조

https://jwt.io/

0개의 댓글