JWT란 무엇일까?

Alex·2025년 1월 16일
0

CS를 공부하자

목록 보기
14/74

보통 서버가 클라이언트 인증을 확인하는 방식은 쿠키,세션,토큰 세가지가 있다.

각 인증방식을 먼저 알아보자

쿠키란?

쿠키는 Key-value형태의 문자열 덩어리다. 클라이언트가 웹사이트를 방문하면, 그 사이트가 사용하는 서버를 통해 클라이언트의 브라우저에 설치되는 작은 기록 정보 파일이다. 각 사용자마다 브라우저에 정보를 저장하니 고유 정보 식별이 가능하다.

  • 브라우저가 서버에 요청을 보낸다.
  • 서버는 클라이언트의 요청에 대한 응답을 작성할 때, 클라이언트 측에 저장하고 싶은 정보를 응답 헤더의 set-cookie에 담는다.
  • 클라이언트는 요청을 보낼 때마다 매번 저장된 쿠키를 요청 헤더의 Cookie에 담아보낸다. 이걸 기반으로 이용자를 식별한다.

단점은?

  • 보안에 취약하다. 요청시 쿠키 값을 그대로 보내서 탈취 가능성이 있다.
  • 용량 제한이 있어 많은 정보를 담지 못한다.

세션이란?

쿠키의 보안적 이슈 때문에, 비밀번호 같은 클라이언트의 민감 정보를 브라우저가 아닌 서버 측에 저장을 할 수 있다.

골자는 민감한 정보는 클라이언트에 보내지 말고 서버에서 모두 관리한다는 것이다.

  • 유저가 웹사이트에 로그인하면 세션이 서버 메모리 상에 저장된다. 세션을 식별하기 위한 세션 id를 기준으로 정보 저장한다.
  • 서버에서 브라우저 쿠키에 세션 id를 저장한다.
  • 쿠키에 정보가 담겨져 있기 때문에, 브라우저는 해당 사이트에 대한 요청의 쿠키에 세션 id를 담는다.
  • 서버는 클라이언트가 보낸 세션 id와 서버 메모리에서 관리하는 세션 id를 비교해서 인증을 수행한다.

단점은

  • 쿠키를 포함한 요청이 외부에 노출되도 세션 id는 유의미한 개인정보를 담지 않지만, 해커가 세션 id 자체를 탈취해서 클라이언트인척 위장할 수 있다.
  • 서버에서 세션 저장소를 사용하므로 요청이 많아지면 서버 부하가 커진다.

토큰이란?

클라이언트가 서버에 접속하면, 서버는 인증의 의미로 토큰을 부여한다. 클라이언트는 이 토큰을 요청 헤더에 넣어서 계속 인증을 시도한다.

기존 세션 기반은, 세션 정보를 계속 메모리에 보관해야 하기에 부하가 커졌지만 이 방식은 토큰을 서버가 아니라 클라이언트에 저장한다.

  • 사용자가 아이디와 비밀번호로 로그인한다.
  • 서버 측에서 사용자에게 유일한 토큰을 발급한다.
  • 클라이언트는 토큰을 쿠키나 스토리지에 저장하고, 서버에 요청할 때마다 해당 토큰을 HTTP 요청 헤더에 전달한다.

단점은?

  • 데이터 길이가 길어저 인증 요청이 많아질수록 네트워크 부하가 커진다.
  • 페이로드는 암호화되지 않기 때문에 유저의 중요한 정보를 담을 수 없다.
  • 토큰이 탈취되면 대처하기 어렵다(보통 사용 기간 제한을 설정하는 식으로 극복한다)

그럼 JWT는 뭐야?

JWT(Json Web Token)이란

  • Json 포맷을이용해서 사용자 속성을 저장하는 Claim 기반의 Web 토큰이다.

보통 JWT는 static 변수와 로컬 스토리지에 저장한다. static 변수에 저장하는 이유는 HTTP 통신마다 JWT를 헤더에 담아야 하는데, 로컬 스토리지에서 계속 불러오면 오버헤드가 발생할 수 있기 때문이다.

JWT 구조

JWT는 Header, Payload, Signature 세 부분으로 이루어지며, 각 부분은 Base64Url로 인코딩된다.

Header

  • typ : 토큰의 타입
  • alg :Signature를 해싱하기 위한 알고리즘을 지정

Payload
토큰에 사용할 정보의 조각들인 클레임들이 담겨있다.

등록된 클레임

->토큰 정보를 표현하기 위해 이미 정해진 데이터들로, 선택적으로 작성이 가능하다.

  • iss: 토큰 발급자(issuer)
  • sub: 토큰 제목(subject)
  • aud: 토큰 대상자(audience)
  • exp: 토큰 만료 시간(expiration), NumericDate 형식으로 되어 있어* 야 함 ex) 1480849147370
  • nbf: 토큰 활성 날짜(not before), 이 날이 지나기 전의 토큰은 활성화되지 않음
  • iat: 토큰 발급 시간(issued at), 토큰 발급 이후의 경과 시간을 알 수 있음
  • jti: JWT 토큰 식별자(JWT ID), 중복 방지를 위해 사용하며, 일회용 토큰(Access Token) 등에 사용

공개 클레임
->사용자 정의 클레임으로, 공개용 정볼르 위해 사용한다.

비공개 클레임
->서버와 클라이언트 사이에 임의로 지정한 정보를 저장한다.

Signature

토큰을 인코딩하거나 유효성 검증을 할 때 사용하는 고유한 암호화 코드다. 서명은 위에서 만든 헤더와 페이로드의 값을 각각 BASE64Url로 인코딩하고, 인코딩한 값을 비밀키를 이용해 헤더에서 정의한 알고리즘으로 해싱하고, 이 값을 다시 BASE64Url로 인코딩해서 생성한다.

시그니쳐는 one-way 해시방식으로, 이를 복호화하는 게 불가능하다. 클라이언트에서 보낸 JWT를 통해서 시그니쳐를 만들고, 원래 JWT의 시그니쳐와 비교해서 다른 부분이 있으면 조작됐다고 확인하는 방식이다.

주의할 사항

1) 정보가 많아질수록 토큰길이가 길어져서 네트워크 부하가 커질수 있다.
2) 페이로드는 암호화된 게 아니라, BASE64Url로 인코딩된 것이다. 중간에 페이로드를 탈취해서 디코딩할 수 있기에 중요 데이터를 넣지 말아야 한다.
3) JWT는 Stateless 구조라서 상태를 저장하지 앟는다. 한번 만들어지면 제어가 불가능하기에, 토큰을 임의로 삭제하는 게 불가능하다. 토큰 만료 시간을 꼭 넣어주어야 한다.

JWT 인증 과정

  • 사용자가 로그인 시도를 한다.
  • 서버는 인증 요청을 받고 JWT를 생성한 뒤에, 쿠키에 담아 클라이언트에 발급한다.
  • 클라이언트는 JWT를 로컬 스토리지나 쿠키에 저장한다. API 서버에 요청할 때 Header에 액세스 토큰을 담아 보낸다.
  • 서버는 JWT 토큰을 검증한다.
  • 클라이언트가 서버에 요청했는데, 액세스 토큰이 만료되면 리프래시 토큰을 이용해서 새로운 액세스 토큰을 받는다.

참고 자료

profile
답을 찾기 위해서 노력하는 사람

0개의 댓글