JWT 토큰 인증 방식에 대해 알아보자 ❕
오늘날 많은 서비스들이 JWT를 이용한 토큰 인증 방식으로 사용자들의 인증/인가를 확인한다. JWT란 무엇이며 어떤 방식으로 인증에 사용되는지 공부하려고 한다.
1. JWT (Json Web Token)
Json Web Token의 약자로, 인증에 필요한 정보들을 암호화시킨 Json 토큰을 의미한다. JWT는 HTTP header에 담겨 전달된다.
JWT는 Json 데이터를 Base64로 인코딩하여 직렬화하고, 토큰 내부는 위변조 방지를 위해 개인키(private key)를 통한 전자서명이 들어있다. 서버는 인증된 클라이언트에게 JWT토큰을 발급해주고, 클라이언트는 매 요청마다 JWT를 HTTP header에 담아 서버에게 전송한다. 그럼 서버는 개인키를 통해 JWT토큰을 검증하고, 검증이 완료되면 요청에 대한 응답을 전달한다.
(보통 HTTP header에 `"Authorization" : "Bearer <생성된 토큰 값>"` 형태로 저장해 사용한다)
구조
JWT는 세 파트로 나눠지며, 각 파트를 '.'으로 구분한다.
구분된 세 파트는 Header(헤더), Payload(내용), Signature(서명)을 의미한다.

- Header (헤더)
- 토큰의 타입(typ)과 해시 암호화 알고리즘(alg)으로 구성된다.
- Payload (내용)
- 담고자 하는 사용자 정보를 정보를 담는다.
- key-value 형태로 데이터를 저장하는데, 이를 Claim(클레임)이라고 한다.
- 클레임은 등록된 클레임(Registered Claim), 공개 클레임(Public Claim), 비공개 클레임(Private Claim)로 나누어 저장한다.
- 등록된 클레임(Registered Claim)은 미리 정의된 클레임으로 다음과 같은 종류가 있다. 모두 3글자로, 선택해서 일부만 작성해도 되는데 모두 작성하는 것이 좋다.
- iss (issuer : 발행자)
- exp (expiration time : 만료 시간)
- sub (subject: 제목)
- iat (issued at : 발행 시간)
- jti (jwt id)
- 다만, Payload에 있는 내용은 수정이 가능하고 쉽게 확인할 수 있기 때문에 민감한 정보는 담으면 안된다.
- Signature (서명)
- (Header + Payload)를 Base64 인코딩 한 값과 개인키로 서명한 전자서명값을 Header에 명시된 해시함수로 암호화해 담는다.
- ^누군가 Payload의 정보를 조작해도 Signature에는 수정되기 전 Payload 내용을 토대로 저장되므로 서버는 해당 토큰이 조작되었는지 쉽게 알 수 있다.^ (Signature는 server 측에서 관리하는 개인키를 포함한 값을 암호화하므로 server 측 개인키가 유출되지 않는 이상 복호화할 수 없다)
⇒ JWT는 디버거를 사용해서 인코딩된 내용을 바로 복호화할 수 있다. 복호화하면 Payload에 담은 정보들이 쉽게 노출되어 버린다. 따라서 Payload에는 민감한 정보는 담으면 안된다. JWT는 정보 보호를 목적으로 하는 것이 아닌 위변조 방지를 목적으로 하는 것이다.
즉, JWT는 토큰 안에 들어있는 정보가 무엇인지 아는게 중요한 게 아니라 해당 토큰이 서버가 발급한 유효한 토큰인지 확인하기 위한 것이다.
다음 사이트에서 직접 JWT 토큰을 생성하고 인코딩/디코딩 할 수 있다.
JWT.IO
JSON Web Tokens are an open, industry standard RFC 7519 method for representing claims securely between two parties.
jwt.io

Signature의 your-256-bit-secret
에는 서버측에서 관리하는 개인키가 들어간다.
2. JWT 토큰 인증

