[TIL] JWT (JSON Web Token) ?

승은·2024년 11월 7일
0

TIL

목록 보기
22/23

왜 JWT가 만들어졌는가

HTTP는 state-less를 지향한다. (서버와 클라이언트 구조에서 서버가 클라이언트의 상태를 갖고 있지 않는 것)
-> state-ful방식(세션)보다 비교적 많은 양의 데이터가 반복적으로 전송되므로 네트워크 성능 저하가 될 수 있다.
-> 쿠키는 노출되었을 때 민감 정보까지 노출되기 때문에 보안이 좋지 않다.

쿠키와 세션의 단점을 보완하기 위해 등장한 하나의 인터넷 표준 인증 방식이다. 말 그대로 인증에 필요한 정보들을 토큰에 담아 암호화시켜 사용하는 것.

자세한 내용은 아래 링크 참고! 굉장히 구체적으로 설명되어있다.
https://brunch.co.kr/@jinyoungchoi95/1

공개/개인 키를 쌍으로 사용하여 토큰에 서명하면, 개인 키를 보유한 서버가 서명된 토큰이 정상적인 토큰인지 인증할 수 있다.

JWT의 구조

aaaaaa.bbbbb.ccccc

(.) 으로 구분되어 각 Header, Payload, Signature로 구성되어있다.

예시,

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

실제로 위와 같은 형태로 만들어진다. JWT 인코딩 링크

  • Header : 해시 알고리즘, 토큰 타입 정의
  • Payload : 전달하는 데이터 -> Key : Value 형태로 저장
    • Claim은 사용자가 원하는 키와 값을 구성할 수 있다.
    • Payload는 서명된 파트가 아니기 때문에, 민감한 정보는 담으면 안된다.
    • 디코딩하여 누구나 header와 payload에 담긴 값을 알 수 있다.
  • Signature : header, payload가 바뀌었는지 확인

stateful해야 하는 세션의 단점을 보완하기 위해 만들어진 JWT는 별도의 세션 저장소를 강제하지 않기 때문에 stateless하여 확장성이 뛰어나고, signature를 통한 보안성까지 갖추고 있다.

JWT 동작 원리

  1. Sliding Session -> 특정 유저에 대해 만료 시간을 연장시켜주는 방법
  2. Refresh Token

보통 두 가지 방법 중 하나를 사용한다. 오늘은 Refresh Token에 대해서만 기록한다.

JWT가 만료되기 직전의 유효시간을 보고 재발급을 어떤 방식으로 하는지가 중요하다. 이 방법은 가장 많이 사용하는 방법으로 JWT를 처음 발급할 때 Access Token과 함께 Refresh Token을 발급하여 짧은 만료 시간을 해결하는 방법이다.

1. 로그인 요청 시 서버는Access Token과 Refresh Token을 함께 발급
- Access Token은 짧은 유효 기간을 가지며 API 요청 시 사용된다.
- Refresh Token은 상대적으로 긴 유효 기간을 가지며 Access Token이 만료되었을 때 새 Access Token을 얻는 데 사용된다.
2. Access Token이 만료되었을 때 Refresh Token을 통해 갱신
- 클라이언트는 Access Token이 만료되면 저장된 Refresh Token을 이용해 서버에 새로운 Access Token을 요청한다.
3. 요청 시 Access Token을 사용
- 클라이언트는 이후의 API 요청마다 Access Toekn을 포함하여 인증을 수행한다.

이러한 흐름은 사용자가 재로그인하지 않고도 일정 시간 동안 인증 상태를 유지할 수 있도록 해주며 보안성을 높이기 위해 사용한다.

┌──────────┐                    ┌────────┐                       ┌───────────────┐
│ 클라이언트  │                    │  서버   │                       │ 데이터베이스     │
└──────────┘                    └────────┘                       └───────────────┘
      │                               │                                     │
      │ ID/PW로 로그인 요청              │                                     │
      │──────────────────────────────>│                                     │
      │                               │ DB에서 사용자 인증                      │
      │                               │────────────────────────────────────>│
      │                               │                                     │
      │                               │  Access Token 및 Refresh Token 생성   │
      │                               │                                     │
      │Access Token과 Refresh Token 반환│                                     │
      │<──────────────────────────────│                                     
                                                                          
       Access Token을 포함한 API 요청                                        
      │──────────────────────────────>│                                     │
      │                               │ Access Token 검증                    │
      │                               │────────────────────────────────────>│
      │                               │                                     │
      │  요청 처리 후 응답 반환            │                                     │
      │<──────────────────────────────│                                     
                                                                          
       Access Token 만료                                                  
       Refresh Token으로 새로운 Access Token 요청                             
      │──────────────────────────────>│                                     │
      │                               │ Refresh Token 검증                   │
      │                               │────────────────────────────────────>│
      │                               │                                     │
      │ 새로운 Access Token 반환         │                                     │
      │<──────────────────────────────│                                     │
      │                               │                                     │

