[Web] JWT vs OAuth

coderH·2023년 4월 2일
0

JWT와 OAuth는 개발을 공부하다보면 많이 접하게 되는데 두 개념 모두 인증을 위해 사용됩니다.

오늘은 이 두 요소에 대한 개념과 차이점에 대해 다뤄보겠습니다.

JWT (JSON Web Token)

JWT는 서버에서 생성하는 토큰으로 두 엔티티(클라이언트와 서버) 간에 정보를 공유하기 위해서 사용되는 인터넷 표준입니다.

JWT를 사용하면 토큰을 통해 사용자를 검증하기 때문에 서버에서 DB 쿼리를 생성하거나 검증 부분에 관여를 할 필요가 없어 서버의 부담을 줄일 수 있다는 장점이 있습니다.

또한, 토큰은 JSON형식으로 되어있으며 토큰 내부에는 사용자에 대한 정보가 담겨있습니다.

토큰 발급 과정 (JWT Flow)

JWT Flow

JWT 토큰은 클라이언트가 인증 서버에 로그인을 시도하면 인증 서버에서 사용자를 검증한 뒤 JWT 토큰을 생성합니다.

이후, 해당 토큰을 클라이언트에게 전달하며 클라이언트는 Resource Server에 요청할 때 토큰과 함께 요청을 보내게 됩니다.

요청을 받은 Resource Server는 해당 토큰을 통해 사용자를 검증하고 적절한 응답을 합니다.

이 때, 상황에 따라 인증 서버와 리소스 서버를 위 사진처럼 분리하는 경우도 있고
리소스 서버에서 JWT토큰을 직접 생성해 반환하는 경우도 있습니다.

만약, 인증 서버와 리소스 서버가 분리된 경우라면 리소스 서버에서 토큰을 복호화하기 위해 인증 서버측으로 토큰 검증을 위한 API 요청을 보내거나 혹은 API Key, 토큰등을 저장하고 관리하는 별도의 도구를 사용하기도 합니다.

토큰 내부 구조

토큰 내부 구조

JWT토큰은 Base64라는 방식으로 인코딩되며 크게 Header, Payload, Signature 3개의 영역으로 이루어져있고 이들은 각각 "."으로 구분합니다.

토큰은 서버가 아닌 클라이언트에 저장되어 있으며 HeaderPayload 영역의 경우 별도의 암호화과정이 이루어지지 않습니다.

따라서, 언제든지 노출될 수 있기 때문에 토큰 내부에는 사용자의 민감한 정보를 포함하면 안됩니다.

즉, 토큰은 사용자를 식별하는 목적으로만 사용합니다.

Header 영역

토큰의 타입, 서명할 때 사용된 해시 알고리즘 등 토큰과 관련된 내용이 포함됩니다.

Payload 영역

서버에서 첨부하는 사용자의 권한 정보와 토큰 발급자, 토큰 대상자, 만료시간, 발급시간 등의 데이터가 포함되어 있는 영역으로 여기에 속한 각 요소들을 JWT Claim이라고 합니다.

이러한 클레임들은 객체처럼 key와 value 한 쌍으로 구성되어 있으며
key는 문자열 타입만, value는 JSON에서 지원하는 데이터 타입이라면 모두 사용 가능합니다.

JWT Claim은 Registered, Public, Private 3가지로 분류하며 PublicPrivate을 묶어 Custom Claim이라고도 합니다.
참고로, Custom Claim은 최대 100kb까지 설정이 가능합니다.

  • Registered Claim
    토큰에 관련된 정보를 담는 영역으로 JWT의 목적인 간결함을 위해 key는 보통 3자리의 문자열로 표현합니다.

    key의 명칭은 RFC에 정의된 규칙에 따라 작성되어야 하며 자주 사용되는 요소들은 아래와 같습니다.
Claim NameDescription
iss(issuer)토큰 발급자
sub(subject)토큰 제목
aud(audience)토큰 대상자
exp(expiration)토큰 만료시간
nbf(Not Before)토큰의 활성날짜로 해당 시간 이전에는 토큰을 사용할 수 없습니다.
따라서, 토큰을 발급할 때 발급 당시의 시간 혹은 그 이후로 설정해주어야합니다.
iat(Issued At)토큰 발급시간으로 이 값을 통해 토큰의 age(발행이후 현재까지의 시간)를 계산할 수 있습니다.
  • Public 영역
    사용자의 이름, 이메일 주소와 같이 일반적인 정보를 담는 영역으로 의미와 사용법에 대해서는 RFC가 아닌 IANA의 JWT클레임 레지스트리에 정의되어 있습니다.

    클레임 간의 충돌을 방지하기 위해 해당 사용법을 준수해주어야 합니다.

  • Private 영역
    정보 사용자와 제공자간에 임의로 정한 클레임을 말하며 Public Claim보다 더 구체적인 데이터를 포함할 때 사용됩니다.