- 사용자가 id, pw를 입력해 서버에 로그인 인증을 요청한다.
- 서버는 유저의 정보를 확인한 후 Header, Payload, Signature를 정의해 JWT 토큰을 발급하고 이를 쿠키에 담아 클라이언트에게 전달한다.
- 클라이언트는 전달받은 JWT를 로컬 스토리지 및 쿠키에 담아둔다.
- 이후 클라이언트는 서버에 요청할 때 HTTP header
Authorization
에 JWT를 담아서 요청한다. - 서버는 요청 온 HTTP header의
Authorization
을 읽어 해당 서버가 발급한 토큰인지 검증한다. - 토큰 검증이 성공되면 클라이언트의 요청에 대한 응답을 전달하고, 토큰 검증이 실패하면 요청을 차단한다.
3. JWT 장단점
장점
- Signature를 이용해 데이터 위변조를 확인하여 요청을 차단할 수 있다. (전자서명 사용)
- Self-contained : 인증 정보에 대한 별도의 저장소가 필요없다. (Payload에 유저이름과 권한을 담아두면 DB를 조회할 필요가 없기 때문)
- 서버는 무상태(stateless)가 되어 확장성이 우수하다.
- 다른 로그인 시스템에 접근 및 권한 공유가 가능하다. (쿠키와 차이)
- 모바일 어플리케이션 환경에서도 잘 동작한다.
- CORS 및 분산 환경에서도 사용할 수 있다.
단점
- Self-contained : 토큰 자체에 정보를 담고 있으므로 담겨진 정보를 볼 수 있다.
- Payload에 담는 정보가 많아질수록 토큰의 길이가 늘어가 네트워크 부하가 생길 수 있다.
- Payload는 암호화 된 것이 아니라 Base64 인코딩된 것이기 때문에, 민감한 데이터를 넣지 못한다.
- 토큰은 클라이언트 측에서 관리하고 저장하므로 토큰 자체를 탈취당하면 대처하기 어렵다.
- 한 번 발급된 토큰은 유효 기간 동안 계속 사용할 수 있으므로, 토큰이 유출되거나 탈취당했을 때 해당 토큰을 무효화할 수 있는 방법이 없다.
4. Access Token & Refresh Token
JWT는 한 번 발급되면 유효 기간 동안 계속 사용할 수 있으므로, 토큰이 유출되거나 탈취되었을 때 해당 토큰을 무효화할 수 있는 방법이 없다. 그렇다고 토큰 만료 시간(exp)을 짧게 설정한다면 유저는 로그인하는 횟수가 많아지면서 서비스를 이용하는데 불편함을 겪을 것이다.
따라서 오늘날 서비스 대부분은 Access Token & Refresh Token 두 가지 토큰을 발급해 관리함으로써 위 문제를 해결한다. Access Token과 Refresh Token 모두 JWT이며, 토큰이 어떻게 저장되고 사용되느냐에 따라 이름을 분리한 것이다.
- Access Token : 유저의 정보가 담긴 토큰으로, 클라이언트는 서버의 리소스를 요청할 때 해당 토큰을 이용한다. 짧은 수명을 가진다.
- Refresh Token : 새로운 Access Token을 발급해주기 위해 사용되는 토큰으로, 해당 토큰은 DB에 저장해 사용한다. 탈취당하면 안되는 토큰이다.
⇒ 유저가 로그인하면, 서버는 Access Token & Refresh Token을 발급해 Refresh Token은 DB에 저장하고 Access Token은 클라이언트에게 전달한다. Access Token에는 유저의 정보를 담고 만료시간을 짧게 설정한다. 만약 유저의 Access Token이 만료된다면 Refresh Token을 이용해 Access Token을 재발급받아 사용한다. 따라서 유저의 로그인 시간을 연장할 수 있도록 하고, 인가에 사용되는 토큰(Access Token)의 만료시간을 짧게 설정해 보안을 강화한 것이다.
Access Token & Refresh Token 동작 흐름

- 유저가 로그인 요청을 한다.
- 서버는 유저의 로그인 정보를 확인 후, Access Token과 Refresh Token을 발급한다.
- 이때 Refresh Token은 DB에 저장하고, Access Token만 쿠키에 담아 클라이언트에게 전달한다.
- 클라이언트는 전달받은 Access Token을 로컬 스토리지 및 쿠키에 담아둔다.
- 만약 로컬 스토리지에 저장했다면, 이후 클라이언트는 서버에 요청할 때 HTTP header
Authorization
에 Access Token을 담아 요청한다. (쿠키에 저장한다면 자동으로 서버에 전달되므로 HTTP header 설정을 추가로 할 필요 없다) - 서버는 요청된 HTTP header의
Authorization
을 읽어 Access Token이 현재 서버에서 발행한 토큰인지 검증한다. - 토큰 검증이 성공되면 클라이언트의 요청에 대한 응답을 전달하고, 토큰 검증이 실패하면 요청을 차단한다.
- 만약, Access Token이 만료되었다면 Refresh Token을 이용해 Access Token을 재발급한 후 클라이언트에게 전달한다.
- 클라이언트는 새롭게 발급된 Access Token을 이용해 서버에게 요청을 보낸다.
참고자료 😃
'Web' 카테고리의 다른 글
[Web] XSS & CSRF (0) | 2024.05.29 |
---|---|
[Web] Servlet & JSP (0) | 2024.05.04 |
[Web] Cookie & Session & Token 인증 (0) | 2024.04.06 |
[Web] 웹 스토리지 (localStorage & sessionStorage) (0) | 2024.04.02 |
[Web] Web Server & WAS (0) | 2024.03.30 |
JWT 토큰 인증 방식에 대해 알아보자 ❕
오늘날 많은 서비스들이 JWT를 이용한 토큰 인증 방식으로 사용자들의 인증/인가를 확인한다. JWT란 무엇이며 어떤 방식으로 인증에 사용되는지 공부하려고 한다.
1. JWT (Json Web Token)
Json Web Token의 약자로, 인증에 필요한 정보들을 암호화시킨 Json 토큰을 의미한다. JWT는 HTTP header에 담겨 전달된다.
JWT는 Json 데이터를 Base64로 인코딩하여 직렬화하고, 토큰 내부는 위변조 방지를 위해 개인키(private key)를 통한 전자서명이 들어있다. 서버는 인증된 클라이언트에게 JWT토큰을 발급해주고, 클라이언트는 매 요청마다 JWT를 HTTP header에 담아 서버에게 전송한다. 그럼 서버는 개인키를 통해 JWT토큰을 검증하고, 검증이 완료되면 요청에 대한 응답을 전달한다.
(보통 HTTP header에 "Authorization" : "Bearer <생성된 토큰 값>"
형태로 저장해 사용한다)
구조
JWT는 세 파트로 나눠지며, 각 파트를 '.'으로 구분한다.
구분된 세 파트는 Header(헤더), Payload(내용), Signature(서명)을 의미한다.

