JWT(JSON Web Token) ?

  • JWT(Json Web Token)란 인증에 필요한 JSON 데이터를 암호화시켜 저장한 Web Token

왜 JWT를 사용할까?

  • HTTP는 무상태(Stateless)비연결성(Connectionless)이라는 특성을 가지고 있다.
    1. Stateless: 이전 상태를 유지/기억하지 않음
      • 장점: 서버의 확장성이 높음
      • 단점: 클라이언트에게 추가 데이터를 전송해야 함
    2. Connectionless: 연결을 유지하지 않음
  • 연결을 유지하지 않고(Connectionless) 이전 상태도 기억하지 못한다(Stateless)는 것은 이동하는 페이지마다 요청을 새로 해야한다는 것을 의미한다. 즉, 사용자가 신뢰성이 있는 사용자인지 매번 인증해야 한다.
  • 이는 번거로울 뿐만 아니라 통신이 느려질 수도 있기 때문에 한 번 인증된 사용자가 일정 기간 인증을 유지하도록 JWT를 사용한다.

JWT의 구조

xxxxxx.yyyyyy.zzzzzz // Header.Payload.Signature
  • JWT는 .을 구분자로 나누어 구성된 3가지 문자열이다.
  • Header, Payload는 Base64 URL-safe로 인코딩되어 누구나 쉽게 복호화할 수 있기 때문에 절대 중요한 정보를 넣으면 안 되지만, Signature는 비밀키가 없으면 복호화할 수 없기 때문에 보안상 안전하다.

Header

  • Signature를 해싱하기 위한 해시 알고리즘 정보, 토큰 타입

Payload

  • 서버와 클라이언트가 주고 받으며, 시스템에서 실제로 사용될 정보에 대한 내용들
    • 대상, 이름, 발급일시, 만료일시 등

Signature

  • Header + Payload + 비밀키(서명)를 Header의 알고리즘으로 암호화한 문자열
    • 토큰의 위변조 여부를 확인하기 위해 사용됨
    • Header나 Payload의 데이터를 위조해도, Signature를 통해 유효한 토큰인지 알 수 있음

장점

  • 로컬에 저장하기 때문에 서버 용량에 영향을 주거나 받지 않는다.
  • 비밀키를 통해 서명하기 때문에 보다 안전하다.
  • HTTP 헤더나 URL 파라미터로 간단하게 전송하기 때문에 네트워크 부하가 적다.

단점

  • Payload에 저장되는 정보가 많아지면 네트워크 사용량이 증가하여, 데이터 설계 고려가 필요해진다.
  • 토큰이 클라이언트에 저장되어, 서버에서 클라이언트의 토큰을 조작할 수 없다.
  • 토큰이 발급되면 중간에 만료 기간 변경이 불가능하므로, 토큰 만료 처리를 구현해야 한다.

정리

JWT도 토큰 탈취의 보안 위험에서 벗어날 수 없기 때문에, 실무에서는 AccessToken과 RefreshToken처럼 기한이 있는 인증 방식을 사용한다.

둘 다 JWT로 구현되지만, AccessToken은 기한이 짧고(몇 시간에서 며칠) 클라이언트에 저장된다. RefreshToken은 AccessToken보다 수명이 길어(2주 이상) AccessToken의 재발급을 위해 사용하며 최근에는 보안을 위해 데이터베이스에 저장하고 있다.

그리고 AccessToken는 만료 기한이 짧기 때문에 로그인을 자주 해야하는 번거로움이 있을 수 있으니 AccessToken만 사용하기보다는 RefreshToken을 함께 사용해서 편리하고 보안을 강화하는 게 좋아보인다.

프로젝트에 적용한 방법

  • 가입 시 내부에서 사용할 정보를 키값과 함께 인코딩하여 accessToken과 refreshToken을 생성하는데, accessToken은 헤더에 담아 리턴해주고, refreshToken은 DB에 저장한다.
  • 클라이언트로부터 API 요청을 받을 때 accessToken이 필요하다면 함께 받은 뒤 확인하는데, 이때 만약 accessToken이 만료되었다면 DB의 refreshToken을 조회해서 만료되지 않았으면 accessToken을 새로 발급해준다.
    • 하지만 이때 refreshToken도 만료되었다면 다시 로그인하도록 에러를 리턴한다.

❓refreshToken은 어디에 두어야 할까? accessToken만 주는 것이 아니라 refreshToken도 같이 줘야 하나? 그래서 accessToken이 만료되거나 없으면 다시 같이 발급해주고 ?

  • accessToken만 사용하다가 보안 문제로 인해 refreshToken도 같이 발급하기 시작
  • refreshToken을 로컬에 저장해둘 수도 있지만, refreshToken처럼 탈취할 수 있다는 단점이 있어 최근에는 refreshToken을 서버에 저장하기 시작함
  • 결국 지금 사용하는 방식이 괜찮은 방식이며, AccessToken과 RefreshToken의 개념과 HTTP에 대해서 더 자세히 알아보는게 좋겠다.

참고