JWT는 JSON Web Token의 약자입니다.
말 그대로 JSON 데이터 형태로 구성된 웹 토큰입니다.
일반적으로 로그인이 되었을 때,
로그인을 유지하거나 권한이 필요한 곳에 접근할 수 있도록 하는 등으로 사용됩니다.
그렇다면 이 토큰의 구성은 어떻게 되어있고 사용했을 때의 장점이 무엇이며,
언제 어디에 주로 사용되는지 순서대로 살펴봅시다!!
구조
JWT는 점(.)으로 구분되는 세 부분으로 구성됩니다.
Header . Payload . Signature
Header
헤더는 일반적으로 토큰의 유형(JWT)과 Signature 부분을 암호화하는 알고리즘으로 JSON 데이터를 구성합니다.
{
"alg" : "HS256",
"typ" : "JWT"
}
그 후 이 JSON 데이터를 Base64Url로 인코딩해서 JWT의 첫 번째 부분으로 구성합니다.
Payload
페이로드는 사용자의 데이터 등으로 JSON 데이터를 구성합니다.
이때 데이터들을 클레임이라고 부르는데, 클레임은 세 가지 유형이 있습니다.
- 등록된 클레임
- 미리 정의된 데이터들을 말합니다.
발행자, 만료시간, 권한 등이 있습니다.
- 미리 정의된 데이터들을 말합니다.
- 공개 클레임
- JWT를 사용하는 사람들이 원하는 대로 정의하는 데이터들을 말합니다.
이 문서를 참고하여 작성합니다.
- JWT를 사용하는 사람들이 원하는 대로 정의하는 데이터들을 말합니다.
- 비공개 클레임
- 사용에 동의한 당사자 간에 정보를 공유하기 위해 생성된 맞춤 데이터입니다.
미리 정의되었거나 공개된 데이터가 아닙니다.
- 사용에 동의한 당사자 간에 정보를 공유하기 위해 생성된 맞춤 데이터입니다.
이렇게 클레임들로 이루어진 JSON 데이터를 Base64Url로 인코딩하여 JWT의 두 번째 부분으로 구성합니다.
Signature
이 부분은 인코딩된 헤더, 인코딩 된 페이로드, 비밀키를
헤더에서 지정한 알고리즘으로 암호화해서 JSON 데이터를 구성합니다.
여기서 비밀키는 특정 문자열을 직접 작성해 주면 됩니다.
( 그냥 좀 길게 막!!! 쓰시고 저장해두세요. )
Signature 부분을 통해서 토큰이 누군가에 의해서 변경되었는지를 확인하는 데 사용됩니다.
합체!
이렇게 만들어진 데이터들을 앞서 말했듯이 점(.)으로 구분되도록 합치면 완성입니다!
만약 JWT를 HTTP 헤더를 통해 전송하는 경우 일부 서버는 헤더에 8KB 이상을 허용하지 않으므로 주의해야 합니다.
장점
토큰 자체에 사용자 정보를 포함하기 때문에 Stateless 라는 특성을 가진다는 장점이 있습니다.
이로 인해서 서버에서 세션을 관리할 필요가 없고 서버의 부하를 줄일 수 있습니다.
Stateless 특성은 RESTful 한 특성 중 하나여서 REST API를 구현할 때 고려해 볼 수 있습니다.
이러한 Stateless 특성을 통해서 JWT를 분산 시스템(아키텍처)에서 활용할 때 큰 장점이 될 수 있습니다.
분산된 시스템에서의 세션을 관리하는 것이 어려울 때 사용한다면,
비밀키 등을 사용해서 토큰을 인증하고 토큰에서 필요한 데이터를 추출할 수 있다는 강점이 있습니다
단점
JWT는 Payload 부분에 데이터를 담아서 Base64Url 로만 인코딩하기 때문에 JWT가 탈취되었을 때 Payload의 데이터를 확인하기 쉽습니다. 따라서 보안적으로 민감한 데이터는 Payload에 포함하지 않아야 합니다.
JWT를 탈취당하는 경우를 대비하고 데이터들의 변경을 반영하기 위하는 등의 이유로 만료시간을 설정합니다.
JWT가 만료되면 다시 토큰을 발급받아야 한다는 단점이 존재합니다.
또한, 비밀 키가 노출되면 토큰을 탈취하고 새롭게 작성하는 것이 가능해집니다.
따라서 키 관리에 반드시 주의해야 합니다.
그리고 일단 발급된 JWT는 발급을 취소하는 등의 행동이 불가능합니다.
악의적인 사용자라고 판단이 된다면 토큰을 무효화하기 위해서 블랙리스트를 관리하는 등의 방법을 사용해야 합니다.
언제, 어디서
위의 장점과 단점을 통해서 어떠한 상황에서 사용하는 것이 좋은지 예시를 살펴봅시다.
- Single Page Application (SPA)
- Mobile Application
- MSA
- API 보안
- ...
만약 JWT의 단점이 부각되는 상황에서는 JWT 대신 세션 기반의 인증 등을 사용하는 것이 적합합니다.
민감한 정보가 포함될 수 있고 보안이 매우 중요한 은행 애플리케이션은 JWT의 인증보다는 세션 기반의 인증이 더 신뢰할 수 있는 방법입니다.
하나의 JWT 만을 사용했을 때 발생할 수 있는 문제들을 해결할 수 있도록 다양한 방법이 시도되고 있습니다.
그중에서 Refresh 토큰을 사용하는 방법을 설명하겠습니다.
Refresh 토큰
하나의 JWT 만으로 인증/인가를 시도하면서 발생하는 토큰 탈취, 토큰 만료등의 단점이자 문제점을 해결하기 위해서 Refresh 토큰을 사용합니다.
사용되는 JWT를 Access 토큰과 Refresh 토큰으로 나누어 사용합니다.
Access 토큰은 짧은 유효시간을 가지게 하여 탈취가 되어도 위험성을 낮출 수 있게 하고 Http 헤더에 담아서 클라이언트에서 편하게 사용할 수 있도록 합니다.
Refresh 토큰은 긴 유효시간을 가지며 Http only 설정을 한 쿠키에 담아서 Access 토큰을 재발급하는 목적으로만 사용되도록 합니다.
하나의 토큰을 사용했을 때는 만료될 때마다 로그인을 다시 해야 한다는 사용자의 불편함이 있는데,
Refresh 토큰을 통해 Access 토큰을 재발급 해줄 수 있으므로 사용자에게 편리함을 줄 수 있습니다.
하지만 Refresh 토큰을 DB에 저장하고 토큰을 검증할 때 사용해야 하므로 Stateless라는 특성은 사라지게 됩니다.
또한, DB에 저장된 Refresh 토큰의 보안적 위협을 막고 토큰이 만료되는 것을 관리해주어야 한다는 문제가 있습니다.
만료된 토큰 관리를 위한 방법으로 Redis 라는 DB를 사용하여 TTL 설정을 해줄 수도 있습니다.
이처럼 각각의 장단점을 깊이 있게 고려해서 어떤 인증 방법을 사용할 것이며,
JWT를 사용한다면 어떤 방법으로 JWT의 단점을 해결할 것인지를 선택해주어야 합니다.
Reference
https://substantial-park-a17.notion.site/Docs-002024551c294889863d0c7923590568
'WEB' 카테고리의 다른 글
OAuth2가 뭐죠? (0) | 2024.03.30 |
---|---|
[Trouble Shooting] 미디어 스트림 오류 ->> TypeError: Cannot read properties of undefined (reading 'getUserMedia') (0) | 2023.05.31 |
[Trouble Shooting] CORS 에러 ->> The request client is not a secure context and the resource is in more-private address space `private`. (0) | 2023.05.31 |
[Web] WebRTC를 활용한 화상통화 서비스의 서버 구성 (0) | 2023.05.02 |
[Web] WebSocket API / REST API (0) | 2023.04.13 |