이 게시글은 verlopert의 jwt 강의 내용을 요약한 것입니다.

Token 인증 기반이란?

소개

현재 많은 모던 웹서비스에서 토큰 기반 인증 시스템을 이용하고 있는 주요 이유들은 다음과 같다.

Stateless 서버

  • Stateful 서버
    Client에게 요청 받을 때마다 client의 상태를 계속 유지하고 이 정보를 서비스 제공에 이용하는 서버. 세션을 유지하고 있는 서버가 이에 해당한다. 유저의 로그인 정보를 세션에 저장해두고(서버 컴퓨터 메모리 or DB에) 서비스를 제공할 때 이 데이터를 이용한다.

  • Stateless 서버
    상태 정보를 저장하지 않고 server는 client에서 들어오는 요청으로만 작업을 처리 -> client와 server 같의 연결고리가 없기 때문에 확장성(Scalability)이 높아진다.

Mobile Application에 적합하다

모바일 어플리케이션을 개발한다면, 안전한 API를 만들기 위해선 쿠기 컨테이너같은 인증시스템은 이상적이지 않다.

인증 정보를 다른 Application으로 전달

OAuth 같은 경우가 이에 해당. Kakao, Naver, Google, Facebook 같은 소셜 계정으로 다른 웹서비스에서도 로그인 할 수 있게 된다.

보안

Application의 보안을 높일 수 있다.

기존의 서버 기반 인증시스템

세션 저장소에 user의 세션 정보를 담아놓고 요청이 들어오면 해당 데이터를 이용하여 서비스를 제공하는 방식이었다.
-> 서버를 확장하기 어려워 지는 등의 문제가 발생했다.

문제점 1 - 세션

세션저장소를 대부분 메모리에 둘텐데, 로그인 중인 유저의 수가 늘어난다면? 서버의 램에 과부하가 발생한다. DB에 저장하는 방식 또한 DB 성능에 무리를 줄 수 있다.

문제점 2 - 확장성

서버를 확장하는 것이 어려워진다. 멀티프로세싱이나 여러 대의 서버 컴퓨터를 추가하는 등의 확장을 하면 세션 저장소에 대한 분산 시스템을 설계해야 하며, 확장 과정이 매우 복잡해진다.

문제점 3 - CORS(Cross-Origin Resource Sharing)

세션을 관리할 때 일반적으로 쿠리를 사용한다. 쿠키는 단일 도메인 및 서브 도메인에서만 작동되도록 설계되어있다.


토큰 기반 시스템의 작동 원리

Stateless하다. 즉, 이 시스템에서는 user의 인증 정보를 서버나 세션에 담아두지 않는다.
세션이 존재하지 않으니, 유저들이 로그인 되어있는지 안되어있는지 신경도 쓰지 않으면서 서버를 손쉽게 확장할 수 있다.

구현 방식

시스템마다 크고 작은 차이가 있겠지만, 대략적으로 보면 다음과 같다.

  1. 유저가 id,pw로 로그인
  2. 서버 측에서 해당 계정정보를 검증
  3. 계정 정보가 정확하다면 서버측에서 user에게 signed 토큰을 발급
    signed : 토큰이 서버에서 정상적으로 발급된 토큰임을 증명하는 서명(signature)를 지니고 있다는 의미
  4. client는 전달받은 토큰을 저장해두고 요청할 때마다 서버에 token을 전달
  5. 서버는 token을 검증하고 요청에 응답

JWT?

특징

기본 정보

JSON Web Token(JWT)은 웹표준(RFC 7519)으로서 두 개체에서 JSON 객체를 사용하여 가볍고 self-contained(자가수용적인) 방식으로 정보를 안정성 있게 전달해준다.

수많은 프로그래밍 언어에서 지원

Self-contained?

JWT는 필요한 모든 정보를 자체적으로 지니고 있다. JWT 시스템에서 발급된 토큰은 토큰에 대한 기본 정보, 전달할 정보, 서명을 포함하고 있다.

쉽게 전달 가능

자가수용적이기 때문에 두 개체 사이에서 손쉽게 전달될 수 있다. 웹서버의 경우 HTTP 헤더에 넣어서 전달할 수 있고, URL의 파라미터로 전달할 수도 있다.

어떤 상황에서 사용될까?

회원 인증

  • user가 로그인을 하면 server는 user의 정보에 기반한 토큰을 발급하여 유저에게 전달
  • 그 후, user가 서버에 요청할 때마다 JWT를 포함하여 전달
  • server는 user가 보내는 JWT가 유효하고 인증됐는지 확인

정보 교류

두 개체 사이에서 안정성있게 정보를 교환하기에 좋은 방법이다. 정보가 sign되어 있기 때문에 정보를 보낸 이가 바뀌진 않았는지, 또 정보가 도중에 조작되지는 않았는지 검증할 수 있다.

JWT의 구조

#Header.Payload.Signature
aaaaaaa.bbbbbbb.ccccccccc
  • typ : 토큰의 타입
  • alg : Hashing 알고리즘
{
    "typ": "JWT",
    "alg": "HS256"
}

Payload

토큰에 담을 정보가 들어있다. 여기에 담는 정보의 한 조각을 Claim이라고 부르고, name/value의 한 쌍으로 이루어져 있다.

클레임의 종류는 다음과 같이 크게 세 분류로 나뉜다.

등록된(Registered) 클레임

서비스에서 필요한 정보들이 아닌, 토큰에 대한 정보들을 담기 위하여 이름이 정해진 Claim들
registered claim의 사용은 모두 optional이며 이에 포함된 claim들은 다음과 같다.

  • iss : 토큰 발급자
  • sub : 토큰 제목
  • aud : 토큰 대상자
  • exp : 토큰 만료시간
  • nbf : Not Before. 토큰 활성 날짜와 비슷한 개념
  • iat : 토큰이 발급된 시간
  • jti : JWT의 고유식별자. 일회용 토큰에서 많이 사용함.
공개(Public) 클레임

공개 클레임들은 충돌이 방지된(collision-resistant)이름을 가지고 있어야 한다. 즉, 이름이 겹치면 안된다.

{
    "https://velopert.com/jwt_claims/is_admin":true # 충돌 방지를 위해 이름을 url 형식으로 지음
}
비공개(Private) 클레임

registered도, public도 아닌 클레임. client, server 간 협의 하에 사용되는 클레임들이다.
이름이 중복되어 충돌이 가능하므로 주의해야 한다.

    "username" : "velopert"

Signature

Header의 인코딩 값과 정보의 인코딩값을 합친 후 주어진 비밀키로 hash를 하여 생성.

profile
새로운 기술을 테스트하고 적용해보는 걸 좋아하는 서버 개발자

0개의 댓글

관련 채용 정보

Powered by GraphCDN, the GraphQL CDN