[이론편] JWT(Json Web Token) 란 ?

mallin·2022년 1월 22일
0

JWT

목록 보기
1/2
post-thumbnail

옛날에는 서버 기반 인증 방식을 사용하다가 시스템이 점점 많아지고 커짐에 따라 서버 기반 인증 방식의 한계가 나타났고, 토큰 기반 인증 방식이 등장하게 되었다. JWT 는 토큰 기반 인증 방식 중 하나인데 두 인증 방식의 차이부터 JWT 이론 및 실습까지 차근차근 알아보자.

이건 TMI 인데 .. 진짜 처음에 JWT 에 대한 인식 없었을 때 JWT 에 대해서 들었을 때 java 에서만 사용하는 토큰 인 줄 알았다 😰

서버(세션) 기반 인증 방식 vs 토큰 기반 인증 방식

토큰 / 서버 기반 인증 방식이 필요한 이유

HTTP 는 다음과 같이 2가지의 특징을 가지고 있는데

이름설명
Connenctionless클라이언트가 요청을 서버에게 보내면 서버는 이에 대한 적절한 응답을 한 후에 연결을 종료합니다.
StatelessConnenctionless의 특징으로 서버와 클라이언트와의 연결이 종료된다면 상태 정보는 저장하지 않고 사라집니다.

위 특징을 가지고 있기 때문에 로그인 후 사용자가 새로운 요청을 했을 때 과거에 로그인 한 사실을 기억하지 못한다
👉 그렇기 때문에 어딘가에 사용자가 로그인 했다는 걸 저장하고 있어야 한다.

서버(세션) 기반 인증 방식

서버를 기반으로 인증하는 방식이다.
그렇기 때문에 서버 측에서 사용자들의 정보를 기억하고 있어야 한다.
서버 기반 인증 방식은 서버 측에서 유저 정보를 세션을 통해 저장한다.

서버(세션) 기반 인증 방식은 아래와 같은 과정을 가진다.


출처 : https://velopert.com/2350#google_vignette

  1. 유저가 로그인
  2. 서버에서 유저에 대한 세션 생성 및 유지
  3. 유저가 인증 요청을 하는 경우 세션 저장소에서 읽어서 응답

즉, 유저의 정보는 서버에 저장되어 있고,
유저가 요청을 했을 때 서버에 있는 사용자 정보로 유효한 사용자인지 확인하고 맞는 경우 응답을 한다.

하지만 서버 인증 방식에는 몇가지의 단점이 있다.

🤔 단점

① 사용자 수가 늘어날수록 세션으로 저장하는 정보가 증가하기 때문에 메모리를 많이 사용하게 된다
② 세션을 관리할 때 많이 사용하는 쿠키는 단일 도메인 및 서브 도메인에서만 작동하기 때문에 여러 도메인에서 관리가 번거롭다

이러한 문제점을 해결하기 위해 토큰 기반 인증 방식이 나오게 되었다

토큰 기반 인증 방식

인증받은 사용자들에게 토큰을 발급하고, 서버에 요청을 할 때 헤더에 토큰을 함께 보내서 유효성을 검사한다.
서버측에서 사용자에 대한 정보를 가지고 있지 않고 클라이언트에서 오는 요청 만으로 인증을 진행한다


출처 : https://velopert.com/2350#google_vignette

  1. 유저가 로그인 요청
  2. 서버에서 유저정보에 대해서 토큰 생성 후 응답
  3. 유저가 서버에 정보 요청할 때 토큰 정보와 함께 요청
  4. 서버는 토큰이 정상적인 토큰인지 검사한다음 정상적인 토큰이면 응답

서버에서 사용자에 대한 정보를 가지고 있지 않고, 사용자가 토큰을 가지고 요청을 하는 방식이다

🙂 장점

① 무상태성 (Stateless)
: 토큰 기반 인증 방식에서 사용되는 토큰은 서버가 아니라 클라이언트 측에 저장되기 때문에 서버는 완전히 Stateless 하다.

② 확장성 (Scalability)
: 클라이언트와 서버의 연결 고리가 없기 때문에 확장성이 매우 용이하다.
EX) 토큰 기반 인증 방식이 아니라 서버 기반 인증 방식인 경우 서버를 확장하여 분산처리를 한다면, 해당 사용자는 처음 로그인 했었던 서버에만 요청을 받도록 설정해주야 하지만 토큰 기반 인증 방식은 토큰만 있으면 되기 때문에 상관 없다.

③ 보안성
: 클라이언트가 서버로 요청을 보낼 때 더 이상 쿠키를 전달하지 않으므로, 쿠키 사용에 의한 취약점이 사라진다

④ 여러 플랫폼 및 도메인
: 서버 기반 인증 시스템의 문제점 중 하나인 CORS를 해결할 수 있다. 토큰을 사용한다면 어떤 디바이스, 어떤 도메인에서도 토큰의 유효성 검사를 진행한 후에 요청을 처리할 수 있다. 이런 구조를 통해 assests 파일(Image, html, css, js 등)은 모두 CDN에서 제공하고, 서버 측에서는 API만 다루도록 설게할 수 있다.

🤔 단점

① 보안
: 토큰이 노출될 경우 유효기간이 지나기 전까지는 토큰을 사용할 수 있다. 이를 해결하기 위해 유효기간을 짧게 잡고 갱신할 수 있도록 해야한다.

토큰 기반 방식의 장점 중 하나인 무상태성에서 stateless 라는 말이 잠깐 나왔는데, stateless 란 뭘까 ?

stateless vs stateful

