본문 바로가기

Golang/etc

Apple 로그인 JWT, JWK

728x90
반응형

애플로그인 구현을 위해서 꼭 알아야하는 jwt

굳이 애플로그인이 아니어도 필요하기 때문에 먼저 개념을 정리하고 apple 로그인 구현까지 포스팅해보려 한다. 

 

JWT (JSON Web Token)

- jwt는 header, playload, signature 3 부분으로 이루어져있다. 

- 이를 base64 encoding 한 후 concat, 즉 문자열을 합친 것이 jwt이다. 

- 토큰에 포함된 내용들은 암호화 되어있지 않기 때문에 누구나 확인 가능하다. 

- signature를 이용하여 해당 토큰이 실제로 원래 발급자가 발급했던 유효한 토큰인지 검증 할 수 있다. 

- signature 생성을 위한 알고리즘은 발급시에 선택가능하다 (RS256, ES256, HS256 등)

 

https://jwt.io

 

JWT.IO

JSON Web Tokens are an open, industry standard RFC 7519 method for representing claims securely between two parties.

jwt.io

jwt.io에 가면 인코딩된 토큰을 디코드 해서 내용을 확인할 수 있다. 

위 사이트에서 볼 수 있는 예제이다. 

 

앞서 설명했듯이 header, payload, verify signature로 구분되어 있는데 각 부분에 대한 설명은 뒤에서 더 자세히 하겠다. 

 

HEADER

- "alg" : signature 생성을 위해 사용한 알고리즘을 명시한다. 

- "typ" : 타입을 나타낸다. 

- "kid" : 서명시 사용하는 키 (public / private Key)를 식별하는 값이다. 혹은 key가 게속 변경되는 경우 kid 를 사용한다. 

 

PAYLOAD 

- jwt의 내용으로, payload에 있는 속성들을 Claim 이라고 한다. 

- "iss" : jwt를 생성한 곳

- "iat" : jwt 생성시간

- "exp" : jwt 만료시간

- "aud" : 유저 인증을 위해 jwt를 사용하는 경우 payload에 토큰을 발급받은 사용자ID 값을 포함한다.

-> jwt를 이용하여 application server에 요청, server에서 jwt signature 유효성을 확인하고, 유효하다면 payload에서 사용자ID 값을 읽어 들여서 요청을 보낸 사람이 어떤 사용자 인지 인증 할 수 있다. (애플로그인에서 사용하는 방법)

- 등등 key, value의 형태로 이루어져있고 생성하는 사용자가 직접 필드를 추가해서 정보를 추가할 수 있다. 

- base64 url-safe로 인코딩한다. 

 

SIGNATURE

- header, payload의 값이 변조되지 않았는지 확인하기 위해 필요한 서명이다. 

- RS256 : 비대칭키 방식으로 private Key를 사용해서 암호화 한다.

- jwt를 발급한 서버뿐만 아니라, jwt를 받아서 사용하는 어떤 주체라도 signature 유효성 검증이 가능하다.

- 일반적으로 public key는 jwt를 발급한 서버에서 JWK (JSON Web Key)에 정의된 방식을 통해 공개적으로 제공한다. 

- 애플이 이 JWK를 제공하고 있고, 로그인 검증시에 필요하다. 

 

JWK (JSON Web Key)

- JWT 서명 검증을 위한 정보를 담은 JSON 표준이다. 

- JWT를 사용하는 서비스들이 public key를 제공하기 위해 key에 접근할 수 있는 URL을 제공하고있다. 

- 애플의 경우 아래 링크에 접속하면 3개의 키를 제공하는 것을 확인 할 수 있다. 

 

https://appleid.apple.com/auth/keys

 

 

다음 포스팅에서 자세히 설명하겠지만 애플로그인의 경우 id_token의 서명을 해독할 수 있는 public key를 위와 같은 형태로 제공하고 있다. 3개의 키 중 kid가 일치하는 키의 정보로 서명을 해독해야한다. 

 

아주아주 귀찮고 까다롭다. 다른 oauth2.0 로그인의 경우 절차가 생각보다는 간단한데 애플은 그렇지 않다. 

클라이언트 서버단에서 처리해주어야할 절차가 복잡하다. 

사실 나같은 초보 개발자는 처리절차를 구현하는 것도 힘들지만,

jwt, jwk의 개념을 제대로 이해하고 플로우를 그려가면서 구현해야하기 때문에 조금 더 벅찬거 같다. 

 

각설하고

 

JWT 구성 요소에 대해 설명해보면

- "kty" : 키 타입

- "kid" : 앞서 jwt의 header에 kid가 들어가는 경우도 있다고 설명했는데,

여러개의 public key중에서 jwt와 jwk의 kid가 일치하는 것을 사용해서 서명을 verify해야한다. 

애플로그인의 경우 3개를 제공하고 있다. 

- "alg" : 사용한 알고리즘

- "use" : public key가 어떤 용도로 사용되는지 명시

- "n" : RSA modulus

- "e" : RSA public exponet

-> 위 두 가지 n, e 의 값을 알면 사실상 public key를 구현할 수 있다. 

애플로그인의 경우 kid로 어떤 public key를 사용할건지 결정하고, 그 키의 n, e 값을 디코딩하여 signature를 verify할 수 있는 key로 변환해주어야 한다.

 

 이 과정을 전부 거쳐야 apple에서 보낸 id_token 을 verify할 수 있다. 

 

그리고 그게 끝이 아니라.....

다시 내가 가지고 있는 private key를 이용해서 jwt signature를 완료하고 그걸 apple쪽에 다시 전달하여 사용자 인증을 완료해야한다.

 

애플 미워..

 

근데 사실 이걸 하면서 공부가 진짜 많이 되긴했다. 

미워.. 아니야 안미워 고마워 :) 

 

 

ㅋㅋ 

 

 

 

다음 포스팅에서는 그래서 코드로 어떻게 구현할 것인가를 적어보겠다.

 

 

728x90
반응형

'Golang > etc' 카테고리의 다른 글

tcp/ip -02,03  (0) 2022.06.27
tcp/ip - 01  (0) 2022.06.22
Golang Apple Login (애플 로그인)  (0) 2022.06.14
golang .env 파일 환경변수 셋팅  (0) 2022.04.13
go init()  (0) 2022.04.13