CS ( Computer Science )/네트워크 (Networking)

[Net] Token & JWT

JABHACK 2024. 12. 29. 20:40

Token

📌 Web Application이나 API에서 인증(Authentication)과 인가(Authorization) 과정에서 사용되며 사용자 또는 시스템의 신원과 권한을 증명하고 요청의 유효성을 검증하는 데 사용되는 디지털 문자열이다.

  • 인증(Authentication), 권한 부여(Authorization), 또는 데이터 교환을 위해 클라이언트와 서버 간에 사용되는 작고 안전한 데이터 객체입니다.
  • 로그인 인증이나 사용자 권한 관리를 할 때 토큰을 발급하고, 이를 통해 사용자를 식별하거나 인증 상태를 유지할 수 있습니다.
  • 토큰은 전체 데이터를 포함하지 않는다. 박스가 아니라 키라고 생각해야한다. 말 그대로 다른 클라에 요청할 시 사용가능한 인물인지에 대한 정보만 포함된다. 패킷이 아니다.

  • Token 생성 시 사용자의 고유한 정보를 포함한다.
  • 데이터베이스에 접근하지 않고 Token의 유효성만 검증한다.
  • Token의 단점
    1. Cookie/Session 방식보다 Token 자체의 데이터 용량이 많다.
      • 요청이 많아지면 그만큼 트래픽이 증가한다.
    2. Payload(전송되는 데이터)는 암호화되지 않아서 중요한 데이터를 담을 수 없다.
    3. Token을 탈취당하면 대처하기 어려워 만료 시간(30분)을 설정한다.

 

0. Token을 사용하는 이유

  1. Token은 서버가 아닌 클라이언트에 저장되어 서버의 부담을 덜 수 있다.
  2. Cookie는 웹 브라우저에만 존재하여 모바일 앱 등의 다양한 클라이언트에서 인증을 처리할 수 없다.
  3. Token 방식은 Stateless를 기반으로 하여 확장성이 뛰어나다.
  4. 인증된 사용자임을 확인하기 위한 고유한 서명을 포함하여 위조된 요청인지 확인할 수 있다.

 

1. 토큰의 기본 개념

토큰의 역할

  1. 인증(Authentication):
    • 사용자가 로그인하면 서버는 인증 결과를 기반으로 토큰을 발급합니다.
    • 클라이언트는 이후 요청마다 이 토큰을 사용하여 인증된 사용자임을 증명합니다.
  2. 권한 부여(Authorization):
    • 사용자가 어떤 리소스에 접근할 수 있는 권한이 있는지 확인합니다.
    • 예: "관리자" 권한을 가진 사용자만 특정 API에 접근 가능.
  3. 상태 정보 저장(State):
    • 토큰에 사용자 관련 정보를 포함하여 서버가 상태를 유지하지 않아도 인증 상태를 확인할 수 있습니다.

2. 토큰의 종류

a. 세션 토큰

  • 서버가 상태를 관리하며, 클라이언트는 세션 ID를 사용해 서버에 요청.
  • 예: session_id=abcd1234 쿠키로 저장.

b. JSON Web Token (JWT)

  • 클라이언트 측에서 상태를 관리할 수 있는 자체 포함(Self-Contained) 토큰.
  • 서명(Signature)을 통해 데이터의 변조를 방지.
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjEsIm5hbWUiOiJKb2huIERvZSJ9.s5t0sT5kdcfXb3wNkm2mOiVjHXe

c. OAuth 토큰

  • OAuth2.0 표준에서 사용하는 토큰으로, **액세스 토큰(Access Token)**과 **리프레시 토큰(Refresh Token)**으로 구성.

d. CSRF 토큰

  • CSRF(Cross-Site Request Forgery) 공격을 방지하기 위해 요청마다 고유한 토큰을 생성.

3. JSON Web Token (JWT)의 구조

JWT는 세 가지 부분으로 구성된 문자열이며, 점(.)으로 구분됩니다.

Header.Payload.Signature

Header (헤더):

  • 토큰의 메타정보를 포함.
  • 예: 알고리즘과 토큰 타입.
{
  "alg": "HS256",
  "typ": "JWT"
}

Payload (페이로드):

  • 사용자 정보와 클레임(Claim)을 포함.
  • 예: 사용자 ID, 권한 정보.
{
  "userId": 1,
  "role": "admin"
}

 

Signature (서명):

  • 토큰의 무결성을 검증하기 위한 서명.
  • 비밀키(Secret Key)로 생성.

4. 토큰 기반 인증 흐름

a. 로그인 요청

  • 사용자가 서버에 로그인 요청을 보냅니다.
POST /login HTTP/1.1
Host: example.com
Content-Type: application/json

{
  "username": "john_doe",
  "password": "secure_password"
}

b. 토큰 발급

  • 서버는 사용자를 인증한 후, JWT 또는 세션 토큰을 발급합니다.