- Header (헤더)
- 토큰의 타입(typ)과 해시 암호화 알고리즘(alg)으로 구성된다.
- Payload (내용)
- 담고자 하는 사용자 정보를 정보를 담는다.
- key-value 형태로 데이터를 저장하는데, 이를 Claim(클레임)이라고 한다.
- 클레임은 등록된 클레임(Registered Claim), 공개 클레임(Public Claim), 비공개 클레임(Private Claim)로 나누어 저장한다.
- 등록된 클레임(Registered Claim)은 미리 정의된 클레임으로 다음과 같은 종류가 있다. 모두 3글자로, 선택해서 일부만 작성해도 되는데 모두 작성하는 것이 좋다.
- iss (issuer : 발행자)
- exp (expiration time : 만료 시간)
- sub (subject: 제목)
- iat (issued at : 발행 시간)
- jti (jwt id)
- 다만, Payload에 있는 내용은 수정이 가능하고 쉽게 확인할 수 있기 때문에 민감한 정보는 담으면 안된다.
- Signature (서명)
- (Header + Payload)를 Base64 인코딩 한 값과 개인키로 서명한 전자서명값을 Header에 명시된 해시함수로 암호화해 담는다.
- 누군가 Payload의 정보를 조작해도 Signature에는 수정되기 전 Payload 내용을 토대로 저장되므로 서버는 해당 토큰이 조작되었는지 쉽게 알 수 있다. (Signature는 server 측에서 관리하는 개인키를 포함한 값을 암호화하므로 server 측 개인키가 유출되지 않는 이상 복호화할 수 없다)
⇒ JWT는 디버거를 사용해서 인코딩된 내용을 바로 복호화할 수 있다. 복호화하면 Payload에 담은 정보들이 쉽게 노출되어 버린다. 따라서 Payload에는 민감한 정보는 담으면 안된다. JWT는 정보 보호를 목적으로 하는 것이 아닌 위변조 방지를 목적으로 하는 것이다.
즉, JWT는 토큰 안에 들어있는 정보가 무엇인지 아는게 중요한 게 아니라 해당 토큰이 서버가 발급한 유효한 토큰인지 확인하기 위한 것이다.
다음 사이트에서 직접 JWT 토큰을 생성하고 인코딩/디코딩 할 수 있다.
JWT.IO
JSON Web Tokens are an open, industry standard RFC 7519 method for representing claims securely between two parties.
jwt.io

Signature의 your-256-bit-secret
에는 서버측에서 관리하는 개인키가 들어간다.
2. JWT 토큰 인증