Signature 영역

토큰에 대한 무결성을 확인하는 목적으로 HeaderPayload영역의 정보들을 바탕으로 시그니처가 생성됩니다.

비대칭키 방식으로 암호화가 이루어지며 리소스 서버에서 토큰을 받으면 이 Signature 영역을 복호화한 뒤 토큰의 변조 여부를 파악합니다.

HeaderPayload의 원본 데이터를 바탕으로 암호화를 진행하기 때문에
추후 두 영역에 변조가 발생했더라도 복호화 과정에서 원본 데이터와 일치하는지를 검사하므로 토큰의 변조 여부를 파악할 수 있습니다.

즉, 토큰은 Signature영역을 제외하고는 암호화되지 않고 인코딩만 이루어지며 Base64라는 방식은 쉽게 디코딩할 수 있기 때문에 언제든지 공격자에 의해 값이 노출 될 위험이 있다는것을 명심하고 사용자의 민감한 정보를 토큰에 포함하지 않도록 주의해야 합니다.

JWT의 장단점

  • 장점
  1. 토큰을 사용하지 않고 세션 방식으로 사용자를 검증하는 경우, 서버에서는 클라이언트의 로그인에 대한 상태를 저장해두고 있어야 하는데 이는 서버 혹은 DB의 메모리를 추가적으로 사용하게 되어 사용자가 많다면 서버에 부담이 될 수 있습니다.
    하지만, JWT를 사용하면 이러한 작업이 필요하지 않으므로 서버의 부담을 덜 수 있습니다.

  2. 암호화 된 Signature영역을 통해 토큰의 변조 여부를 감지할 수 있습니다.

  • 단점
  1. 토큰이 탈취되는 경우 만료될 때까지 대처할 수 없습니다.
    이러한 상황을 방지하기 위해선 JWT 블랙리스트를 구현해야 하며 이는 추가적인 작업을 필요로 합니다.

  2. 또한, 토큰이 탈취된다면 공격자는 사용자의 신원을 가장해 사용자 계정으로 임의의 작업을 수행할 수도 있습니다.

  3. Payload 영역은 암호화 되어있지 않아 민감한 정보는 포함할 수 없다는 단점이 있습니다.

  4. 토큰에 많은 양의 정보를 포함하는 경우 쿠키 및 세션의 크기보다 더 커져 과도한 통신 비용을 유발할 수 있습니다.

OAuth (Open Authorization)

OAuth는 토큰 기반의 인증 프로토콜로서 웹, 모바일 등 다양한 환경에서 사용되고 있습니다.

페이스북으로 로그인하기, 구글로 로그인하기 등 SNS 계정 정보로 로그인할 때 사용되는 프로토콜로 서드파티 라이브러리에 유저의 정보를 공유할 때 사용되며 사용자는 자신의 ID, PW와 같은 민감한 자격증명 정보를 신뢰하기 어려운 서드파티 라이브러리에 제공하지 않아도 해당 서비스를 이용할 수 있습니다.

유저의 정보를 가지고 있는 Resource Server는 이미 검증 된 클라이언트에게만 유저의 동의하에 특정 계정 정보를 공유하며 닉네임, ID와 같은 일반적인 정보 외의 민감한 개인정보는 노출하지 않습니다.

