728x90

로컬 로그인을 구현하지 않고, Oauth2.0을 통해 간편한 로그인만 구현하고 싶다는 생각이 들었다.
인터넷에는 Oauth2.0이 훨씬 쉽고, 보안 측면에서도 좋다고 한다. 막상 하다 보면 어렵다.

이 글은 지난 1달 동안 Oauth2.0에 관련하여 삽질한 것에 대한 이야기를 담은 것이며, 제 경험을 공유하여 Oauth2.0 입문자들이 조금 더 쉽게 이해하길 원하며 적고 있다. 물론 누군가에게 검증받은 글이 아님으로 모든 것이 맞다고는 볼 수 없다.

먼저 JWT가 무엇인지 알아보고, JWT를 이용하여 지칭한 AccessToken과 refreshToken을 알아본다. 그 후 직접적으로 사용하는 JWT 이용을 알아본다. 그 후 우리가 진정으로 하고 싶은 SNS에서 제공해주는 Oauth2.0에 대해 알아본다.

1. JWT?

Oauth2.0을 사용하기 위해서는 Jwt란 것을 알아야한다. jwt는 Json Web Token이다. https://jwt.io/에 가면 payload에 값을 담아서 jwt를 생성해보는 실습을 할 수 있지만, 이런 개념은 카카오, 네이버, 구글을 사용 시엔 덜 중요하다. 만약 내가카카오, 네이버, 구글과 같이 직접 jwt를 발행해준다면 알아야하는 내용이지만, 우리는 3사에서 직접 jwt를 발급해주니 3사가 넣은 내용이 토큰에 담겨 있겠구나 정도만 알아두자.

 

JWT.IO

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

jwt.io

더보기

하지만 궁금한 사람도 있을 수 있으니 간단하게 알아보자.

먼저 JWT에 들어가면 아래와 같이 HEADER와 PAYLOAD, VERIFY SIGNATURE가 있다는 것을 알 수 있다.

헤더에 들어가는 alg는 우리가 사용하는 alg를 말하고 있고, 페이로드에는 우리가 담고 싶은 값을 담아 두면 된다.인증 시그니쳐는 우리가 사용하는 비밀 키가 들어간다.
즉, 우리가 설정한 Payload와 함께 헤더에 지정된 alg, 그리고 지정한 비밀키와 함께 아래와 같은 토큰이 생성된다.

우리가 카카오와 네이버와 같은 곳에 받는 jwt 토큰은 헤더, 페이로드, 인증 시그니쳐로 이루어져있고, payload에는 각 회사가 설정한 내용, 비밀키가 지정되어있다는 것을 알 수 있다.

2. access_token과 refresh_token

jwt는 2가지의 token이 있는데 이는 맞는 말이며 틀린 말일 수도 있다. 왜 그런지 알아보자. jwt.io에 들어가면 jwt하나만 보여준다. 어라? access_token과 refresh_token으로 2가지 있는 것을 알고 있는데 jwt2.0엔 하나만 보여주고 있다. 사실 access_token과 refresh_token은 jwt이다. jwt를 풀어쓰면 json web token이니 jwt 자체가 토큰이란 것이다.

2가지 토큰이 있는 이유는, 사람이 jwt의 생존 기간을 수정하여, 생존 기간이 짧은 것은 access_token, 생존 기간이 긴 것은 refresh_token이라고 지칭한 것 뿐이다. 물론 jwt를 암호화에 쓰이는 시크릿 키가 다르게 들어가겠지만, 결국 사람이 이름을 지어준 것 뿐이다. 앞에 생존 기간이란 말이 나왔는데, 생존 기간이란 함은 토큰이 생존할 수 있는 기간으로 만약 2분의 생존 기간을 설정한 jw token이 있다고 하면 2분 뒤 이 token은 사용할 수 없게 된다. 뇌피셜이지만, 아마 검증 시 생존 기간을 검사하여 가려내는 것 같다.

jwt에 들어가는 시크릿 키

우리는 이제 access_token과 refresh_token이 시크릿 키가 다르고(같을 수도 있다.), 생존 기간이 다른 jwt라는 것을 알게 되었다. access_token은 사용자 인증에 쓰이고, 그래서 생존 기간은 refresh_token보다 짧다. refresh_token은 access_token이 만료되었을 때 access_token을 발급 시에 인증 과정에서 쓰인다.

