2024. 10. 26. 19:48ㆍSpring Boot/Spring Security
Token
웹 애플리케이션에서 클라이언트와 서버 간의 안전한 통신을 위해 토큰이 사용됩니다. HTTP는 상태 비저장(stateless) 프로토콜이기 때문에, 클라이언트의 로그인 상태를 유지하거나 사용자를 식별하기 위해 매번 인증이 필요합니다. 토큰은 사용자 인증과 권한 부여, 세션 관리 등을 보다 안전하고 효율적으로 처리하며, 이를 통해 웹 애플리케이션의 보안성과 확장성을 크게 향상시킵니다.
토큰의 생성과 전송 과정
- 인증 과정: 사용자가 로그인을 하면 서버는 사용자의 자격 증명을 확인하고, 이를 바탕으로 토큰을 생성하여 반환합니다. 이 토큰은 주로 JSON Web Token (JWT) 형식으로, 서버만이 검증할 수 있는 서명(Signature)과 인증에 필요한 정보를 포함하고 있습니다.
- 토큰의 구조: JWT를 예로 들면, 토큰은 다음과 같은 세 부분으로 구성됩니다.
- Header: 토큰 유형과 암호화 방식을 정의합니다.
- Payload: 사용자 ID, 권한, 만료 시간 등 인증 및 권한 부여에 필요한 정보를 담고 있습니다.
- Signature: Header와 Payload를 서버의 비밀 키로 해싱하여 생성된 값으로, 토큰의 무결성을 보장합니다.
- 토큰 전송: 클라이언트는 이후 요청마다 이 토큰을 서버에 전송하여 본인을 인증합니다. 토큰은 HTTP 헤더(예:
Authorization: Bearer [토큰]
)나 쿠키, URL 파라미터 등을 통해 전송되며, 서버는 이를 검증하여 요청을 처리할 수 있는 권한이 있는지 확인합니다. - 서버의 토큰 검증: 서버는 토큰이 위조되지 않았는지 확인하기 위해 Signature 검증을 수행하며, 만료 시간도 함께 확인합니다. 유효하지 않거나 만료된 토큰이 있을 경우 서버는 요청을 거부하고, 필요 시 재로그인을 요청하거나 Refresh Token을 통해 토큰을 재발급할 수 있습니다.
토큰의 핵심 기능과 목적
- 인증(Authentication): 토큰은 사용자가 누구인지 서버에 알려주는 중요한 역할을 합니다. 사용자가 인증을 완료한 후 서버가 발급한 토큰을 클라이언트가 저장하고, 이후 각 요청마다 이를 포함하여 인증 절차를 거치지 않고도 본인을 증명할 수 있습니다.
- 세션 관리(Session Management): 토큰은 클라이언트가 직접 세션을 관리하는 방식으로 서버의 부담을 줄입니다. 각 요청마다 클라이언트가 토큰을 전송하므로 서버는 별도의 세션 저장소를 사용하지 않아도 되고, 이로 인해 서버의 확장성이 향상됩니다.
- 권한 부여(Authorization): 토큰에는 사용자 권한에 관한 정보가 담겨 있어, 서버는 이를 통해 사용자가 요청한 리소스에 접근할 권한이 있는지를 판단할 수 있습니다. 예를 들어, 관리자와 일반 사용자의 권한을 다르게 설정하여 리소스 접근을 제어할 수 있습니다.
- 보안(Security): 토큰은 서버에서 안전하게 생성되며, 암호화 및 서명을 통해 변조 방지 기능을 가집니다. CSRF(Cross-Site Request Forgery)와 같은 공격으로부터 보호되며, 서버만이 토큰의 무결성을 검증할 수 있습니다.
- 크로스 도메인 요청(Cross-Domain Requests): 토큰은 CORS(Cross-Origin Resource Sharing)를 통해 다른 도메인에서도 사용할 수 있어 유연하고 보안적인 방식으로 크로스 도메인 요청을 처리할 수 있습니다. 쿠키 기반 인증보다 더욱 유연한 구조를 제공합니다.
토큰의 주요 종류와 그 특징
- JSON Web Token (JWT): 자가 포함(Self-contained) 구조로, 사용자 인증 정보와 권한, 만료 시간 등의 정보를 담아 서버가 토큰의 무결성을 확인할 수 있습니다. JWT는 웹 애플리케이션의 인증과 권한 부여에 널리 사용되는 대표적인 형식입니다.
- OAuth 2.0 토큰: Google, Facebook 등의 외부 인증 제공자를 통해 사용자 인증을 수행하는 방식입니다. 사용자는 외부 서비스의 인증을 거쳐 애플리케이션에 로그인할 수 있으며, 계정 정보를 애플리케이션에 직접 제공하지 않고도 안전하게 인증이 가능합니다.
- Refresh Token: JWT는 만료 시간이 비교적 짧게 설정되는 경우가 많아, 사용자가 토큰 만료 후 다시 로그인해야 하는 번거로움을 방지하기 위해 사용됩니다. Refresh Token은 만료된 액세스 토큰을 갱신하여, 인증 절차를 반복하지 않고도 사용자가 연속적으로 서비스를 사용할 수 있도록 합니다.
토큰 사용 시 고려해야 할 보안 요소
- 무결성 검증: 토큰은 클라이언트가 수정할 수 없도록 서명을 포함하여 생성됩니다. 서버는 이 서명을 검증하여 토큰이 위조되지 않았음을 확인합니다.
- 암호화: 토큰은 안전하게 생성되며, HTTPS를 통해 전송하여 중간에 탈취되는 것을 방지합니다. 특히 사용자 정보가 담긴 토큰의 경우, 민감 정보 보호를 위해 암호화된 형식이 필요합니다.
- 토큰 저장 위치: 클라이언트는 토큰을 안전하게 저장해야 하며, 쿠키에 저장할 경우
HttpOnly
및Secure
속성을 설정하여 XSS 공격을 방지하는 것이 좋습니다. - 토큰의 만료 시간: 토큰의 만료 시간을 짧게 설정하여 보안을 강화하며, Access Token과 Refresh Token을 함께 사용하여 만료된 토큰의 자동 갱신이 가능합니다.
- 탈취 위험 관리: 탈취된 토큰이 악용되지 않도록 정기적으로 재발급하거나 블랙리스트를 사용해 특정 토큰을 무효화하는 방법을 고려해야 합니다.
토큰 기반 인증 방식의 장점과 한계
- 장점:
- 서버 부담 감소: 상태 비저장 방식으로 서버의 세션 저장 부담을 덜어주며, 분산 서버 환경에서도 유연하게 인증을 유지할 수 있습니다.
- 확장성: 서버가 사용자 세션을 관리하지 않기 때문에 서버 확장이 용이합니다.
- 한계:
- 보안 리스크: 토큰이 탈취될 경우 악용될 가능성이 있으므로, 클라이언트가 이를 안전하게 저장하고 전송하는 방식이 중요합니다.
- 토큰 무효화의 어려움: 토큰을 강제로 무효화하거나 폐기하는 데 한계가 있습니다. 이를 해결하기 위해 블랙리스트 관리나 주기적인 토큰 갱신을 고려해야 합니다.
토큰은 웹 애플리케이션의 인증, 세션 관리, 권한 부여를 안전하고 효율적으로 처리하기 위한 핵심적인 수단입니다. 토큰 기반 인증은 서버의 확장성을 높이며, 클라이언트와 서버 간의 상태 비저장 통신을 가능하게 하여, 현대 웹 애플리케이션에서 필수적인 보안 메커니즘으로 자리잡고 있습니다
JWT (JSON Web Token)
JSON Web Token (JWT)는 RFC 7519에 정의된 웹 표준으로, 두 개체 간에 JSON 형식의 정보를 안전하게 전송하기 위한 간단하고 자가 포함된 형식을 제공합니다. JWT는 주로 인증 및 정보 교환의 목적으로 사용되며, 서버와 클라이언트 간의 상태 유지와 신뢰할 수 있는 정보 전송에 적합한 방식을 제공하여 널리 사용되고 있습니다.
JWT의 구성 요소
JWT는 크게 헤더(Header), 페이로드(Payload), 그리고 서명(Signature)의 세 부분으로 구성됩니다. 이 세 부분은 각각의 목적과 역할을 가지며, 다음과 같이 구성됩니다.
- 헤더 (Header)여기서
alg
는 서명에 사용될 알고리즘 (예: HMAC SHA256)이며,typ
는 토큰의 타입을 나타내는 것으로 기본적으로 JWT로 설정됩니다. 이 헤더는 서버가 토큰을 처리하고 검증할 때, 어떤 알고리즘과 토큰 유형을 사용해야 하는지에 대한 정보를 제공합니다. { "alg": "HS256", "typ": "JWT" }
- 헤더는 JWT의 타입과 암호화 알고리즘 정보를 담고 있는 JSON 객체입니다. 가장 일반적인 구조는 다음과 같습니다:
- 페이로드 (Payload)
- 등록된 클레임 (Registered Claims): JWT 표준에 의해 정의된 클레임으로, 주로 토큰에 대한 일반적인 정보를 담고 있습니다. 예를 들어,
iss
(발급자),sub
(대상자),exp
(만료 시간) 등이 있습니다. - 공개 클레임 (Public Claims): 애플리케이션의 사용에 따라 정의되는 클레임으로, 예를 들어
name
,email
과 같은 정보를 추가할 수 있습니다. 다만 충돌을 방지하기 위해 클레임 이름 충돌 방지 규칙을 지켜야 합니다. - 비공개 클레임 (Private Claims): 애플리케이션 간에 협의에 의해 정의되는 클레임으로, 두 당사자 간의 정보 전송을 위해 사용됩니다.페이로드에 포함할 수 있는 데이터의 유형은 제한이 없으며, JWT가 JSON 객체 형태로 구조화되어 있기 때문에 원하는 데이터를 자유롭게 담을 수 있습니다.
- 등록된 클레임 (Registered Claims): JWT 표준에 의해 정의된 클레임으로, 주로 토큰에 대한 일반적인 정보를 담고 있습니다. 예를 들어,
- 페이로드는 JWT 내에 포함될 주요 데이터로, 사용자의 신원이나 권한 정보 등 원하는 데이터를 JSON 객체로 담습니다. 이 정보는 클레임(claim)이라고 불리며, 각 클레임은
이름/값 쌍
으로 이루어집니다. 페이로드에 포함할 수 있는 대표적인 클레임에는 다음이 있습니다: - 서명 (Signature)서명은 헤더와 페이로드를 각각 Base64URL로 인코딩한 후, 서버의 비밀 키(또는 개인 키)로 지정된 알고리즘을 사용해 해싱하여 생성됩니다. 이 서명은 서버에서 토큰을 검증할 때 사용되며, 해시 결과를 비교하여 토큰의 무결성을 확인할 수 있습니다.
HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)
- 서명은 JWT의 무결성을 보장하고, 토큰이 발행된 이후 변조되지 않았음을 검증하기 위해 사용됩니다. 서명은 다음과 같이 생성됩니다:
JWT의 작동 원리
JWT는 서버가 클라이언트에게 보낸 정보를 신뢰할 수 있도록 하는 방식을 제공합니다. 보통 서버는 사용자가 로그인하면 인증 정보를 확인한 후, 해당 사용자에 대한 정보를 담아 서명이 포함된 JWT를 생성하고 클라이언트에게 전달합니다. 클라이언트는 이후의 모든 요청마다 이 토큰을 함께 보내어 자신을 인증할 수 있습니다.
서버는 클라이언트가 보낸 토큰의 서명을 검증하여 토큰이 변조되지 않았음을 확인하고, 페이로드에 담긴 사용자 정보를 기반으로 인증과 권한을 부여합니다.
JWT의 장점과 보안 강화
- 자가 포함된 구조: JWT는 필요한 정보가 페이로드에 담겨 있는 자가 포함된 구조이므로, 서버가 별도의 세션을 저장하지 않아도 됩니다. 즉, 서버가 상태 비저장(stateless) 상태를 유지할 수 있습니다.
- 서명과 검증 가능성: JWT는 디지털 서명 또는 암호화를 통해 보안을 강화할 수 있습니다. 서명된 JWT를 JWS (JSON Web Signature)라고 하며, 암호화된 JWT를 JWE (JSON Web Encryption)라고 합니다. 이로써 JWT는 무결성을 보장하여, 신뢰할 수 있는 출처에서 생성된 토큰만이 유효하도록 할 수 있습니다.
- Base64URL 인코딩: JWT는 Base64URL로 인코딩된 문자열 형태로 전송됩니다. 이는 공백 없이 URL에 삽입할 수 있고, 문자 수가 비교적 짧아 HTTP 헤더와 같이 제한적인 전송 채널을 통해 효율적으로 전달될 수 있습니다.
JWT의 일반적인 사용 사례
- 인증 (Authentication): JWT는 사용자 인증에 널리 사용되며, 사용자가 로그인하면 서버는 사용자의 ID와 권한 정보 등을 담은 JWT를 생성하고 클라이언트에 전달합니다. 이후 클라이언트는 이 토큰을 매 요청마다 함께 전송하여 인증을 대체할 수 있습니다.
- 권한 부여 (Authorization): JWT는 페이로드에 사용자의 권한에 대한 정보를 포함할 수 있기 때문에, 서버는 이를 기반으로 사용자가 특정 리소스에 접근할 수 있는지 판단합니다.
- 정보 교환 (Data Exchange): JWT는 신뢰할 수 있는 정보 교환 수단으로 사용될 수 있습니다. 서명이 포함된 JWT는 발행자가 정당한 출처임을 증명하므로, 안전한 데이터 교환 방식으로 활용됩니다.
JWT의 보안적 고려 사항
JWT는 HTTP 전송 중 탈취 또는 변조될 가능성이 있으므로 다음과 같은 보안 요소를 고려해야 합니다.
- 서명 검증: 클라이언트가 보낸 JWT는 서버가 반드시 서명을 검증하여, 변조된 토큰이 아닌지 확인해야 합니다. 비밀 키 또는 공개 키를 사용하여 서명 검증을 통해 토큰의 무결성을 확인할 수 있습니다.
- 만료 시간 설정:
exp
클레임을 사용하여 JWT의 만료 시간을 설정하고, 만료된 토큰은 서버에서 거부함으로써 보안을 강화할 수 있습니다. Refresh Token을 함께 사용하여 만료된 토큰을 갱신하는 방식도 많이 사용됩니다. - HTTPS 사용: 토큰이 전송되는 과정에서 탈취당하지 않도록 HTTPS 프로토콜을 사용하여 암호화된 상태로 전송하는 것이 중요합니다.
- 저장 위치 고려: 클라이언트가 토큰을 안전하게 저장해야 합니다. 브라우저의 경우 로컬 스토리지 또는 쿠키에 저장할 수 있으며, 쿠키에 저장할 경우
HttpOnly
및Secure
속성을 설정하여 XSS와 CSRF 공격을 방지할 수 있습니다.
JWT는 인증, 권한 부여, 데이터 교환 등 웹 애플리케이션의 다양한 보안 요구 사항을 충족시키는 유용한 기술입니다. 자가 포함된 구조와 서명, 암호화 등의 보안 기능을 통해 클라이언트와 서버 간의 신뢰할 수 있는 통신을 가능하게 합니다.
이를 통해 JWT는 사용자 세션 관리와 무결성을 보장하면서도 서버의 확장성을 높여 현대 웹 애플리케이션에서 필수적인 보안 메커니즘으로 자리 잡았습니다.
JWT 구조
1. JWT의 구조 개요
JWT (JSON Web Token)는 세 가지 주요 구성 요소(Header, Payload, Signature)로 이루어져 있으며, 각 부분은 점(.
)으로 구분되어 연결됩니다. JWT는 클라이언트와 서버 간에 인증 및 권한 부여 정보와 같은 중요한 정보를 안전하게 전달할 수 있는 방식으로, 효율적이고 유연한 토큰 기반 인증을 지원합니다.
header.payload.signature
이 구조를 통해 서버와 클라이언트는 요청마다 인증을 반복할 필요 없이, 토큰을 통해 신원을 확인하고, 권한을 부여하는 과정을 간소화할 수 있습니다. 다음으로 각 구성 요소를 상세히 살펴보겠습니다.
2. JWT의 각 구성 요소
(1) Header
헤더(Header)는 JWT의 기본적인 메타데이터를 포함하고 있으며, 주로 다음 두 가지 정보를 담습니다:
- typ: 토큰의 유형을 지정합니다. 보통은 JWT라는 값을 가지며, 토큰이 JWT임을 표시합니다.
- alg: 서명에 사용될 암호화 알고리즘을 명시합니다. 일반적으로 HMAC SHA256 (HS256) 또는 RSA 등의 알고리즘을 사용할 수 있습니다.
헤더는 JSON 객체 형태로 정의되며, 최종적으로는 Base64URL 인코딩을 통해 JWT의 첫 번째 부분을 형성합니다. 다음은 헤더의 예입니다:
{
"alg": "HS256",
"typ": "JWT"
}
Base64URL 인코딩 방식으로 헤더가 인코딩되며, 최종적으로 암호화된 형태로 토큰에 포함됩니다.
(2) Payload
페이로드(Payload)는 JWT의 본문에 해당하며, 사용자에 대한 정보와 토큰의 세부 정보를 담고 있는 클레임(Claims)이 포함됩니다. 클레임은 토큰이 인증하는 대상에 관한 정보이며, JSON 객체 형태로 정의됩니다. 클레임은 크게 등록된 클레임(Registered Claims), 공개 클레임(Public Claims), 비공개 클레임(Private Claims) 세 가지로 나눌 수 있습니다:
- 등록된 클레임 (Registered Claims)
- iss (Issuer): JWT를 발급한 주체 (예: 발급자 또는 서버)를 식별합니다. 주로 JWT의 발급자 신뢰성을 확인하는 데 사용됩니다.
- sub (Subject): JWT의 주제, 즉 대상자를 식별하며 보통 사용자 ID와 같은 고유한 값을 가집니다.
- aud (Audience): 토큰의 대상 수신자를 나타내며, JWT가 특정 수신자만을 위한 것인지 확인하는 데 사용됩니다.
- exp (Expiration Time): JWT의 만료 시간을 지정합니다. 만료 시간을 통해 토큰의 유효 기간을 설정할 수 있습니다.
- nbf (Not Before): 이 시간 이전에는 JWT를 유효하지 않게 처리하도록 지정하는 필드입니다. 지정된 시간이 되기 전에는 토큰이 유효하지 않도록 설정할 수 있습니다.
- iat (Issued At): JWT가 발급된 시간(UNIX 타임스탬프)을 표시하며, JWT의 연령을 판단할 수 있습니다.
- jti (JWT ID): JWT에 대한 고유 식별자로, 토큰의 중복 사용을 방지하는 데 사용됩니다.각 클레임의 사용은 선택적이며, 애플리케이션의 보안 요구 사항에 따라 설정됩니다.
- 등록된 클레임은 JWT 표준에 의해 정의된 필드로, 정보의 상호 운용성을 위해 권장됩니다. 애플리케이션의 필요에 따라 선택적으로 사용할 수 있으며, 주요 클레임에는 다음과 같은 것들이 있습니다:
- 공개 클레임 (Public Claims)
- 공개 클레임은 JWT를 사용하는 서비스들 간의 상호 운용성을 위해 IANA에 등록되거나, URL 형태로 정의하여 사용됩니다. 공개 클레임은 사용자 ID나 역할(role)과 같은 애플리케이션 특정 정보를 포함할 수 있지만, 서로 다른 애플리케이션 간에 동일한 클레임 이름이 충돌할 가능성이 있으므로 조심해야 합니다.
- 비공개 클레임 (Private Claims)
- 비공개 클레임은 JWT를 주고받는 두 시스템 간의 합의에 의해 정의된 애플리케이션 전용 클레임으로, 등록된 클레임이나 공개 클레임과 충돌하지 않는 이름을 사용해야 합니다. 예를 들어, 사용자별 세부 정보와 같은 특정 정보를 담을 수 있습니다.
페이로드 또한 Base64URL 인코딩되어 JWT의 두 번째 부분을 형성합니다.
3. Registered Claim Names
등록된 클레임은 JWT 표준에서 필수로 정의된 것은 아니지만, 유용하고 공통적으로 사용되는 정보들이기 때문에 각 JWT 사용자가 쉽게 상호 운용할 수 있도록 권장됩니다. 주요 등록 클레임에는 다음이 있습니다:
- iss (Issuer)
- JWT를 발행한 서버 또는 주체를 식별합니다.
- 클라이언트가 JWT의 발행자를 검증하여 신뢰할 수 있는 서버에서 발행한 토큰인지 확인하는 데 유용합니다.
- sub (Subject)
- JWT가 인증하는 대상을 식별합니다.
- 주로 사용자 ID 등 고유한 식별자가 포함됩니다.
- aud (Audience)
- 토큰의 대상 수신자를 지정합니다.
- 수신자는 aud 값에 따라 자신이 토큰의 대상인지 확인하고, 아닐 경우 토큰을 거부할 수 있습니다.
- exp (Expiration Time)
- 토큰의 유효 기간을 나타냅니다. 이 시간이 지나면 토큰이 만료됩니다.
- nbf (Not Before)
- 토큰이 유효하지 않은 시간을 지정합니다. 주어진 시간 이전에는 이 토큰이 무효로 처리됩니다.
- iat (Issued At)
- 토큰이 발급된 시점을 기록합니다. JWT의 연령을 측정할 때 유용하게 사용됩니다.
- jti (JWT ID)
- JWT의 고유 식별자이며, 주로 토큰의 재사용을 방지하는 데 활용됩니다.
4. Signature
서명(Signature)은 JWT의 무결성을 보장하는 요소로, 토큰이 발급된 후 변조되지 않았음을 확인하기 위해 사용됩니다. 서명은 서버가 클라이언트에게 전달한 토큰이 중간에서 위변조되지 않았음을 확인하는 중요한 부분입니다. 서명은 다음과 같이 생성됩니다:
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)
서명은 JWT의 헤더와 페이로드를 각각 Base64URL로 인코딩하여 .
으로 연결한 뒤, 서버가 비밀 키(secret key) 또는 공개/비공개 키 쌍을 이용해 지정된 암호화 알고리즘을 사용하여 생성됩니다. 서버는 클라이언트가 보낸 JWT의 서명을 검증하여 토큰의 무결성을 확인하고, 변조되지 않았을 경우에만 토큰을 신뢰합니다.
5. JWT Compression
JWT의 페이로드 크기가 클 경우, HTTP 헤더로 전송할 때 효율성을 높이기 위해 압축할 수 있습니다. JWT 표준에서는 JWE(JSON Web Encryption)에서만 압축을 지원하므로, JWT에 대해 직접적인 압축 표준은 없습니다. 하지만, 특정 JWT 라이브러리에서는 JWS에서도 압축 기능을 제공합니다.
JWT는 헤더, 페이로드, 서명으로 구성된 간단한 구조를 통해, 클라이언트와 서버 간의 인증과 정보를 안전하게 교환할 수 있습니다. 또한, Base64URL 인코딩 및 서명을 통해 토큰의 무결성을 유지하면서, 클레임 기반의 유연한 데이터 구조를 통해 다양한 서비스 요구에 적합한 토큰을 생성할 수 있습니다.
JWT는 인증, 권한 부여, 정보 교환 등에서 활용도가 높으며, 서버의 상태 비저장(stateless) 방식을 지원하는 구조 덕분에 \*\*대규모 시스템\*\*에서도 안정적인 보안과 확장성을 제공합니다.
JWT의 사용 방법
JWT는 다양한 사용 사례에서 유연하고 강력한 방식으로 인증 및 정보 교환을 지원합니다. 여기서는 JWT를 사용하는 일반적인 인증 및 정보 교환 과정과, 이 과정에서 각 단계가 어떻게 수행되는지를 설명하겠습니다.
1. 인증(Authentication)
JWT를 통한 인증 과정에서는 리프레시 토큰(Refresh Token)을 함께 사용하여 보안성과 사용자 경험을 더욱 향상할 수 있습니다. 이 과정은 다음과 같은 단계로 이루어집니다.
- 사용자 로그인 요청
- 사용자가 서버에 아이디와 비밀번호를 제출하여 로그인 요청을 보냅니다.
- 서버는 제출된 정보를 검증해 사용자가 신뢰할 수 있는 사용자임을 확인합니다.
- JWT 및 리프레시 토큰 생성
- 서버는 사용자의 인증 정보를 확인한 후 액세스 토큰(Access Token)과 리프레시 토큰(Refresh Token)을 함께 생성합니다.
- 액세스 토큰은 사용자의 ID, 권한 정보, 발행 시간(iat), 만료 시간(exp) 등의 클레임을 포함하고 있으며, 일반적으로 만료 시간이 짧습니다.
- 리프레시 토큰은 액세스 토큰보다 긴 유효 기간을 가지며, 만료된 액세스 토큰을 갱신할 때 사용됩니다. 리프레시 토큰에는 보통 서명(Signature) 정보만 포함되어 있습니다.
- JWT 및 리프레시 토큰 전달
- 서버는 액세스 토큰과 리프레시 토큰을 클라이언트에 반환합니다. 클라이언트는 액세스 토큰을 인증에 사용하기 위해 로컬 저장소나 메모리에 저장하고, 리프레시 토큰은 추가 인증 없이 토큰을 갱신하기 위해 안전하게 저장합니다.
- 액세스 토큰을 사용한 인증 요청
- 이후 요청마다, 클라이언트는 액세스 토큰을 Authorization 헤더에
Bearer
타입으로 추가하여 서버에 요청을 보냅니다. 예:Authorization: Bearer <액세스 토큰>
- 이후 요청마다, 클라이언트는 액세스 토큰을 Authorization 헤더에
- 액세스 토큰의 검증 및 만료 확인
- 서버는 클라이언트가 전송한 액세스 토큰의 서명과 만료 시간을 검증하여 토큰이 유효한지 확인합니다. 토큰이 유효하면 서버는 요청을 처리하고 권한에 따라 적절한 응답을 보냅니다.
- 액세스 토큰이 만료된 경우, 서버는 만료된 토큰을 기반으로 추가 요청을 거부합니다.
- 리프레시 토큰을 통한 액세스 토큰 갱신
- 만료된 액세스 토큰이 있을 때, 클라이언트는 보유 중인 리프레시 토큰을 사용해 새 액세스 토큰을 요청합니다.
- 서버는 리프레시 토큰을 검증한 후 새 액세스 토큰을 생성하여 클라이언트에 반환하고, 클라이언트는 새로 발급된 액세스 토큰을 사용해 인증된 요청을 다시 수행할 수 있습니다.
리프레시 토큰을 사용하면 짧은 유효 기간의 액세스 토큰으로 보안성을 유지하면서도, 사용자가 반복적으로 로그인할 필요 없이 지속적인 인증 상태를 유지할 수 있습니다.
2. 정보 교환(Information Exchange) 및 리프레시 토큰의 역할
JWT는 서버와 클라이언트, 또는 서버 간의 정보 교환에 있어 안전성과 데이터 무결성을 보장할 수 있습니다. 리프레시 토큰을 사용하면 정보 교환 시 재인증을 위한 절차를 단순화할 수 있습니다.
- 서명(Signature): JWT는 서명을 통해 발행자와 수신자가 데이터의 진위를 검증할 수 있습니다. 이로 인해 중간에서 데이터가 변조되지 않도록 보호됩니다.
- 자가 포함(Self-contained) 데이터: JWT는 필요 정보를 자체 포함하여 외부 데이터베이스 접근이 필요 없습니다. 예를 들어, 서버 간 통신 시 클라이언트의 권한 정보나 접근 제한을 JWT에 포함하여 전달할 수 있습니다.
- 리프레시 토큰의 보안 역할: 리프레시 토큰을 함께 사용하면, 액세스 토큰이 만료될 때 추가적인 로그인을 필요로 하지 않으면서도 보안을 유지할 수 있어, 서버 간 안전하고 효율적인 인증 처리가 가능합니다.
리프레시 토큰을 활용함으로써 장기적인 인증을 안정적으로 유지할 수 있고, 필요 시 짧은 주기의 액세스 토큰으로 보안성을 강화할 수 있어 JWT 인증과 정보 교환에서 매우 중요한 역할을 합니다.
JWT의 장점
JWT는 여러 가지 이유로 웹 애플리케이션의 인증 및 정보 교환에 널리 사용됩니다. 주요 장점은 다음과 같습니다:
- 자가 포함(Self-contained):
- JWT는 모든 필요한 정보를 자체적으로 포함하고 있기 때문에, 각 요청마다 외부 데이터베이스를 조회할 필요가 없습니다.
- 예를 들어, 사용자 ID와 역할 정보를 포함하여 인증된 사용자가 특정 리소스에 접근할 수 있는지 여부를 즉각적으로 확인할 수 있습니다.
- 간결함(Compactness):
- JWT는 JSON 형식을 Base64URL로 인코딩한 형태이므로 매우 컴팩트하여 HTTP 헤더나 쿠키에 쉽게 포함될 수 있습니다.
- 이는 모바일 환경과 같이 대역폭이 제한된 환경에서 유용하며, 네트워크 오버헤드를 줄이는 데 도움을 줍니다.
- 모바일 친화성:
- JWT는 서버에서 상태를 유지하지 않는 Stateless 특성으로 인해, 모바일 클라이언트와 같은 비연결형 환경에서 매우 효율적입니다.
- 모바일 앱이 토큰을 저장하고 네트워크 연결이 가능한 시점에만 서버에 전송하면 되므로, 세션 유지와 관련된 복잡한 작업을 줄일 수 있습니다.
- 크로스 도메인 인증:
- JWT는 쿠키와 달리 특정 도메인에 의존하지 않으며, CORS 정책을 지원하는 환경에서 활용하기가 쉽습니다.
- 쿠키 대신
Authorization
헤더에 JWT를 포함하여 도메인 간 요청(Cross-Domain Request)을 수행할 수 있어, 마이크로서비스와 같은 환경에서 유용합니다.
- 확장성과 유연성:
- JWT는 여러 개의 서비스가 포함된 분산 아키텍처에서 사용자가 동일한 인증 상태를 유지하도록 하는 SAML 및 OAuth2와의 호환성을 가집니다.
- 특히 JWT 기반의
OAuth2
를 통해 외부 애플리케이션과 안전하게 인증 정보를 주고받을 수 있습니다.
JWT의 단점
JWT의 특성상 몇 가지 제한 사항과 단점이 있습니다. 이를 이해하고 필요에 따라 적절한 대응 방안을 마련하는 것이 중요합니다:
- 보안 문제
- JWT는 기본적으로 Base64 인코딩된 JSON 데이터이기 때문에, 인코딩만 된 정보는 누구나 복호화할 수 있습니다. 따라서 중요한 정보를 담아서는 안 됩니다.
- 사용자의 민감한 정보가 노출되지 않도록 전체 토큰을 암호화(JWE) 하거나, 서버가 검증할 때 민감 정보는 별도의 안전한 저장소에서 관리해야 합니다.
- 토큰 길이 증가 문제
- JWT는 Self-contained 구조로 인해 데이터가 많을수록 토큰의 길이가 길어질 수 있으며, 이는 네트워크 오버헤드로 이어질 수 있습니다.
- 이를 방지하기 위해, 토큰에 꼭 필요한 정보만을 포함하도록 설계하고, 압축 알고리즘을 사용해 전송 크기를 줄이는 방법도 고려할 수 있습니다.
- 상태 유지의 어려움
- JWT는 Stateless 특성을 가지기 때문에, 사용자가 로그아웃하거나 토큰을 무효화하는 작업이 복잡할 수 있습니다.
- 토큰을 강제로 만료시키기 위해, 서버에서 특정 토큰을 블랙리스트에 등록하거나, 짧은 만료 기간의 Access Token과 긴 유효 기간의 Refresh Token을 사용하는 방법을 통해 보안성을 강화할 수 있습니다.
- 재사용 공격에 취약
- JWT는 URL에 포함될 수도 있는데, 이 경우 URL에서 캡처된 토큰을 재사용하려는 공격에 노출될 수 있습니다.
- 이 문제를 방지하려면, 반드시 HTTPS를 통해서만 토큰을 전송하고, 사용자가 신뢰할 수 없는 네트워크 환경에서는 HTTPS를 강제하는 것이 좋습니다.
JWT는 웹 애플리케이션에서 효율적인 인증과 정보 교환을 위한 강력한 솔루션으로 자리 잡았습니다. 장점과 단점을 이해하고, 필요에 따라 단점을 보완할 수 있는 전략을 사용함으로써 보다 안전하고 확장성 있는 애플리케이션을 구축할 수 있습니다.
- 효율적이고 자가 포함된 데이터 구조를 통해 추가적인 서버 리소스 소모를 줄일 수 있으며,
- 분산 환경이나 모바일 환경에서도 간결하고 신뢰할 수 있는 인증 방식으로 활용할 수 있습니다.
하지만 JWT를 활용하는 애플리케이션 설계 시, 보안 문제와 상태 관리의 어려움을 해결하기 위해 적절한 대책을 마련하는 것이 중요합니다.
'Spring Boot > Spring Security' 카테고리의 다른 글
certificate.p12 (0) | 2023.05.17 |
---|