JWT

안녕하세요 똑똑한 개발자에서 백엔드 개발을 하고 있는 김영환 입니다. JMT졸맛탱이 아니라 JWT😝 웹 개발을 진행하다보면 빠질수 없는 인증 / 인가 ..
JWT에 대해서 소개해보도록 하겠습니다.

JWT 란 무엇인가

지겨우시죠? 네 저도 지겨워요 Json Web Token 약자로 모바일이나 웹의 사용자 인증을 위해 사용하는 암호화된 토큰을 의미합니다. JWT 정보를 request에 담아 사용자응 정보 열람, 수정 등 개인적인 작업 등을 수행할 수 있게한다.

그럼 JWT는 어떤 정보를 담아서 전달하나요?

JWT는 세 파트로 나누어지고, 각 파트는 .(점)으로 구분하여 aaaaa.bbbbb.ccccc 이런식으로 표현됩니다. JWT는 URL에서 파라미터로 사용할 수 있도록 URL_Safe 한 Base64url 인코딩을 사용합니다.

curl http://127.0.0.1:8000/toktokhan/ -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

header = eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
payload = eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ
signature = SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

위의 값들을 디코딩하보면…

토큰의 타입과 해시 암호화 알고리즘으로 구성되어 있습니다.

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

payload

토큰에 담을 정보가 들어있습니다. 여기에 담은 정보의 한’조각’을 클레임(claim)이라고 부르고, 이는 name/value 의 한쌍으로 이뤄져있습니다. 클레임의 종류는 등록된(registered)클레임, 공개(public)클레임, 비공개(private)클레임 이 존재합니다.

{
  "sub": "1234567890", // 등록된 플레임
  "name": "John Doe", // 비공개 플레임
  "iat": 1516239022  // 등록된 플레임
}

signature

서명은 [헤더 base64 + 페이로드 base64 + SECRET_KEY ] 를 사용하여 JWT 백엔드에서 발행됩니다
각 요청시 서명이 확인됩니다. 헤더 또는 페이로드의 정보가 클라이언트에 의해 변경된 경우 서명이 무효화됩니다.

기존의 인증 / 인가 방식과 다른점?

서버 기반 인증 기존의 인증 시스템에서는 서버측에서 유저들의 정보를 세션에 기억하고 있어야 합니다. 이 세션을 유지하기 위해서는 여러가지 방법이 사용되는데 메모리/디스크/데이터베이스 시스템에 이를 담곤 합니다. 서버 기반 인증 시스템의 흐름은 다음과 같습니다.

토큰 기반 시스템은 stateless합니다. 유저의 인정 정보를 서버나 세션에 담아두지 않기 때문에 인정정보를 서버에 담아둠으로써 발생하는 많은 문제점들이 해소됩니다. 토큰 기반 인증 시스템의 흐름은 대력적으로 다음과 같습니다.

😝 JWT의 장점

▶️ 무상태(stateless), 확장성이 있다. 기존 서버에 세션을 저장하는 방식에서 서버 여러대를 사용하여 요청을 분산하였다면 어떤 유저가 로그인했을 때 그 유저는 처음 로그인한 서버에만 요청을 내보내도록 설정해야합니다. 하지만 토큰을 사용하면 토큰 값만 알고 있다면 어떤 서버로 요청이 들어가던 상관이 없습니다. 즉, 세션스토리지가 필요없다!

▶️ 보안성 쿠키를 전달하지 않아도 되므로 쿠키를 사용함으로써 발생하는 취약점이 사라집니다.

▶️ 여러 플랫폼 및 도메인 어플리케이션 규모가 커지면 여러 디바이스를 호환 시키고 더 많은 종류의 서비스를 제공합니다. 토큰을 사용한다면 그 어떤 디바이스에서도 그 어떤 도메인에서도 토큰만 유효하다면 요청이 정상적으로 처리 됩니다.

😫 JWT의 단점

▶️ 길이 claim에 넣는 데이터가 많아질 수록 JWT토큰이 길어집니다. API호출 시 매 호출마다 토큰 데이터를 서버에 전달해야 하는데 길이가 길다는 것은 그만큼 네트워크 대역폭 낭비가 심할 수 있습니다.

▶️ 보안 JWT는 기본적으로 Payload에 대한 정보를 암호화 하지 않습니다. 단순히 BASE64로 인코딩만 하기 때문에 중간에 패킷을 가로채거나 기타 방법으로 토큰을 취득했으면 디코딩을 통해 데이터를 볼 수 있습니다. 그래서 JWE(JSON Web Encryption)를 통해 암호화 하거나 중요데이터를 Payload에 넣지 말아야 합니다.

마치는 말

다음과 같은 상황에서 JWT가 유용하게 사용 될 수 있습니다.

  1. 회원 인증: JWT 를 사용하는 가장 흔한 시나리오 입니다. 사용자가 로그인을 하면, 서버는 사용자의 정보를 기반으로한 토큰을 발급합니다. 그 후, 사용자가 서버에 요청을 할 때 마다 JWT를 포함하여 전달합니다. 서버는 클라이언트에서 요청을 받을때 마다, 해당 토큰이 유효하고 인증됐는지 검증을 하고, 사용자가 요청한 작업에 권한이 있는지 확인하여 작업을 처리합니다. 서버에서는 사용자에 대한 세션을 유지 할 필요가 없습니다. 즉 사용자가 로그인되어있는지 안되어있는지 신경 쓸 필요가 없고, 사용자가 요청을 했을때 토큰만 확인하면 되므로 세션 관리가 필요 없어서 서버 자원과 비용을 절감할 수 있습니다.

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

younghwan.kim's profile image

younghwan.kim

2021-04-30 10:35

Read more posts by this author