Refresh Token과 Access Token을 사용하는 이유

세션 기반 인증 VS 토큰 기반 인증

이건 다른 블로그에서도 더 자세히 설명되어 있기 때문에 참고하기 !
가장 중요한 차이점은 JWT(토큰 기반 인증)는 서버가 상태 정보를 따로 저장하지 않고도 인증을 수행할 수 있다는 점이다. 이로 인해 서버 자원에 대한 부담이 줄어들어 확장성과 분산 시스템에서의 효율성이 높다. 또한, 보안성과 사용자 편의성을 동시에 확보할 수 있다.

Access Token ?

: API를 사용하기 위한 인증용 토큰

Refresh Token ?

: Access Token의 유효 기간 연장을 위한 토큰

방식이 세션 인증 방식과 크게 다르지 않다고 생각했다. JWT를 선택하는 이유는 "효율성"때문이라고 생각한다.

1. 확장성과 분산 환경에서의 장점

  • 세션 인증 방식에서는 서버가 세션 정보를 저장하고 관리해야하기 때문에 다수의 서버가 사용될 경우 각 서버에 동일한 세션 정보를 동기화하거나 별도의 세션 저장소를 사용해야한다.
  • 토큰 인증 방식은 토큰 자체에 이미 인증 정보를 담고 있기 때문에 동기화할 필요가 없다. -> stateless
  • 분산 서버나 MSA에서는 사용자 요청이 다양한 서버에 분산될 수 있는데 각 서버가 독립적으로 인증을 수행할 수 있어 보다 효율적이고 유연한 서비스 제공이 가능하다.

2. 클라이언트 중심의 인증 관리

  • 세션 인증에서는 세션이 만료될 때마다 서버에서 관리해야 하므로 서버에 부담이 커진다.
  • 토큰 인증에서는 클라이언트가 토큰을 직접 관리하기 때문에 서버가 클라이언트의 인증 상태를 유지할 필요가 없다.

3. 모바일 및 API 기반 애플리케이션에 적합

  • 세션 인증은 주로 웹 환경에 적합하게 설계되어있다. 쿠키 기반 세션 관리는 모바일 앱에서는 사용하기 어렵다.
  • 토큰 인증은 HTTP 헤더에 포함되어 API 호출 시마다 사용할 수 있다. 모바일 앱이나 Single Page Application같은 비동기 요청이 많은 환경에 적합하다.

4. 보안성

  • 세션 인증은 주로 쿠키에 저장되며 세션 고정 공격이나 CSRF와 같은 공격에 취약하다.
  • 토큰 인증은 JWT처럼 클라이언트 측에서 로컬 스토리지에 저장할 수 있으며, 토큰 서명을 통해 위조를 방지할 수 있습니다. 특히 각 토큰에 서명이 포함되어 있어 무결성이 보장됩니다.
  • Access Token과 Refresh Token을 별도로 관리할 수 있어 Access Token이 유출되더라도 Refresh Token을 이용해 새로 발급할 수 있어 리스크 관리에도 유리합니다.

5. Stateless 프로토콜의 이점

  • RESTful API와 같은 Stateless 설계를 지향하는 환경에서는 토큰 인증이 더 적합합니다.

6. SSO에 유리

  • 세션 인증은 특정 도메인 내에서만 유효한 쿠키를 사용하기 때문에 다양한 시스템 간 인증을 공유하기 어렵다.
  • 토큰 인증은 도메인에 구애받지 않기 때문에 다양한 시스템 간 통합 인증(SSO)에 유리하다. JWT는 SSO 환경에 널리 사용된다.

간단한 웹 애플리케이션이나 보안이 매우 중요한 환경(서버가 인증을 완전히 통제해야 하는 경우)에서는 세션 인증 방식이 더 적합할 수 있다. 토큰 인증 방식을 사용하는 이유는 위와 같은 추가적인 기능을 용이하게 제공하기 위해서이다.

참고
https://brunch.co.kr/@jinyoungchoi95/1
https://velog.io/@vamos_eon/JWT%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%80-%EA%B7%B8%EB%A6%AC%EA%B3%A0-%EC%96%B4%EB%96%BB%EA%B2%8C-%EC%82%AC%EC%9A%A9%ED%95%98%EB%8A%94%EA%B0%80-%EC%82%AC%EC%9A%A9%EC%B2%982

0개의 댓글