- 사용자가 id, pw를 입력해 서버에 로그인 인증을 요청한다.
- 서버는 유저의 정보를 확인한 후 Header, Payload, Signature를 정의해 JWT 토큰을 발급하고 이를 쿠키에 담아 클라이언트에게 전달한다.
- 클라이언트는 전달받은 JWT를 로컬 스토리지 및 쿠키에 담아둔다.
- 이후 클라이언트는 서버에 요청할 때 HTTP header
Authorization
에 JWT를 담아서 요청한다. - 서버는 요청 온 HTTP header의
Authorization
을 읽어 해당 서버가 발급한 토큰인지 검증한다. - 토큰 검증이 성공되면 클라이언트의 요청에 대한 응답을 전달하고, 토큰 검증이 실패하면 요청을 차단한다.
3. JWT 장단점
장점
- Signature를 이용해 데이터 위변조를 확인하여 요청을 차단할 수 있다. (전자서명 사용)
- Self-contained : 인증 정보에 대한 별도의 저장소가 필요없다. (Payload에 유저이름과 권한을 담아두면 DB를 조회할 필요가 없기 때문)
- 서버는 무상태(stateless)가 되어 확장성이 우수하다.
- 다른 로그인 시스템에 접근 및 권한 공유가 가능하다. (쿠키와 차이)
- 모바일 어플리케이션 환경에서도 잘 동작한다.
- CORS 및 분산 환경에서도 사용할 수 있다.
단점
- Self-contained : 토큰 자체에 정보를 담고 있으므로 담겨진 정보를 볼 수 있다.
- Payload에 담는 정보가 많아질수록 토큰의 길이가 늘어가 네트워크 부하가 생길 수 있다.
- Payload는 암호화 된 것이 아니라 Base64 인코딩된 것이기 때문에, 민감한 데이터를 넣지 못한다.
- 토큰은 클라이언트 측에서 관리하고 저장하므로 토큰 자체를 탈취당하면 대처하기 어렵다.
- 한 번 발급된 토큰은 유효 기간 동안 계속 사용할 수 있으므로, 토큰이 유출되거나 탈취당했을 때 해당 토큰을 무효화할 수 있는 방법이 없다.
4. Access Token & Refresh Token
JWT는 한 번 발급되면 유효 기간 동안 계속 사용할 수 있으므로, 토큰이 유출되거나 탈취되었을 때 해당 토큰을 무효화할 수 있는 방법이 없다. 그렇다고 토큰 만료 시간(exp)을 짧게 설정한다면 유저는 로그인하는 횟수가 많아지면서 서비스를 이용하는데 불편함을 겪을 것이다.
따라서 오늘날 서비스 대부분은 Access Token & Refresh Token 두 가지 토큰을 발급해 관리함으로써 위 문제를 해결한다. Access Token과 Refresh Token 모두 JWT이며, 토큰이 어떻게 저장되고 사용되느냐에 따라 이름을 분리한 것이다.
- Access Token : 유저의 정보가 담긴 토큰으로, 클라이언트는 서버의 리소스를 요청할 때 해당 토큰을 이용한다. 짧은 수명을 가진다.
- Refresh Token : 새로운 Access Token을 발급해주기 위해 사용되는 토큰으로, 해당 토큰은 DB에 저장해 사용한다. 탈취당하면 안되는 토큰이다.
⇒ 유저가 로그인하면, 서버는 Access Token & Refresh Token을 발급해 Refresh Token은 DB에 저장하고 Access Token은 클라이언트에게 전달한다. Access Token에는 유저의 정보를 담고 만료시간을 짧게 설정한다. 만약 유저의 Access Token이 만료된다면 Refresh Token을 이용해 Access Token을 재발급받아 사용한다. 따라서 유저의 로그인 시간을 연장할 수 있도록 하고, 인가에 사용되는 토큰(Access Token)의 만료시간을 짧게 설정해 보안을 강화한 것이다.
Access Token & Refresh Token 동작 흐름

- 유저가 로그인 요청을 한다.
- 서버는 유저의 로그인 정보를 확인 후, Access Token과 Refresh Token을 발급한다.
- 이때 Refresh Token은 DB에 저장하고, Access Token만 쿠키에 담아 클라이언트에게 전달한다.
- 클라이언트는 전달받은 Access Token을 로컬 스토리지 및 쿠키에 담아둔다.
- 만약 로컬 스토리지에 저장했다면, 이후 클라이언트는 서버에 요청할 때 HTTP header
Authorization
에 Access Token을 담아 요청한다. (쿠키에 저장한다면 자동으로 서버에 전달되므로 HTTP header 설정을 추가로 할 필요 없다) - 서버는 요청된 HTTP header의
Authorization
을 읽어 Access Token이 현재 서버에서 발행한 토큰인지 검증한다. - 토큰 검증이 성공되면 클라이언트의 요청에 대한 응답을 전달하고, 토큰 검증이 실패하면 요청을 차단한다.
- 만약, Access Token이 만료되었다면 Refresh Token을 이용해 Access Token을 재발급한 후 클라이언트에게 전달한다.
- 클라이언트는 새롭게 발급된 Access Token을 이용해 서버에게 요청을 보낸다.
참고자료 😃
'Web' 카테고리의 다른 글
[Web] XSS & CSRF (0) | 2024.05.29 |
---|---|
[Web] Servlet & JSP (0) | 2024.05.04 |
[Web] Cookie & Session & Token 인증 (0) | 2024.04.06 |
[Web] 웹 스토리지 (localStorage & sessionStorage) (0) | 2024.04.02 |
[Web] Web Server & WAS (0) | 2024.03.30 |