Token
📌 Web Application이나 API에서 인증(Authentication)과 인가(Authorization) 과정에서 사용되며 사용자 또는 시스템의 신원과 권한을 증명하고 요청의 유효성을 검증하는 데 사용되는 디지털 문자열이다.
- 인증(Authentication), 권한 부여(Authorization), 또는 데이터 교환을 위해 클라이언트와 서버 간에 사용되는 작고 안전한 데이터 객체입니다.
- 로그인 인증이나 사용자 권한 관리를 할 때 토큰을 발급하고, 이를 통해 사용자를 식별하거나 인증 상태를 유지할 수 있습니다.
- 토큰은 전체 데이터를 포함하지 않는다. 박스가 아니라 키라고 생각해야한다. 말 그대로 다른 클라에 요청할 시 사용가능한 인물인지에 대한 정보만 포함된다. 패킷이 아니다.
- Token 생성 시 사용자의 고유한 정보를 포함한다.
- 데이터베이스에 접근하지 않고 Token의 유효성만 검증한다.
- Token의 단점
- Cookie/Session 방식보다 Token 자체의 데이터 용량이 많다.
- 요청이 많아지면 그만큼 트래픽이 증가한다.
- Payload(전송되는 데이터)는 암호화되지 않아서 중요한 데이터를 담을 수 없다.
- Token을 탈취당하면 대처하기 어려워 만료 시간(30분)을 설정한다.
- Cookie/Session 방식보다 Token 자체의 데이터 용량이 많다.
0. Token을 사용하는 이유
- Token은 서버가 아닌 클라이언트에 저장되어 서버의 부담을 덜 수 있다.
- Cookie는 웹 브라우저에만 존재하여 모바일 앱 등의 다양한 클라이언트에서 인증을 처리할 수 없다.
- Token 방식은 Stateless를 기반으로 하여 확장성이 뛰어나다.
- 인증된 사용자임을 확인하기 위한 고유한 서명을 포함하여 위조된 요청인지 확인할 수 있다.
1. 토큰의 기본 개념
토큰의 역할
- 인증(Authentication):
- 사용자가 로그인하면 서버는 인증 결과를 기반으로 토큰을 발급합니다.
- 클라이언트는 이후 요청마다 이 토큰을 사용하여 인증된 사용자임을 증명합니다.
- 권한 부여(Authorization):
- 사용자가 어떤 리소스에 접근할 수 있는 권한이 있는지 확인합니다.
- 예: "관리자" 권한을 가진 사용자만 특정 API에 접근 가능.
- 상태 정보 저장(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. 토큰의 장단점
장점
- 확장성:
- 상태를 서버에 저장하지 않으므로, 분산 서버 환경에서도 쉽게 사용 가능.
- 자체 포함(Self-Contained):
- JWT는 페이로드에 필요한 정보를 포함하므로, 서버가 별도의 데이터베이스를 조회할 필요가 줄어듭니다.
- 유연성:
- 토큰은 쿠키, HTTP 헤더, 또는 URL 파라미터로 전달할 수 있습니다.
단점
- 보안 취약성:
- 토큰이 탈취되면 만료 전까지 악용될 수 있습니다.
- 해결: HTTPS 사용, 짧은 유효 기간, 리프레시 토큰.
- 데이터 크기:
- JWT는 페이로드에 데이터를 포함하므로, 크기가 커질 수 있습니다.
- 만료 처리:
- JWT는 발급 후 변경할 수 없으므로, 토큰이 만료되거나 폐기된 경우 클라이언트에 새로운 토큰을 발급해야 합니다.
6. 토큰과 세션의 차이
세션 기반 인증 | 토큰 기반 인증 (JWT) | |
저장 위치 | 서버 (세션 ID는 클라이언트에 저장) | 클라이언트 (서버에 상태 저장 없음) |
확장성 | 서버가 상태를 관리하므로 확장에 제약 | 상태를 저장하지 않으므로 확장성 우수 |
보안성 | 서버에서 세션 만료나 폐기가 가능 | 탈취 시 만료 전까지 악용 가능 |
데이터 크기 | 세션 ID만 저장 | 페이로드 포함, 크기가 상대적으로 큼 |
사용 사례 | 로그인 상태 유지 (웹 애플리케이션) | API 인증, 분산 시스템 |
7. 토큰 사용 시 보안 고려 사항
- HTTPS 사용:
- 토큰이 네트워크에서 탈취되지 않도록 HTTPS를 통해 전송.
- 짧은 유효 기간 설정:
- 액세스 토큰은 유효 기간을 짧게 설정하고, 만료 시 리프레시 토큰으로 재발급.
- 서명 검증:
- 서버는 토큰의 서명을 반드시 검증하여 변조 여부를 확인.
- 탈취 방지:
- HttpOnly, Secure 속성을 사용해 쿠키로 저장하거나, 브라우저 로컬 저장소에 저장.
8. 요약
- **토큰(Token)**은 클라이언트와 서버 간 인증 및 권한 부여를 위한 작은 데이터 객체입니다.
- JWT는 가장 널리 사용되는 토큰 방식으로, 페이로드에 사용자 정보를 포함하여 자체적으로 인증을 수행.
- 토큰은 분산 시스템과 API 기반 애플리케이션에서 유용하지만, 보안을 강화하기 위해 짧은 유효 기간과 HTTPS 사용 등 추가 조치를 해야 합니다.
JWT(JSON Web Token)
📌 인증에 필요한 정보들을 암호화시킨 JSON 형태의 Token을 의미한다. JSON 데이터 포맷을 사용하여 정보를 효율적으로 저장하고 암호화로 서버의 보안성을 높였다.
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 : 사용자 지정 클레임, 당사자들 간에 정보를 공유하기 위한 목적
- Registered Claims : 미리 정의된 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가 그대로 노출되기 때문에 비밀번호나 민감한 정보를 저장하지 않는다.
- 클라이언트의 로그인 요청
- 로그인에 성공했다면 Header, Payload에 Secret Key를 사용하여 Signature를 만든다.
- 이후 Base64로 Encoding 한다.
- 일반적으로 Cookie에 담아 클라이언트에게 JWT를 발급한다.
- 발급받은 JWT를 저장 후 서버에 요청할 때 Authorization Header에 JWT를 담아 보낸다.
- 서버에서 JWT의 유효성 검사를 통해 통과한다면 인증에 성공하여 요청을 처리해준다.
- JWT 만료, 위변조 여부를 검사한다.
JWT의 유효성 검사
- A의 JWT를 B가 탈취
- B가 탈취한 JWT를 임의로 수정
- B가 수정한 JWT로 Server에 요청
- 서버는 Signature를 사용하여 유효성 검사(Signature 불일치)
- Header, Payload를 서버의 Secret Key값을 이용해 Signature를 다시 만들어 비교한다.
- 임의로 조작된 데이터를 판별할 수 있다.
JSON Web Token의 목적은 정보 보호가 아닌, 위조 방지에 있다. |
JWT 장점
- Signature로 서버의 보안성이 증가한다.
- Token 자체가 필요한 정보(유저 및 검증 정보)들을 모두 가지고 있다.
- 서버는 인증 정보와 관련된 별도의 저장소를 사용하지 않는다.
- 서버의 수평 확장성(Scale Out)이 높아진다.
- Cookie가 없는 다른 환경에서도 인증/인가를 적용할 수 있다.
- DB를 조회하지 않아도 된다.
Mobile의 경우 App을 자주 닫거나 백그라운드로 전환하여 Session 방식을 사용하지 않는다. |
JWT 단점
- Payload는 암호화 된 것이 아니라 민감한 정보를 다루지 못한다.
- Token의 길이가 길어서 트래픽이 증가하면 네트워크에 부하가 증가한다.
- 클라이언트 측에서 Token을 관리하기 때문에 탈취당하면 대처하기 어렵다.
Access Token, Refresh Token
📌 Token은 클라이언트에서 관리하여 탈취당할 위험성이 높기 때문에 만료 시간 설정이 필요하다. 이 때 발생하는 단점을 극복하기 위해 Access Token과 Refresh Token을 사용한다.
- Token의 유형
- Access Token
- 사용자 인증 후 서버가 발급하는 유저 정보가 담긴 토큰이다.
- 유효 기간 동안 API나 리소스에 접근할 때 사용한다.
- Refresh Token
- Access Token은 보안을 위해 짧은 수명을 가진다.
- Access Token이 만료된 경우 재발급 받기위해 사용한다.
- 주로 데이터베이스에 유저 정보와 같이 저장한다.
- Access Token
- 클라이언트의 로그인 요청
- 로그인에 성공했다면 Header, Payload에 Secret Key를 사용하여 Signature를 만든다.
- 발급받은 JWT를 저장 후 서버에 요청할 때 Authorization Header에 JWT(Access Token)를 담아 보낸다.
- 서버에서 JWT의 유효성 검사를 통해 통과한다면 인증에 성공하여 요청을 처리해준다.
- Access Token이 만료 되었다면 Refresh Token 으로 토큰 재발급을 요청한다.
- 서버로부터 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 |