ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 로그인 기능 구현의 과정 (feat. OAuth2.0 와 JWT)
    🏢 업무 리서치 기록 2022. 12. 16.

    회사에서는 Google Workspace를 도입해서 사용하기 때문에 사내 구글계정이 따로 있고 사내 내부 서비스의 대부분은 그 회사 구글 계정으로 로그인 할 수 있는 기능을 지원하고 있다. 그렇다면 어떻게 구글 로그인을 구현했을까?

     

    먼저 OAuth 인증 방식에 대해 알아보자

     

    OAuth 참여자

    • 리소스 서버 : Google, Facebook 같이 클라이언트가 제어하고자 하는 인증 자원(아이디, 비번)을 보유하고 있는 서버
    • 리소스 오너 : 자원의 소유, 실제 사용자
    • 클라이언트 : 리소스 서버에 접속해서 정보를 가져오고자 하는 웹 어플리케이션

     

    OAuth 과정

    1. 리소스 서버에 Client 등록해야 합니다. → GCP에서 등록 작업 수행

    이때 웹어플리케이션에서 인증을 수행할 URL과 Authorization Code를 전달받을 redirect URL를 입력합니다. 그러면 Client IDClient Secret을 얻을 수 있습니다. 그러면 아래 3개의 정보를 알게 되는데 이 3가지 정보를 가지고 다음 과정을 수행합니다.

    • Client ID : 클라이언트 웹 어플리케이션을 구별할 수 있는 식별자이며, 노출이 무방합니다.
    • Client Secret : Client ID에 대한 비밀키로서, 절대 노출해서는 안 됩니다.
    • Authorized redirect URL : Authorization Code를 전달받을 리다이렉트 주소입니다.

    GCP 콘솔에서 Client ID, Client Secret, redirect URL 이 3가지 정보로 실제 Access Token을 발급 받는 작업을 수행한다.

     

     

    2. Resource Owner의 승인

    프론트엔드에서는 웹 어플리케이션에서 로그인 버튼이 눌리면 리소스 서버에서 제공한 URL로 사용자가 이동해서 인증과정을 수행하도록 합니다. 이때 redirect URL을 함께 전달합니다.

     

    리소스 서버에서 최종적으로 승인을 마치면 전달한 redirect URL로 인증 코드가 함께 발급됩니다.

    그러면 클라이언트 서버는 ID, 시크릿키, 인증코드 이 세가지를 가지고 리소스 서버에 Access Token 발급을 다시한번 요청합니다. Access Token이 내려오면 클라이언트 서버는 앞으로 리소스오너의 리소스를 얻기 위해 리소스서버에 요청을 보낼때 이 Access Token을 가지고 이용하게 됩니다.

     

    Refresh Token

    보통 Resource Server는 Access Token을 발급할 때 Refresh Token을 함께 발급하는데 Resource Server의 API를 호출할 때는 Access Token을 사용하다가 Access Token이 만료되어 401 에러가 발생하면, Client는 보관 중이던 Refresh Token을 보내 새로운 Access Token을 발급받게 됩니다.

     

    3. Resource 요청

    그러면 Access Token으로 유저 이메일이나 프로필 이미지등의 정보(=Resource)를 받아와 나머지 인증과정을 수행하면 되는것이다.

     

    이 과정을 그림으로 보면 다음과 같다.

     

    사용하는 OAuth 2.0 서비스에 따라 code를 주고 받고 하는 5~6번의 과정은 생략될 수 있다고 한다.

     

    실제 프로젝트에서는 http://www.passportjs.org/packages/passport-google-oauth20/ 라이브러리를 사용해서 적용을 했는데 내부적으로 위의 일련의 과정들이 추상화 캡슐화 되어있어 인증을 위한 파라미터나, 콜백 세팅만 해주면 되었기 때문에 실제 정확히 리소스 서버와 클라이언트 서버 간 어떤 요청들이 주고 받아지는지 한눈에 보이지 않았다. 사용하기는 편했지만 개인적으로 궁금증이 있었는데 이렇게 정리를 한번 하니까 머릿속에 들어오는것 같다.

     

    로그인 상태를 유지하기 위한 방법

    실제 프로젝트에서는 크롬 창을 닫았다가 다시 열어도 로그인 된 상태를 유지하기 위해 JWT 토큰도 활용했는데 다음과 같은 방식으로 적용을 했다.

     

    프론트에서는 사용자가 로그인 버튼을 누르면 서버에서 제공한 구글 로그인 창을 띄우는 요청으로 리다이렉트 시킨다.

     

    유저가 구글 로그인을 성공적으로 인증을 마치면 유저 프로필 정보를 구글에서 부터 얻어와 서버에서는 그 프로필 정보로 유저 객체를 만들고 그 객체를 JWT 토큰에 담아 set-cookie 헤더 에 담아 응답 요청을 내린다.

     

    프론트에서는 set-cookie 응답 헤더를 읽어 서버로 받은 JWT 토큰값을 쿠키에 저장 해 가지고 있는다.

    그리고 앞으로의 인증에서는 그 JWT 토큰값을 이용한다. 이렇게 하면 한번만 구글 로그인을 수행해도 쿠키에 토큰이 남아 있을 경우 로그인 된 상태를 유지 할 수 있다.

     

    서버는 유저가 헤더에 실어서 보낸 JWT 토큰값과 JWT 토큰을 발급할때 사용했던 시크릿키로

    유저가 헤더에 실어서 전한 JWT 토큰이 유효한지 확인해서 만약 유효하지 않은 토큰 일 경우 인증실패로 처리한다.

     

    그리고 추가적으로 전달받은 JWT의 PAYLOAD 부분에 있는 유저 정보를 가지고 실제 유저 테이블에 등록된 유저인지 한번 더 확인하는 작업을 수행한다.

     

    JWT 토큰이란?

    JWT에는 HEADER, PAYLOAD, VERIFY SIGNATURE 이렇게 3부분이 있는데

     

    HEADER에는 암호화 알고리즘 방식이 기술되어있고,

    PAYLOAD에는 실제 전달하고자하는 JSON 데이터가 들어있다.

    그리고 PAYLOAD 와 시크릿 키로 VERIFY SIGNATURE 부분이 결정된다.

     

    그래서 PAYLOAD 부분이 바뀌면 VERIFY SIGNATURE 부분이 바뀌게 되고 이걸 통해서 JWT 토큰값이 유효한 값인지 변조된값인지 확인이 가능하다.

     

    JWT의 경우 단순히 base64 인코딩 되어있기 때문에 누구든지 다시 디코딩하여 PAYLOAD에 어떤 정보가 들어있는지 확인 하는것이 가능하다. 그래서 민감한 정보는 담지 말아야 한다. 즉 JWT를 사용하는 이유는 토큰이 유효한지 만 검사하기 위해 사용하는 것이다.

     

    보통 JWT 토큰이 탈취되는걸 막기위해 유효기간을 설정한다.

    유효기간이 지났을 경우 인증이 실패하게 되고, JWT refresh 토큰으로 JWT토큰을 재발급 받을 필요없이 다시 로그인 페이지로 리다이렉션 시켜서 OAuth과정부터 다시 실행하게 끔 한다.

     

     

    출처

     

    OAuth2 인증 방식에 대해 알아보자.

    OAuth2 인증 방식을 Google 서비스를 예제로 알아보자.

    velog.io

     

    댓글

GitHub: https://github.com/Yesung-Han