3. 직접 JWT를 사용하는 방법은 무엇일까?

jwt를 발급하기 위해서는 서버에서 발급을 해줘야 할 것이다. 여러 언어에 라이브러리가 존재할 것이고 이를 이용하면 jwt를 만들 수 있다. express를 사용하여 jwt를 만드는 것을 해보았는데, 라이브러리 덕에 한 줄로 가능하며, 의외로 쉽다.
왜 이런 소제목을 만들어 사용하는 방법을 적는지 모르겠지만, 나중에 내용을 추가하거나 지우는 것도 한 방법일 것 같다.;;

4. 그래서 네이버, 카카오, 구글은 어떻게 사용하는 거야?

사용하는 방법을 알아보기 전에 전체적인 흐름을 알아보고, 웹, 모바일 환경에서 어떻게 진행되는지 알아보자.
먼저 왜 다른 환경을 고려하고 있을까? 프론트에서 로그인을 구현할 수도 있고, 백에서도 가능하고 도대체 어디에 해야하는지 모르겠다. 왜 이런 생각이 들었는지 하나부터 끝까지 정리해보겠다.
1. 프론트에서 진행하고 token을 발급받는 code를 백에 보낸다. 그 후 백이 code를 받고 token을 발급한다.
2. 프론트에서 code와 token까지 발급받고 백으로 보낸다.
3. 백에서 code부터 토큰까지 발급받는다.
token 발급 시 밖으로 노출되면 안 되는 것들이 있음(시크릿 키)으로 백에 Token을 발급하는 것이 옳은 것 같다. 그럼 굳이 프론트에서 code를 받아서 백으로 보내는 귀찮음이 있어야할 까? 그냥 백에서 구현하면 안 되나?
확실한 방법은 없는 것 같다. 각 프로젝트 마다 방법이 다 다르고, 처음에 이런 이유 때문에 초보자들은 어려움을 느끼는 것 같다.

4-1. Passport

Express에서 Passport를 이용하여 code와 token을 받는 것이 한번에 이루어진다. 😮 이 때 accessToken과 RefreshToken이 나오는데 대부분 버린다.? 🤔🤔🤔🤔🤔🤔🤔🤔🤔🤔🤔🤔🤔🤔🤔🤔🤔🤔🤔🤔🤔🤔🤔🤔🤔
수많은 검색 중에 카카오에 추가적인 정보 요청을 하는 경우 저장하라고 되어있는데 조회를 안 하는건가?
Jwt 정의에서 accessToken을 가지고 검증한다고 하였는데, 그것을 버린다? 그렇다면 express에서 지원하는 session을 이용해서 사용자 검증을 하는 걸까? token 검증만 하면 굳이 세션을 가지고 있어야 할까? 그렇다면 내가 직접 Jwt 토큰을 발급한다면 어떻게 될까? 그럼 되는거 아닐까?

4-2. Nest Js

Express의 상위 버전?이라고 말할 수 있는 NestJs의 공식 사이트에서는 순수 JWT를 이용한 로그인 구현을 소개하고 있다. < 한글로 번역된 사이트도 있으니 참고할 것>
NestJS 공식 문서를 따라 하다 보면 JWT를 직접 생성하고, 프론트로 보내주고, 백에서 받아 인증하는 것까지 쉽게?... 아니고 할 수 있다. 하다보면 드는 생각이 세션을 유지할 이유가 없다라는 것이다. JWT 자체에 생존 기간이 존재함으로 생존 기간이 만료되면 자동으로 거부된다. 따로 세션을 유지할 필요가 없고, JWT만으로 로그인 검증이 가능하다는 점이 참 좋은 것 같다. 이것이 옳은 것인지는 모른다.

4-3. 다시 Passport

생활코딩에서는 session을 이용하여 인증을 유지한다. 그렇다면 2가지 방법이 존재하는 것이 아닐까?
생활코딩과 같이 세션을 유지하거나, 아니면 우리 어플에 맞게 jwt를 발급하여 검증하거나, 아니면.. accessToken과 refreshToken을 받은 것을 이용한다거나 만약 3번째 방법을 이용한다면 내가 직접 검증 시 이 token이 어느 회사 token인지 몰라 조금 고민이 될 것 같다.

반응형

+ Recent posts