[인증/인가] - JWT

Kim Hyen Su·2023년 11월 10일

🔒인증인가

목록 보기
3/9
post-thumbnail

🎆 JWT란?

웹에서 사용되는 웹 토큰의 표준규격.(RFC 7519)

사용자의 인증, 인가 정보를 서버와 클라이언트 간에 안전하게 주고 받기위해 사용됩니다.

이를 위해 JSON 형태의 정보를 암호화 및 해싱 알고리즘을 통해 서명으로 만들어 토큰에 담아 통신하게 됩니다.

즉, JWT 하나로 인증을 수행할 수 있습니다.

🎇 JWT 구조


  • JWT 구조
[ 헤더 ] . [ 페이로드 ] . [ 서명 ]

위와같이 헤더, 페이로드, 서명이 .(dot)로 구분하여 하나의 JWT 토큰을 구성합니다.

  • 헤더에는 토큰의 유형해싱 알고리즘 이 명시되어 있습니다.

    {
     "alg" : "HS256",
     "typ" : "JWT" 
    }
  • 페이로드(내용)에는 토큰과 관련된 인증인가를 위한 정보를 담습니다.

    페이로드의 한 덩어리를 "claim" 이라고 하며, 키와 값의 한쌍으로 이뤄져 있습니다.

    claim은 크게 3가지로 구분됩니다.

    • 등록된 클레임(Registered) : 토큰에 대한 정보를 포함.

      • iss : 토큰 발급자 (issuer)
      • sub : 토큰 제목 (subject)
      • aud : 토큰 대상자 (audience)
      • exp : 토큰의 만료시간 (expiraton), 시간은 NumericDate 형식으로 되어있어야 하며 (예: 1480849147370) 언제나 현재 시간보다 이후로 설정되어 있어야 합니다.
      • nbf : Not Before 를 의미하며, 토큰의 활성 날짜와 비슷한 개념입니다. 여기에도 NumericDate 형식으로 날짜를 지정하며, 이 날짜가 지나기 전까지는 토큰이 처리되지 않습니다.
      • iat : 토큰이 발급된 시간 (issued at), 이 값을 사용하여 토큰의 "age" 가 얼마나 되었는지 판단 할 수 있습니다.
      • jti : JWT의 고유 식별자로서, 주로 중복적인 처리를 방지하기 위하여 사용됩니다. 일회용 토큰에 사용하면 유용합니다.
    • 공개 클레임 : JWT를 사용하는 사용자가 원하는 대로 정의할 수 있습니다.

      클레임명의 충돌을 방지하려면 IANA JSON Web Token Registry 에 정의하거나 충돌 방지 네임스페이스를 포함하는 URI로 정의해야합니다.

    💡 IANA JSON Web Token Registry란?

    JWT(Json Web Token)를 사용하는 사용자가 자유롭게 정의할 수 있는 Public claims에 대해 충돌을 방지하기 위해 정의되어 있는 레지스트리를 말합니다.

    • 비공개 클레임 : 통신하는 당사자간에 정보를 공유하기 위한 커스텀 클레임, 중복으로 인한 충돌에 주의해야 합니다.
  • 서명에는 헤더와 페이로드의 인코딩된 값을 secret key를 통해 암호화되어 저장됩니다.

    실제 서버 측에서 인증 시에 서명부분을 비밀키로 복호화하여 정보를 검증하게 됩니다.

주의사항

payload는 서명된 값들이 아니므로, 단순 Base64로 인코딩된 데이터입니다.

따라서, 누구나 Base64로 디코딩하여 데이터 열람이 가능하므로, 회원의 중요 정보를 담으면 안됩니다.

🎇 JWT 특징

  • Http 프로토콜의 주요 특징인 무상태성을 가짐
  • 디바이스 종류에 무관하게 사용 가능

🎇 JWT 장단점

장점
  • 중앙의 인증서버, 데이터 스토어에 대한 의존성 없음, 시스템 수평 확장이 유리
  • Base64 URL Safe Encoding 이므로 URL, Cookie, Header 모두에서 사용 가능
단점
  • Payload에 정보가 많아지면 네트워크 사용량이 증가, 데이터 설계 고려 필요
  • 서버에서 클라이언트의 토큰을 조작할 수 없기 때문에 탈취에 대한 대처에 취약

🎇 토큰기반인증 VS 세션기반인증

HTTP는 무상태 프로토콜의 일종이다.

❓무상태 프로토콜
  • 각 요청 간에 독립적으로 처리되며, 저장됮 않고 서로 다른 요청 간에 관련이 없다.

따라서, HTTP 자체로는 인증을 한번 성공하더라도, 다음 요청 시에 다시 인증 과정을 거쳐야 되는 상황이 발생하게 된다.

이러한 HTTP 프로토콜의 한계를 극복하기 위한 인증 방식이 크게 2가지가 있다.

✅ 세션 기반 인증

  • 서버 기반의 인증 방식.
  • 서버 내 세션을 통해 인증 정보를 저장하고 관리한다.
  • 보안성이 좋으나, 최근 대규모 서비스를 제공하는 서버가 많아지게 되면서 서버에 부담이 되기 시작했다. 이러한 경우, sacale 확장 작업이 필요한 경우가 발생하게 된다.
  • 하지만 세션 기반 인증의 경우, 스케일을 수평 확장 할 경우 각 서버마다 세션이 달라지게 되어 인증/인가 정보를 공유해야 되는 상황이 발생하게 된다. 이는 로직적으로 구현하기가 상당히 어렵고 관리가 힘들다고 한다...

✅ 토큰 기반 인증

  • 위처럼 세션 기반의 인증의 한계를 극복하고자, 최근 토큰 기반 인증이 많이 사용된다.
  • 서버는 로그인 성공 시 클라이언트로 토큰을 발급한다. 클라이언트는 토큰을 저장하며, 서버 요청 시마다 토큰을 가지고 가서 리소스를 받아오는 형태이다.
  • 서버에서는 토큰 발급과 인증/인가 과정만 수행된다.
  • 또한, 토큰은 Stateless하여, 서버가 토큰의 상태 확인 및 관리가 불가하다. 이는 서버 내 토큰의 정보를 보관하지 않기 때문에 토큰에 대한 제어권이 없기 때문이다.
  • 위와 같은 이유로, 만약 토큰을 탈취 당하게 된다면 토큰의 만료 전까지 무방비하게 민감정보가 노출될 수 있다.(민감정보 노출의 위험이 커짐.)
  • 이를 보완하기 위해서 토큰 에 민감정보를 직접 담으면 안되며, 만료 기한을 최대한 짧게 설정해야 한다. 하지만, 너무 짧게 잡게되면, 클라이언트 입장에서 자주 인증/인가를 거쳐야 하는 불편함이 발생하게 된다.
  • 이와 같은 문제를 해결하기 위해 고안된 것이 access-tokenrefresh-token이다.

📖 access-token과 refresh-token은 다음 포스팅에서 자세하게 다루겠습니다.

profile
백엔드 서버 엔지니어

0개의 댓글