JWK 라이브러리를 만들어 보자! #6

김성현·2022년 1월 2일
0
post-thumbnail

6편 : 각 과정의 구현

지난 글로부터 많은 시간이 흘렀다.
블로그 글 상으로는 하루 차이지만 지난 글은 설계하면서 계속 작성하던 글이라 실제 간격은 더 길다.

그럼 이번 글에서는 encode, decode, fetch/fetcher, golang-jwt 기능들이 어떻게 구현되었는지에 대해 기술할 것이다.
각 기능들은 key, set으로 나눠서 어떻게 구현했는지 기술하겠다.

각 구성에는 대략 플로우차트를 그렸는데, 규칙을 딱히 엄격히 지키지는 않고 대강 이해가 될 정도로만 작성했다.

대략적인 형식은 아래와 같다.

함수 명으로 아예 작업이 나눠진 녀석의 경우는 보라 사각형
만약 동작에 대한 설명이 필요한 부분은 초록 메모
조건에 따라 흐름이 바뀔 때는 파란 마름모
만약 함수 이름이 소문자로 시작하는 경우 private 함수이다.
이렇게 표현하였다.

encode

encode - Key

외부에 공개된 함수는 EncodeKey, EncodeKeyBy 두개고 내부적으로 encode* 형태의 각 키 종류에 따른 함수들이 존재한다.

키는 kty에 따라서 분기가 많이 나뉘고 encodePri* 함수들은 먼저 자신의 동작을 수행한 후 encodePub*동작을 추가적으로 수행한다.

encode - Set


외부에 공개된 함수는 EncodeSet, EncodeSetBy각각에서 keys 필드에 있는 여러개의 각 키들을 EncodeKeyBy 함수를 이용해 인코딩한다. (정확하게는 json.Marshaler인터페이스를 이용해 하기는 한다.)

decode

decode - Key

과정은 각각 키 종류에 따라 나뉘고 각 키의 필요 필드들을 확인하며 진행한다.
다만 decodeKeyBy라는 private 함수가 존재하는 이유는 DecodeSetBy 함수에서 각 Key 별로 디코딩을 수행할때 중복동작을 죽이기 위해 나눠 놓았다.

decode - Set


기본적으로 JWK Set 자체가 간단해서 별로 대단한 작업은 없다.

fetch/fetcher

기본적으로 fetch는 HTTPS 요청을 받고 해당 Response가 http.StatusOK(200) 일때 해당 Response의 Body를 이용해 Decoding을 수행한다.

fetch - Set

fetch - Key

fetcher - Set


기본적으로 MustGet, ShouldGetGet 메서드를 편하게 사용하게 만드는 함수다.
따라서 중요한 것은 Get 메서드인데 해당 메서드는 캐시된 값이 없거나 캐시의 TTL(Time To Live) 이 지난 경우Refresh를 통해 값을 HTTPS를 통해 얻어낸다.
이후 해당 값을 설정된 TTL과 함께 저장하고 앞으로 TTL 내에 들어온 Get 요청은 해당 캐시값으로 리턴한다.

여기서 Fetcher 옵션에 따라 만약 Refresh 할 시기가 되더라도 Refresh를 안하고 조건에 따라 TTL을 연장시킬수도 있고 하여튼 다양한 설정이 가능하다.

golang-jwt

기본적으로 LetJWT 함수는 JWK 객체를 받아 JWT.Keyfunc 타입을 리턴해 준다.
만약 해당 타입이 유효하지 않다면 nil을 리턴한다.


사실 쓰고 보니 이번 글은 내용이 별로 없는 것 같다...

사실 이번 글은 소스코드를 진짜 많이 써서 블로그 글은 별로 없지만 실제로는 소스코드로 인해 좀 힘들었다.

정말... 우여곡절이 많았고 코드상으로 이야기할 점이 많지만 그런 부분은 후일담을 정리하면서 쓰려고 하므로 다음 글에서는 에러를 편리하게 처리할 수 있도록 만들기 위해 고민한 내용을 나누려고 한다.

다른것도 어려웠지만 에러메시지가 편리하고 문제가 생겼을 때 충분한 정보를 줄 수 있도록 만드는 것은 고민이 많이 되는 작업이였다.

다음 글에서는 그 과정에서 있었던 내 뻘짓과 어려움들을 공유하고자 한다.

profile
수준 높은 기술 포스트를 위해서 노력중...

0개의 댓글