HTTP/1.1 200 OK
Content-Type: application/json

{
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}

c. 요청마다 토큰 사용

  • 클라이언트는 이후 요청마다 토큰을 Authorization 헤더에 포함하여 전송합니다.
GET /dashboard HTTP/1.1
Host: example.com
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

d. 서버에서 토큰 검증

  • 서버는 토큰의 서명을 검증하고, 페이로드에 포함된 사용자 정보를 기반으로 요청을 처리합니다.

 

5. 토큰의 장단점

장점

  1. 확장성:
    • 상태를 서버에 저장하지 않으므로, 분산 서버 환경에서도 쉽게 사용 가능.
  2. 자체 포함(Self-Contained):
    • JWT는 페이로드에 필요한 정보를 포함하므로, 서버가 별도의 데이터베이스를 조회할 필요가 줄어듭니다.
  3. 유연성:
    • 토큰은 쿠키, HTTP 헤더, 또는 URL 파라미터로 전달할 수 있습니다.

단점

  1. 보안 취약성:
    • 토큰이 탈취되면 만료 전까지 악용될 수 있습니다.
    • 해결: HTTPS 사용, 짧은 유효 기간, 리프레시 토큰.
  2. 데이터 크기:
    • JWT는 페이로드에 데이터를 포함하므로, 크기가 커질 수 있습니다.
  3. 만료 처리:
    • JWT는 발급 후 변경할 수 없으므로, 토큰이 만료되거나 폐기된 경우 클라이언트에 새로운 토큰을 발급해야 합니다.

6. 토큰과 세션의 차이

  세션 기반 인증 토큰 기반 인증 (JWT)
저장 위치 서버 (세션 ID는 클라이언트에 저장) 클라이언트 (서버에 상태 저장 없음)
확장성 서버가 상태를 관리하므로 확장에 제약 상태를 저장하지 않으므로 확장성 우수
보안성 서버에서 세션 만료나 폐기가 가능 탈취 시 만료 전까지 악용 가능
데이터 크기 세션 ID만 저장 페이로드 포함, 크기가 상대적으로 큼
사용 사례 로그인 상태 유지 (웹 애플리케이션) API 인증, 분산 시스템

7. 토큰 사용 시 보안 고려 사항

  1. HTTPS 사용:
    • 토큰이 네트워크에서 탈취되지 않도록 HTTPS를 통해 전송.
  2. 짧은 유효 기간 설정:
    • 액세스 토큰은 유효 기간을 짧게 설정하고, 만료 시 리프레시 토큰으로 재발급.
  3. 서명 검증:
    • 서버는 토큰의 서명을 반드시 검증하여 변조 여부를 확인.
  4. 탈취 방지:
    • HttpOnly, Secure 속성을 사용해 쿠키로 저장하거나, 브라우저 로컬 저장소에 저장.

8. 요약

  • **토큰(Token)**은 클라이언트와 서버 간 인증 및 권한 부여를 위한 작은 데이터 객체입니다.
  • JWT는 가장 널리 사용되는 토큰 방식으로, 페이로드에 사용자 정보를 포함하여 자체적으로 인증을 수행.
  • 토큰은 분산 시스템과 API 기반 애플리케이션에서 유용하지만, 보안을 강화하기 위해 짧은 유효 기간과 HTTPS 사용 등 추가 조치를 해야 합니다.

 

JWT(JSON Web Token)

📌 인증에 필요한 정보들을 암호화시킨 JSON 형태의 Token을 의미한다. JSON 데이터 포맷을 사용하여 정보를 효율적으로 저장하고 암호화로 서버의 보안성을 높였다.

 

JWT.IO

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

jwt.io

 

JWT 구조

Header

  • 토큰의 타입과 해싱 알고리즘을 정의한다.
  • 예시
{
	"alg": "HS256",
	"typ": "JWT"
}

 

Payload

  • 실제로 인증과 관련된 데이터(Claims)를 담고 있다.
  • Claims의 종류
    • Registered Claims : 미리 정의된 Claims
      • iss(issuer) : 발행자
      • exp(expiration time) : 만료시간
      • sub(subject) : 제목
      • iat(issued At) : 발행 시간
      • jti(JWT ID) : 토큰의 고유 식별자
    • Public Claims : 사용자가 정의할 수 있는 클레임, 공개용 정보 전달 목적
    • Private Claims : 사용자 지정 클레임, 당사자들 간에 정보를 공유하기 위한 목적
  • 예시
{
  "sub": "1234567890",
  "name": "Sparta",
  "exp": 1682563600
}

 

Signature

  • Header와 Payload를 서버의 Secret Key로 서명하여 암호화 한다.
  • 암호화는 Header에서 정의한 알고리즘(alg)을 활용한다.
  • 서명을 통해 서버는 Token이 변조되지 않았음을 확인할 수 있다.
  • 예시
HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  secret
)

 

base64UrlEncode는 값을 URL에서 사용할 수 있도록 +, /를 각각 -, _로 표기한다.
Header와 Payload는 Encoding된 값이기 때문에 복호화 혹은 값을 수정할 수 있지만 Signature는 서버에서 관리하는 값이기 때문에 Secret Key가 유출되지 않는 이상 복호화 할 수 없다.

 

 

JWT 인증

📌 JWT는 Base64로 인코딩되어 쉽게 복호화 할 수 있다. Payload가 그대로 노출되기 때문에 비밀번호나 민감한 정보를 저장하지 않는다.

  1. 클라이언트의 로그인 요청
  2. 로그인에 성공했다면 Header, Payload에 Secret Key를 사용하여 Signature를 만든다.
    • 이후 Base64로 Encoding 한다.
    • 일반적으로 Cookie에 담아 클라이언트에게 JWT를 발급한다.
  3. 발급받은 JWT를 저장 후 서버에 요청할 때 Authorization Header에 JWT를 담아 보낸다.
  4. 서버에서 JWT의 유효성 검사를 통해 통과한다면 인증에 성공하여 요청을 처리해준다.
    • JWT 만료, 위변조 여부를 검사한다.

 

JWT의 유효성 검사

  1. A의 JWT를 B가 탈취
  2. B가 탈취한 JWT를 임의로 수정
  3. B가 수정한 JWT로 Server에 요청
  4. 서버는 Signature를 사용하여 유효성 검사(Signature 불일치)
    • Header, Payload를 서버의 Secret Key값을 이용해 Signature를 다시 만들어 비교한다.
    • 임의로 조작된 데이터를 판별할 수 있다.
JSON Web Token의 목적은 정보 보호가 아닌, 위조 방지에 있다.

 

JWT 장점

  1. Signature로 서버의 보안성이 증가한다.
  2. Token 자체가 필요한 정보(유저 및 검증 정보)들을 모두 가지고 있다.
  3. 서버는 인증 정보와 관련된 별도의 저장소를 사용하지 않는다.
  4. 서버의 수평 확장성(Scale Out)이 높아진다.
  5. Cookie가 없는 다른 환경에서도 인증/인가를 적용할 수 있다.
  6. DB를 조회하지 않아도 된다.
Mobile의 경우 App을 자주 닫거나 백그라운드로 전환하여 Session 방식을 사용하지 않는다.

 

 

JWT 단점

  1. Payload는 암호화 된 것이 아니라 민감한 정보를 다루지 못한다.
  2. Token의 길이가 길어서 트래픽이 증가하면 네트워크에 부하가 증가한다.
  3. 클라이언트 측에서 Token을 관리하기 때문에 탈취당하면 대처하기 어렵다.

 

Access Token, Refresh Token

📌 Token은 클라이언트에서 관리하여 탈취당할 위험성이 높기 때문에 만료 시간 설정이 필요하다. 이 때 발생하는 단점을 극복하기 위해 Access Token과 Refresh Token을 사용한다.

  • Token의 유형
    1. Access Token
      • 사용자 인증 후 서버가 발급하는 유저 정보가 담긴 토큰이다.
      • 유효 기간 동안 API나 리소스에 접근할 때 사용한다.
    2. Refresh Token
      • Access Token은 보안을 위해 짧은 수명을 가진다.
      • Access Token이 만료된 경우 재발급 받기위해 사용한다.
      • 주로 데이터베이스에 유저 정보와 같이 저장한다.
  1. 클라이언트의 로그인 요청
  2. 로그인에 성공했다면 Header, Payload에 Secret Key를 사용하여 Signature를 만든다.
  3. 발급받은 JWT를 저장 후 서버에 요청할 때 Authorization Header에 JWT(Access Token)를 담아 보낸다.
  4. 서버에서 JWT의 유효성 검사를 통해 통과한다면 인증에 성공하여 요청을 처리해준다.
  5. Access Token이 만료 되었다면 Refresh Token 으로 토큰 재발급을 요청한다.
  6. 서버로부터 Access Token을 재발급 받는다.
JWT를 Access Token만을 사용하여 인증한다면 탈취되어 보안에 취약할 수 있다. 유효 시간을 부여하여 문제를 해결하지만 유효 시간이 짧다면 로그인을 자주 해야하기 때문에 Refresh Token을 적용한다.
 
참고하면 좋은 영상

 

'CS ( Computer Science ) > 네트워크 (Networking)' 카테고리의 다른 글

[Net] Filter  (0) 2025.01.01
[Net] Session & Cookie의 관계  (0) 2024.12.31
[Net] Cookie  (1) 2024.12.28
[Net] MVC 패턴  (0) 2024.12.13
[Net] API 설계  (0) 2024.12.12