JWT(Json Web Token) 란 무엇일까? (서버 기반 인증 / 토큰 기반 인증)
by coco3oJWT에 대해 알아보기 전에 먼저 "토큰 기반 인증"과 "서버 기반 인증"에 대해 알아보자.
서버 기반 인증 시스템이란? (Session / Cookie)
세션 기반의 인증 시스템이다. 서버 측에서 사용자들의 정보를 기억하기 위해 세션을 유지하는데,
이는 메모리, 디스크, 데이터베이스 등을 통해 관리한다.
클라이언트로부터 요청을 받으면 클라이언트의 상태 정보를 저장하여 유지해야 하므로 Stateful 한 구조를 가진다.
[ 인증 방식 ]
1. 사용자가 로그인 시 올바른 사용자임을 확인하고, 고유한 세션 ID 값을 부여해 세션 저장소에 저장하고 클라이언트에게 발급해준다.
2. 클라이언트는 세션 ID를 받아 쿠키에 저장하고, 인증이 필요한 요청마다 쿠키에 세션 ID를 담아 헤더에 보낸다.
3. 서버에서는 쿠키를 받아 세션 저장소와 비교해 올바른 요청인지 확인한다.
4. 인증이 완료되고 서버는 요청에 응답한다.
[ 장점 ]
- 중요한 정보는 서버에 있기 때문에 쿠키 자체(세션 ID)에는 유의미한 값을 가지고 있지 않다.
[ 단점 ]
- 해커가 훔친 쿠키를 이용해 HTTP 요청을 보내면 서버에서는 올바른 사용자가 보낸 요청인지 알 수 없다. (세션 하이재킹 공격)
> 세션에 유효시간을 넣어줘야 한다.
- 서버에 세션을 저장하므로 사용자가 증가함에 따라 과부하를 줄 수 있어 확장성이 용이하지 못한다.
- 시스템 확장이 어렵다.
토큰 기반 인증 시스템이란? (JWT)
이러한 단점을 극복하기 위해 "토큰 기반 인증 시스템"이 나왔다. 인증받은 사용자에게 토큰을 발급해주고,
서버에 요청을 할 때 HTTP 헤더에 토큰을 함께 보내 인증받은 사용자(유효성 검사)인지 확인한다.
서버 기반 인증 시스템과 달리 사용자의 인증 정보를 서버에 저장하지 않고 클라이언트의 요청으로만 인가를 처리하므로 Stateless 한 구조를 가진다.
JWT는 Json Web Token의 약자로 인증에 필요한 정보를 암호화시킨 토큰을 뜻한다.
세션/쿠키 방식과 유사하게 클라이언트는 Access Token(JWT)을 HTTP 헤더에 실어 서버로 보낸다.
[ 인증 방식 ]
1. 사용자가 로그인 시 올바른 사용자임을 확인하고, 클라이언트에게 Access Token(JWT)을 발급해준다.
2. 클라이언트는 전달받은 토큰을 저장해 두고, 인증이 필요한 요청마다 토큰을 HTTP 헤더에 담아 보낸다.
3. 서버에서는 암호화된 토큰을 복호화 해 올바른 요청인지 확인한다.
4. 인증이 완료되고 서버는 요청에 응답한다.
[ 장점 ]
- 서버 기반 인증 시스템은 저장소의 관리가 필요하지만, 토큰 기반은 Access Token을 발급해준 후 요청이 들어오면 검증만 해주면 되기 때문에 추가 저장소가 필요 없다. 즉 Stateless 하다.
- 쿠키를 사용함으로 인해 발생하는 취약점이 사라진다. 하지만, 토큰을 사용하는 환경에서의 취약점에 대비해야 한다.
- 확장성이 뛰어나다. 토큰 기반으로 하는 다른 인증 시스템에 접근이 가능하다. Ex) facebook, Google 등
[ 단점 ]
- 이미 발급된 JWT를 돌이킬 수 없다. 서버 기반 인증 시스템처럼 저장소를 사용하는 경우에는 해당 세션이 악의적으로 사용될 경우 지워버리면 되지만, JWT는 한 번 발급되면 유효기간이 완료될 때 까지는 계속 사용이 가능하다.
- 즉, 유효기간이 지나기 전까지 실컷 털릴 수 있다.
- JWT의 길이가 길다. 인증이 필요한 요청이 많아질수록 서버의 자원 낭비가 발생한다.
정리하면..
서버 기반 인증 방식은 과거에 사용하던 방식이고 이를 대체하기 위하여 등장한 것이 토큰 기반 인증 방식이지만,
토큰 기반 인증 방식을 사용한다고 해서 무조건 해킹의 위험에서 벗어난 것은 아니다.
JWT(JSON Web Token)란?
JWT 란 JSON 포맷을 이용해 사용자에 대한 속성을 저장하는 Claim 기반의 웹 토큰이다.
JWT는 토큰 자체를 정보로 사용하는 Self-Contained 방식으로 정보를 안전하게 전달한다.
※JWT는 주로 static 변수와 로컬 스토리지에 저장한다고 한다. static 변수에 저장하는 이유는 HTTP 통신을 할 때마다 JWT를 HTTP 헤더에 담아서 보내야 하는데, 이를 로컬 스토리지에서 계속 불러오면 오버헤드가 발생하기 때문이다.
JWT(JSON Web Token)의 구조
JWT는 세 파트로 나누어지며, 각 파트를 점( . )으로 구분한다.
각 순서대로 헤더(header), 페이로드(payload), 서명(signature)로 구성되고,
JSON 형태인 각 부분은 BASE64로 인코딩 되어 표현된다.
1. Header(헤더)
: 토큰의 타입과 해시 암호화 알고리즘으로 구성된다.
alg는 헤더를 암호화 하는 것이 아닌, Signature를 해싱하기 위한 알고리즘을 지정하는 것이다.
{
"alg": "HS256",
"typ": "JWT"
}
typ : 토큰의 타입을 지정한다.
alg : 알고리즘 방식을 지정하며, 서명(Signature) 및 토큰 검증에 사용한다.
2.Payload(내용)
: 토큰에 사용자가 담고자 하는 정보를 담는 곳
Payload에는 토큰에서 사용할 정보의 조각들인 Claim 이 담겨있고,
이는 JSON(Key/Value) 형태의 한 쌍으로 이루어져 있다. 클레임의 종류는 아래와 같이 크게 3 종류로 나누어져 있다.
2-1 등록된 클레임(Registered Claim)
등록된 클레임은 토큰 정보를 표현하기 위해 이름이 이미 정해진 종류의 데이터이다.
등록된 클레임의 사용은 모두 선택적이지만, 사용할 것을 권장한다.
iss : 토큰 발급자 (issuer)
sub : 토큰 제목 (subject)
aud : 토큰 대상자 (audience)
exp : 토큰의 만료시간 (expiraton) : NumericDate 형식으로 되어 있어야 한다.
nbf : 토큰 활성 날짜(not before) : 이 날이 지나기 전의 토큰은 활성화되지 않는다.
iat : 토큰 발급 시간(issued at) : 토큰 발급 이후의 경과 시간을 알 수 있다.
jti : JWT 고유 식별자(JWT ID) : 중복 방지를 위해 사용하며, 일회용 토큰(Access Token) 등에 사용한다.
{
"iss": "dev-coco.tistory.com",
"exp": "1602076408",
"https://dev-coco.tistory.com/jwt": true,
"userId": "dev-coco"
"username": "coco"
}
위의 예시에는 2개의 Registered Claim과 1개의 Public Claim 그리고 2개의 Private Claim으로 이루어져 있다.
2-2 공개 클레임(Public Claim)
공개 클레임은 사용자 정의 클레임으로, 충돌이 방지된 이름을 가져야 하며, 충돌 방지를 위해 클레임 이름을 URI 형식으로 짓는다.
{
"https://dev-coco.tistory.com/jwt": true
}
2-3 비공개 클레임(Private Claim)
비공개 클레임은 사용자 정의 클레임으로, 클라이언트와 서버가 협의하에 임의로 지정한 정보를 저장해서 사용한다.
{
"userId": "dev-coco"
"username": "coco"
}
3. Signature(서명)
: 토큰을 인코딩하거나 유효성 검증을 할 때 사용하는 고유한 암호화 코드이다.
헤더(Header)와 내용(Payload)의 값을 각각 BASE64로 인코딩하고, 인코딩한 값을 비밀키를 이용해
헤더에서 정의한 알고리즘으로 해싱을 하고, 이 값을 다시 BASE64로 인코딩하여 생성한다.
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret
)
위의 Header + Payload + Signature를 합치면 아래의 비밀스런 코드가 완성된다.
그리고 위 코드를 Decoded하면 아래 처럼 뜨게 된다.
참고 :
[JWT] 서버 인증 이해하기 - JWT란, 서버 인증 / 토큰 인증
https://mangkyu.tistory.com/56?category=925341
https://strange-developer.tistory.com/50
'🪐Server' 카테고리의 다른 글
클라우드 컴퓨팅(Cloud Computing)이란? (0) | 2022.04.15 |
---|---|
서버리스(Serverless)란? (1) | 2022.04.09 |
스케일 업(Scale-Up)과 스케일 아웃(Scale-Out)이란? (0) | 2022.02.07 |
서버 사이드 렌더링(ssr) & 클라이언트 사이드 렌더링(csr) (0) | 2021.11.08 |
REST란? REST API 와 RESTful API의 차이점 (6) | 2021.08.13 |
블로그의 정보
슬기로운 개발생활
coco3o