OAuth에서 사용되는 용어

  • Resource Owner (= End-user)
    서비스 제공자가 제공하는 계정 정보의 소유자이자 해당 클라이언트 애플리케이션을 사용하고자하는 유저를 말합니다.

  • Resource Server
    실제 유저의 계정 정보를 가지고 있는 서버로 구글, 깃허브, 페이스북 등의 서비스가 대표적입니다.

  • Authorization Server (= Service Provider)
    유저의 접근 권한 승인 요청과 인증 코드 및 액세스 토큰 발급 등을 담당하는 서버입니다.

  • Client (= Consumer)
    유저에게 권한을 받고 유저의 계정 정보를 필요로하는 웹사이트 혹은 애플리케이션을 말합니다.

  • Client ID (= Consumer Key)
    인증 서버가 클라이언트를 식별하기 위해 발급하는 고유의 키로 해당 키는 클라이언트 애플리케이션에서 보관합니다.

  • Client Secret (= Consumer Secret)
    클라이언트가 액세스 토큰을 요청할 때 자신임을 인증하기 위한 키로 유저의 패스워드와 같은 역할을 합니다.
    이 또한, 인증 서버가 발급하며 클라이언트 애플리케이션에서 보관합니다.

  • Auth Code (= Request Token)
    클라이언트가 리소스 서버에게 유저의 동의를 받았다는 정보가 담긴 토큰으로 이는 추후 액세스 토큰으로 변환됩니다.

  • Access Token
    인증 후 클라이언트가 유저의 정보가 필요할 때마다 Resource Server에게 보내는 토큰이며 클라이언트에 저장되기 때문에 노출 될 위험이 있어 일반적으로 1시간 내외의 만료시간을 가지고 있고 만료시간이 지나면 재발급이 필요합니다.
    클라이언트가 Refresh Token을 가지고 있는 경우 재로그인 없이 해당 토큰만으로 액세스 토큰을 재발급 할 수 있습니다.

참고로, OAuth는 토큰에 대한 포멧을 정의해놓지 않았기 때문에 JWT와 함께 사용할 수 있으며, 이렇게 하는 경우 클라이언트와 서버간의 통신이 줄기 때문에 통신 비용을 감소시킬 수 있습니다.

OAuth Flow

OAuth Flow

  1. 유저가 클라이언트에 접속 후 로그인 버튼 클릭
  2. 클라이언트는 인증 서버에 인증 코드를 요청하고 유저는 리소스 서버의 로그인 페이지로 리다이렉트
  3. 사용자가 로그인 후 접근 권한 승인
  4. 클라이언트는 인증 서버로부터 인증 코드를 받고 자신의 Client ID, Client Seceret과 함께 액세스 토큰 요청
  5. 인증서버는 해당 값들을 검증한 뒤 액세스 토큰을 클라이언트에게 반환
  6. 클라이언트는 액세스토큰과 함께 유저의 특정 정보를 리소스 서버에게 요청
  7. 리소스 서버는 액세스 토큰을 검증하고 유저의 정보를 응답

OAuth의 장단점

  • 장점
  1. 대부분의 인증 서비스와 호환되는 표준화된 인증 프로토콜로 수용성과 호환성이 광범위하여 사용자는 충분한 기능과 옵션을 통해 유저의 계정 정보에 접근할 수 있습니다.
  2. 대부분의 프로그래밍 언어와 웹 프레임워크에서 테스트 되었기 때문에 환경의 제약을 받지 않습니다.
  3. 인증을 처리하는 코드와 클라이언트 코드를 분리할 수 있어 인증 코드를 처리하는 과정에서 애플리케이션에 영향을 주지 않습니다.
  4. 보안성이 높고 필드테스트가 잘 되어있습니다.
  • 단점
  1. Resource Server가 사용자의 로그인 및 활동 여부에 대해 추적할 수 있기 때문에 유저의 사생활이 노출 될 우려가 있습니다.
  2. OAuth Flow에 대해 이해해야 하므로 진입장벽이 다소 높은편입니다.
  3. 프론트와 백이 한 곳만 존재하는 단순한 애플리케이션이라면 오히려 복잡도를 증가시킬 수 있습니다.

JWT와 OAuth 비교

JWTOAuth
정의토큰의 형식접근 권한을 부여하기 위한 프로토콜
사용 예시주로 API통신웹, 브라우저, API, 앱 등 다양한 환경
메모리클라이언트의 메모리 사용서버와 클라이언트의 메모리를 모두 사용
사용 범위범위가 작고 한정되어 소규모 애플리케이션에 적합하다.유연하고 다양한 상황에 대응하기 쉬워 다양한 곳에서 사용 가능하다.
러닝 커브낮은 편높은 편
특징서버에서 세션 상태에 대한 유지없이 유저 인증 및 리소스에 대한 권한을 부여할 수 있다.서버에서 세션 상태를 유지해야 하지만 사용자의 ID, PW를 클라이언트 애플리케이션에 입력 할 필요없이 액세스 권한을 부여할 수 있다.

0개의 댓글