JWT토큰이란?
들어가며
이전 포스팅에서는 JWT 토큰이 만들어지기 전에 왜 필요한지 간단히 살펴보았습니다. 이번 포스팅에서는 JWT가 무엇인지와 함께 JWT가 보안을 유지하는 데 어떤 알고리즘을 사용하는지에 대해 알아보겠습니다.
이전 포스팅을 한번 읽어보고 오시는 걸 추천드립니다.
JWT
JWT(JSON 웹 토큰) 는 당사자 간에 정보를 JSON 개체로 안전하게 전송하기 위한 간결하고 독립적인 방법을 정의하는 개방형 표준( RFC 7519 )입니다. 이 정보는 디지털 서명이 되어 있으므로 확인하고 신뢰할 수 있습니다. JWT는 비밀( HMAC 알고리즘 사용) 또는 RSA 또는 ECDSA를 사용하는 공개/개인 키 쌍을 사용하여 서명할 수 있습니다.
JWT를 암호화하여 무결성을 증명하고 정보 등을 암호화하여 다른 사용자들로부터 보호하는 역할을 합니다.
JWT에서 사용되는 알고리즘
"JWT에서 사용되는 알고리즘에 대해 알아보기 전에 기본적인 보안 알고리즘을 이해하고 활용하는 것이 중요합니다.
보안 알고리즘인 대칭키 알고리즘과 공개키 알고리즘에 대해서 간단하게 이해하고 넘어가도록 하겠습니다.
대칭키 알고리즘( Symmetric Key Algorithm )
이름에서 볼 수 있듯이 대칭되는 키를 통해 정보를 복호화하고 암호화하는 알고리즘입니다. 암호 알고리즘 중에서는 속도가 제일 빠르고 구현이 간단하지만, 키관리가 매우 어려워 키가 유출될 경우 보안에 취약할 수 있다는 단점을 가지고 있습니다.
사용자 A와 사용자 B는 동일한 "황금색 KEY" 를가지고 있습니다.
사용자 A는 사용자 B에게 개인정볼르 보내려고 하는데 개인정보가 탈취될 것이 두려워 대칭키 알고리즘을 통해 정보를 보내려고 합니다. 사용자 A, B는 동일한 키를 가지고 있어 사용자 A의 개인정보를 "황금색 KEY"로 암호화한 다음에 사용자 B에게 전송합니다.
사용자 B는 A와동일한 "황금색 KEY"를 사용해 복호화하여 A의 개인정보를 확인할 수 있습니다. 비밀번호가 "123"인 것도 확인하고 다시 정보를 잘 받았어!라고 응답을 하게 됩니다.
하지만 앞서 보안에 취약할 수 있다고 했습니다. 그림과 같이 중간에 탈취한 키를 가지고 A가 B에게 개인정보를 보낼 때 갖추래 개인정보를 변경하고 사용자 B는 복호화를 진행하고 정보를 봤는데 이상한 정보가 적혀있다면? 의심하게 될 수 있다. 하지만 엇비슷하게 내용을 변경하게 된다면 B는 정보가 해킹당했는지 모르고 사용하게 되면서 무결성이 깨지는 결과를 초래할 수 있다. 그래서 키보관을 철저히 해야 하는 알고리즘이다.
대표적으로 사용하는 것은 AES라는 대칭키 알고리즘이 있다.
공개키 알고리즘( Public Key Algorithm )
공개키 알고리즘은 공개키(public key), 개인키(private key)를 사용해 암호화를 진행하는 알고리즘입니다.
한 사용자는 공캐키와 개인키로 구성된 키를 생성하게 됩니다.
공개키(Public Key) : 공개키는 암호화에 사용되며, 누구나 이를 이용하여 데이터를 암호화할 수 있습니다. 공개키는 외부에 공개되어 있으며, 정보를 안전하게 전송하기 위해 사용됩니다.
개인키(Private Key) :개인키는 복호화에 사용되며, 키 소유자만이 이를 알고 있습니다. 개인키는 안전하게 보관되어야 하며, 이를 통해 암호화된 데이터를 복호화할 수 있습니다.
위에 그림에서처럼 A와 B는 개인키와 공개키 하나씩 생성한 상태입니다.
암호화 과정 후 데이터 전송
1. B의 공개키를 이용해 사용자 A의 개인정보를 암호화합니다.
2. A의 개인키를 이용해 데이터를 한 번 더 암호화합니다
3. 암호화된 데이터를 사용자 B에게 전송합니다.
데이터 응답 후 복호화
1. A의 공개키를 이용해 먼저 복호화합니다. 여기서 무결성을 지킬 수 있습니다.
2. B의 개인키를 이용해 복호화를 합니다.
3. B사용자는 A의 개인정보를 확인할 수 있습니다.
만약 다음과 같이 중간에 해커가 암호화된 데이터를 탈취해 복호화를 진행하려면 일단 2개의 키가 필요하나 만약에 다시 암호화를 해 무결성을 깨지지 않고 B에게 보내려면 키가 4개가 필요합니다. 매우 해커한테는 큰 비용이 발생하기 때문에 보안적으로 안전하다고 할 수 있습니다.
위와 같은 방식으로 공개키 알고리즘을 동작합니다.
대표적인 사용하는 것은 RSA입니다.
바로 JWT에서 사용되는 알고리즘입니다. 위와 같은 알고리즘을 사용해 암호화, 복호화를 진행해 보안된 서비스를 제공합니다.
HMAC 알고리즘( Hash based Message Authentication Code)
RFC2104로 발표된 MAC 기술의 일종으로, 원본 메시지가 변하면 그 해시값도 변하는 해싱(Hashing)의 특징을 활용하여 메시지의 변조 여부를 확인(인증) 하여 무결성과 기밀성을 제공하는 기술입니다.
HMAC = Hash(Message, Key) + Message
※ Hash( ) 함수는 SHA1, SHA2, MD5 등의 알고리즘 사용.
![](https://blog.kakaocdn.net/dn/1ttXF/btsFM9iPNhf/nmDWz1AkyNZO4sLEXcSMqk/img.png)
A가 메시지 "비밀번호: 123"을 B에게 보내고 싶지만, 개인정보가 노출되지 않고 안전하게 전달되길 원한다고 가정해 봅시다. 이럴 때 HMAC 알고리즘을 사용할 수 있습니다.
- A는 "비밀번호: 123" 메시지에 HMAC 알고리즘을 적용하여 비밀키를 생성합니다. 이 비밀키는 메시지의 무결성을 보호하는 데 사용됩니다. 그리고 A는 이 비밀키와 함께 메시지를 B에게 전송합니다.
- B는 메시지를 받으면서, 받은 메시지와 함께 전송된 비밀키를 사용하여 새로운 비밀키를 만듭니다. 그리고 B는 받은 메시지에 대해 새로운 비밀키를 적용하여 HMAC을 다시 생성합니다.\
- 그런 다음, B는 새로 생성된 HMAC과 A가 전송한 HMAC을 비교합니다. 만약 두 HMAC이 일치한다면, 이 메시지가 A가 보낸 것임을 증명합니다. 하지만 두 HMAC이 일치하지 않는다면, 중간에 메시지가 변경되었거나 조작되었다는 것을 의미합니다. 이 경우, B는 메시지를 신뢰하지 않고 거부할 수 있습니다.
이렇게 하면 A가 보낸 메시지가 안전하게 전달되고, 메시지의 무결성이 보호됩니다. 이것이 HMAC 알고리즘의 동작 원리입니다.
JWT 토큰의 구성
JWT토큰은 String 형식으로 되어있으며 xxxxx.yyyyy.zzzzz "."으로 구분해 세 부분으로 구성되어 있습니다.
- header
- payload
- Signature
Header(헤더)
헤더 부분에는 일반적으로 토큰(JWT)과 사용되는 Signature알고리즘(SHA, HMAC) 두 부분으로 구성되어 있습니다.
헤더는 Base64 Url로 인코딩되어 집니다. Base64Url로 암호회된 값은 디코딩을 통해서 값을 확인가능합니다.
xxxxx이 헤더가 됩니다.
{
"alg": "HS256",
"typ": "JWT"
}
payload(정보)
토큰의 두 번째 부분은 Claim을 포함하는 Payload입니다. Claim은 일반적으로 사용자의 간단한 정보를 담을 수 있습니다. (공개되어도 괜찮은 값들) Claim에는 3가지 유형이 존재합니다.
yyyyy 부분은 payload입니다.
- 등록된 Claim : 상호 운용 가능한 클레임의 집합 정보를 제공하기 위한 미리 제공된 값들이며, 필수로 사용해야 만 하는 것이 아닌 권장됩니다. iss(발행자), exp(만료시간), sub(주제), aud(청중)등이 포함되어 있습니다.
- 공개 청구 : 커스텀하게 지정할 수 있는 유형입니다. 하지만 충돌을 방지하려면 다른 설정 등 을해줘야합니다.
- 비공개 Claim : 사용에 동의한 당사자 간에 정보를 공유하기 위해 생성된 맞춤 클레임으로써, 비공개 클레임입니다.
다음과 같이 payload가 구성되어 있습니다.
{
"sub": "sub제목",
"name": "코드기록사",
"admin": true
}
Signature(서명)
서명은 보낸 데이터가 중간에 가로채 값이 변경되지 않았는지 확인하기 위해서 사용되는 값입니다. 서명을 생성하려면 인코딩 된 헤더, 페이로드와 시크릿키를 이용해 서명 부분을 생성합니다.
zzzzz부분이 Signature부분이 됩니다.
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)
이제 각각 생성된 Header, Payload, Signature을 합쳐서 JWT토큰으로 생성합니다.
다음과 같이 JWT 토큰이 생성됩니다.
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.(Header)
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.(Payload)
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c (Signature)
생성 된 토큰은 헤더 부분에 Authorization: Bearer <token> 다음과 같이 사용자에게 전송합니다.
또한 JWT 토큰은 세션 방식을 사용하는 것이 아닌 무상태(stateless) 방식을 사용하기 때문에 세션의 보안 문제점을 해결했다고 볼 수 있습니다.
JWT 토큰을 꼭 사용해야 하나?
꼭 필수로 사용해야 하는 것은 아닙니다. JWT토큰을 통해 보안을 구성한다고 하면 설정이 세션이나 쿠키방식에 비해 상당히 복잡하며 고려해야 할 것들이 무수히 많기 때문에 필수적으로 사용해야 한다라고는 할 수가 없습니다.
하지만 앞서 설명한 것처럼 세션 기반 인증 방식은 로드 밸런싱된 서버 환경에서 문제를 일으킬 수 있습니다. 그러나 JWT(JSON Web Token) 토큰은 이러한 문제를 해결할 수 있는 인증 방법입니다. JWT 토큰은 무상태(stateless)로 전송되기 때문에 여러 대의 서버를 운영하는 경우에도 잘 작동합니다.
여러 대의 서버를 운영할 때 JWT 토큰을 사용하는 것이 세션 기반 인증 방식보다 훨씬 유용합니다. 왜냐하면 JWT 토큰은 서버에 저장되지 않고 클라이언트 측에서 관리되기 때문에 특정 서버에 종속되지 않습니다. 따라서 JWT 토큰을 사용하면 로드 밸런싱된 서버 환경에서도 사용자의 세션 유지와 인증이 보장됩니다.
그러므로 여러 대의 서버를 운영할 때는 JWT 토큰을 사용하는 것이 좋습니다.
하지만 여러 대의 서버를 운영하지 않고 단일 서버를 통해 운영을 한다면 굳이 JWT토큰의 대한 사용은 올바른 방법이라고 볼 수 없습니다.
정리하기
JWT(JSON Web Token)은 클라이언트와 서버 간의 정보를 안전하게 전송하기 위한 개방형 표준으로, 헤더, 페이로드, 서명 세 부분으로 구성됩니다. 여러 대의 서버를 운영할 때는 JWT 토큰을 사용하여 로드 밸런싱된 환경에서도 세션 유지와 인증을 보장할 수 있습니다. 그러나 단일 서버를 사용하는 경우에는 JWT 토큰의 사용이 필수적이지 않을 수 있습니다
틀린 부분도 있을 수 있다고 생각합니다. 그런 부분이 있다면 댓글로 남겨주시면 수정하도록 하겠습니다. 긴 글 끝까지 읽어주셔서 감사합니다. :)
참고
'Spring > SpringSecurity' 카테고리의 다른 글
[Spring Security] JWT(JSON Web Token) 토큰 [3] - JWT+Spring Security를 사용해 로그인을 구현하기 (0) | 2024.03.16 |
---|---|
[Spring Security] JWT(JSON Web Token) 토큰 [1] - JWT 토큰의 등장 배경 (0) | 2024.03.13 |
[SpringBoot-Security] 스프링 시큐리티 동작방식 간단하게 알아보기 (0) | 2023.12.16 |
[SpringBoot-Security] 스프링 시큐리티 AJAX 통신 사용 (0) | 2023.12.13 |