TIL 2021-02-02 (TOKEN)

nyongho·2021년 2월 2일
0

JWT

목록 보기
1/1

TOKEN


TIL List


1) 서버 기반 인증 시스템

토큰에 대해 얘기 하기 앞서 먼저 서버 기반 인증 시스템에 대해서 짚고 넘어가야 할 것 같다.

서버 기반 인증 시스템 이란?

기존의 인증 시스템은 서버 기반의 인증 방식으로, 서버 측에서 사용자들의 정보를 기억하고 있어야 한다. 사용자들의 정보를 기억하기 위해서는 세션을 유지해야 하는데, 메모리나 디스크 또는 데이터베이스 등을 통해 관리한다. 서버 기반의 인증 시스템은 클라이언트로부터 요청을 받으면, 클라이언트의 상태를 계속해서 유지하고 이 정보를 서비스에 이용하는데, 이러한 서버를 Stateful 서버라고 한다. 예를 들어 사용자가 로그인을 하면, 세션에 사용자 정보를 저장해두고 서비스를 제공할 때 사용하곤 한다.

쉽게 우리가 자주 사용하는 포털 사이트인 네이버를 예시로 들어보자.

네이버의 검색 기능 외에 회원 가입을 해야만 이용할 수 있는 네이버 메일, 네이버 페이 등의 서비스를 이용하기 위해서

우리는 네이버에 회원 가입을 해야 한다.

네이버 측에서는 유저가 회원 가입을 하면 해당 유저가 작성한 정보를 어느 곳에 저장 해두어야 한다. 그렇지 않으면

유저는 매번 해당 서비스를 이용할 때마다 회원가입을 해야하는 불편함을 겪을 것이다.

그럼 위와 같은 서버 기반 인증 시스템 을 이용하여 회원의 정보를 저장한다고 가정해보자.

이러한 시스템을 구축한 네이버는 후에 20000명 이상의 유저를 확보했다고 가정한다면, 네이버는 어떠한 부담을 갖게 될까?


1-1. 데이터베이스 과부하

사용자가 인증을 할 때 이러한 정보 (Session) 를 저장하기 위해 네이버는 어떠한 곳에 이 정보를 저장해야 하는데

서버 기반 인증 시스템에서는 이러한 정보들을 대부분 메모리 (RAM) 에 저장한다.

근데 만약 로그인 중인 회원이 많아지게 될 경우 그 메모리 또한 많이 사용하게 되므로

메모리의 부담이 자연스럽게 커지게 된다.

이를 피하기 위해서 유저의 인증 정보를 데이터베이스에 저장한다고 해도 이는 임시적인 방편일 뿐 데이터베이스 또한

로그인 중인 유저의 수가 증가함에 따라 그 부담도 비례하므로 그 근본적인 해결책이 될 수 없다.


1-2. 확장성의 복잡함

네이버에 사용자가 늘어나게 되면 동시간대에 많은 유저들이 사이트를 이용함에 따라 많은 트래픽을 발생시킨다.

이러한 방대한 트래픽을 처리하기 위해서는 프로세스를 많이 돌리거나 컴퓨터를 추가하는 등의 방법으로 서버를 확장해야 한다.

이 과정에서 세션을 사용한다면 이러한 세션들을 분산시키는 시스템을 설계해야 하지만, 이러한 과정은 매우 복잡하다.


1-3. CORS (Cross-Origin Resource Sharing) 의 번거로움

웹 어플리케이션에서 세션을 관리할 때 자주 사용되는 쿠키는 단일 도메인 및 서브 도메인에서만 작동하도록 설계되어 있다.

따라서 쿠키를 여러 도메인에서 관리하는 것은 번거롭다.

서버 기반 인증 시스템은 이러한 문제들을 가지고 있다.

그래서 그 이후, 토큰 기반 인증 시스템이 등장하게 된다.


2) 토큰 기반 인증 시스템

토큰 기반 인증 시스템 이란?

토큰 기반의 인증 시스템은 인증받은 사용자들에게 토큰을 발급하고, 서버에 요청을 할 때 헤더에 토큰을 함께 보내도록 하여 유효성 검사를 한다. 이러한 시스템에서는 더이상 사용자의 인증 정보를 서버나 세션에 유지하지 않고 클라이언트 측에서 들어오는 요청만으로 작업을 처리한다. 즉, 서버 기반의 인증 시스템과 달리 상태를 유지하지 않으므로 Stateless한 구조를 갖는다. 이러한 토큰 기반의 인증 방식을 통해 수많은 문제점들을 해결할 수 있는데, 대표적으로 사용자가 로그인이 되어있는지 안되어있는지 신경쓰지 않고 손쉽게 시스템을 확장할 수 있다.

놀이공원을 예로 들어보자.

만약 놀이공원의 티켓을 구입하는 대신 스태프가 입장객 리스트에다가 내 정보를 적어두고 내가 관람할 때 마다