상태를 서버에서 저장하는지 안하는지 여부에 따라 나눠진다

stateless (무상태)
서버에서 브라우저의 상태(쿠키 or 세션)를 저장하지 않는 형태
토큰 기반 인증 방식이 여기에 속한다.
EX) TCP

stateful (상태 유지)
서버에서 브라우저의 상태(쿠키 or 세션)를 저장하는 형태
서버 기반 인증 방식이 여기에 속한다.
EX) UDP / HTTP

그러면 이제 본격적으로 JWT 에 대해서 알아보도록 하자

JWT (Json Web Token) 란 ?

JSON 객체를 사용하여 가볍고 자가수용적인 (self-contained) 방식으로 정보를 안전성 있게 전달해주기 위한 토큰

위에서 설명한 서버 기반 인증 방식과 토큰 기반 인증 방식 중 토큰 기반 인증 방식에 속한다.

공식 사이트 👉 https://jwt.io/

JWT 구성

.을 구분자로 3가지 문자열로 구성되어 있다

jwt 토큰은 위에 명시되어 있는 공식 사이트에서 복호화 해볼 수 있다. 아래는 공식 사이트에 공개되어 있는 JWT 예시이다.

Signature 를 해싱하기 위한 알고리즘 정보

typ : 토큰의 타입을 지정
alg : 해싱 알고리즘 지정 , 토큰을 검증 할 때 사용되는 signature 부분에서 사용한다.

Payload

서버와 클라이언트가 주고받는 , 시스템에서 실제로 사용될 정보에 대한 내용

  • 토큰에 담을 정보
  • 여기에 담는 정보의 한 조각 을 클레임 (claim) 이라고 부르고 name / value 로 이루어져 있다
  • 토큰에는 여러 클레임을 담을 수 있다
  • 등록된 클레임, 공개 클레임, 비공개 클레임으로 이루어져 있다.

클레임이란 ?

등록된 클레임

  • 토큰 정보를 표현하기 위해 이미 정해진 종류의 데이터
  • 서비스에서 필요한 정보들이 아닌, 토큰에 대한 정보들을 담기 위하여 이름이 이미 정해진 클레임
  • 사용은 모두 선택적이지만 사용할 것을 권고한다.
이름설명
iss토큰 발급자
sub토큰 제목
aud토큰 대상자
exp토큰 만료 시간
nbf토큰의 활성 날짜
iat토큰이 발급된 시간
jtiJWT 의 고유 식별자 , 중복 처리를 방지하기 위하여 사용

공개 클레임

  • 사용자 정의 클레임
  • 공개용 정보를 위해서 사용한다.
  • 충돌이 방지된 이름을 가져야 하기 때문에 클레임 이름을 URI 형식으로 작성한다.
"https://soyeon.com/jwt_claims/is_admin": true

비공개 클레임

  • 사용자 정의 클레임
  • 양 측간(보통 클라이언트 ↔ 서버) 협의하에 사용되는 클레임 이름들
  • 공개 클레임과는 달리 이름이 중복되어 충돌이 될 수 있다
username: "soyeon"

2개의 등록된 클레임 + 1개의 공개 클레임 + 2개의 비공개 클레임으로 구성된 예시

{
	"iss": "naver.com",
	"exp": "1485270000000",
	"http://naver.com/jwt_claims/is_admin": true,
	"userId": "12",
	"username": "soyeon"
}

Signature

토큰의 유효성 검증을 위한 문자열

  • 고유한 암호화 코드
  • 위 토큰이 유효한지 유효하지 않은지에 대한 정보를 가짐
  • 암호화에 사용되는 키 값은 서버에 저장해 놓음
  • 헤더의 인코딩 값과 정보의 인코딩값을 합친 후 주어진 비밀키로 해쉬를 하여 생성

사용방법

생성된 토큰은 HTTP 통신 할 때 header 에 Authorization value 로 값을 넘겨주면 사용할 수 있다

{ 
 "Authorization": "Bearer {생성된 토큰 값}",
}

Access Token vs Refresh Token

Access Token

  • 인증을 위한 토큰
  • 보안을 위해 만료 기간이 짧다
  • 서버에 따로 저장되지 않고 클라이언트가 토큰을 가지고 있다.

Refresh Token

  • Access Token 이 만료되었을 때 새로운 토큰을 발급해주기 위한 키
  • Access Token 보단 만료 기간이 길다
  • 서버에 따로 저장

시나리오

  1. 유저가 로그인 하는 경우 응답으로 Access Token, Refresh Token 발급
         👉 Refresh Token 은 서버에서 저장하고 있음
  2. API 에 접근 하는 경우 토큰 검사
Access TokenRefresh Token결과
유효유효인증 완료, 요청한 정보 리턴
유효만료Refresh Token 재발급
만료유효Access Token 재발급
만료만료권한 없음

장점 vs 단점

장점

  • 중앙의 인증서버, 데이터 스토어에 대한 의존성 없음 , 시스템 수평 확장 유리
  • Base64 URL Safe Encoding > URL, Cookie, Header 모두 사용 가능

단점

  • Payload 의 정보가 많아지면 네트워크 사용량 증가, 데이터 설계 고려 필요
  • 토큰이 클라이언트에 저장, 서버에서 클라이언트의 토큰을 조작할 수 없음
  • 토큰 자체에 정보가 저장되기 때문에 보안성에 문제가 생길 수 있음

🙇🏻‍♀️ 레퍼런스

[Server] 토큰 기반 인증 VS 서버(세션) 기반 인증
JWT란?
[Server] JWT(Json Web Token)란?
JWT란?

0개의 댓글