그 리스트에서 내 이름을 찾는다고 생각해보자. 이렇게 되면 스태프는 입장객에 대한 방대한 데이터를 계속 지니고 있어야

하고 이 입장객의 이름을 찾는데에도 오래 걸릴 것이다.

즉, 굉장히 비효율적이다.

하지만 토큰을 발급해준다면?

해당 토큰을 가지고 있는 사람은 자연스럽게 입장객이 될 것이므로 해당 토큰의 유무로서만 판단하면 끝인 것이다.


2-1. 토큰 기반 인증 시스템의 처리 과정

  1. 사용자가 아이디와 비밀번호로 로그인 요청을 보낸다.

  2. 서버 측에서 해당 정보가 데이터베이스에 있는 정보와 일치하는지 검증한다.

  3. 정보가 정확하다면, 서버 측에서 사용자에게 Signed 토큰을 발급한다. (해당 토큰이 서버에서 발급한 토큰임을 증명하는 Signature 를 의미)

  4. 클라이언트는 해당 토큰을 저장해두고, 서버에 특정 요청을 할 때마다 해당 토큰과 함께 요청을 보낸다.
    (토큰을 보내는 방법은 http 요청 헤더에 토큰을 포함시키면 된다.)

  5. 서버는 유저가 보낸 토큰을 검증하고, 해당 토큰에 따라 요청을 보낸다.

위에서 클라이언트는 고객이고, 서버는 놀이공원 스태프 라고 생각하면 편하다.


3) JWT (Json Web Token)

JWT ?

JWT(Json Web Token)란 Json 포맷을 이용하여 사용자에 대한 속성을 저장하는 Claim 기반의 Web Token이다. JWT는 토큰 자체를 정보로 사용하는 Self-Contained 방식으로 정보를 안전하게 전달한다. 주로 회원 인증이나 정보 전달에 사용되는 JWT는 아래의 로직을 따라서 처리된다.

3-1. JWT 의 구조

JWT 는 Header, Payload, Signature 3 부분으로 이루어져 있으며 각 부분은 JSON 형태로 Base64로 인코딩 되어 있다.

(참고로 Base64 는 암호화된 문자열이 아니다)

3-2. HEADER

토큰의 헤더는 typalg 두 가지 정보로 구성된다. alg는 헤더(Header)를 암호화 하는 것이 아니고, Signature를 해싱하기 위한 알고리즘을 지정하는 것이다.

typ: 토큰의 타입을 지정 ex) JWT

alg: 알고리즘 방식을 지정하며, 서명(Signature) 및 토큰 검증에 사용 ex) HS256(SHA256) 또는 RSA

{ 
 "alg": "HS256",
 "typ": JWT
 }

3-3. PAYLOAD

페이로드에는 토큰에서 사용할 정보의 조각들인 클레임이 담겨 있다. 여기에는 JSON 형태로 다수의 정보를 넣을 수 있다.

하지만 PAYLOAD 는 그만큼 탈취하기 쉬우므로 중요한 정보는 절대로 PAYLOAD 에 넣지 않아야 한다.

3-4. PAYLOAD 의 클레임

클레임은 공개 클레임, 비공개 클레임, 등록된 클레임으로 이루어져 있다.

공개 클레임

공개 클레임은 말 그대로 공개용 정보를 위해 사용된다. (URI 포맷을 사용하면 된다.)

{ "https://bsg-land.com": true }

비공개 클레임

비공개 클레임은 말 그대로 비공개용 정보를 위해 사용된다. 주로 서버와 클라이언트 사이에 임의로 지정한 정보를 저장한다.

{ "token_type": access }

3-5. Signature

Signature(서명)은 토큰을 인코딩 혹은 유효성 검증을 할 때 사용하는 고유한 암호화 코드이다.

Signature는 Header 와 Payload 를 Base64 형태로 인코딩하고, 인코딩한 값을 비밀 키 (SECRET_KEY) 를 이용해 Header 에서 정의한 알고리즘으로 해싱한 뒤, 이 값을 다시 Base 64 로 인코딩 한다.

이렇게 만들어진 토큰들은 HTTP 통신을 할때 Authorization 이라는 key 의 값으로 사용된다.

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

4) JWT 의 단점?

우선 토큰의 가장 큰 문제점은 토큰 그 자체에 정보가 있다는 것이다. 이러한 점을 항상 기억해야 한다.

두 번째로 JWT 는 정보를 저장하지 않는 Stateless 한 형태이기 때문에 한 번 생성하게 되면 그 이후 제어가 불가능 하다.

따라서 토큰의 만료 기간을 꼭! 지정해 줘야 후에 다른 유저가 해당 토큰을 이용해 잘못된 행동을 하는 것을 방지할 수 있다.


profile
두 줄 소개

0개의 댓글