포스트

2022-02-23-TIL

Today I Learned

JWT

JSON 객체를 사용해서 토큰 자체에 정보를 저장하는 웹 토큰의 일종이다. 아주 간편하고 쉽게 적용할 수 있어서 몇 가지 고려사항만 잘 지키면 작은 프로젝트부터 대규모 프로젝트까지 잘 적용할 수 있다.

RFC 7519는 JWT를 두 당사자 사이에 주고받을 클레임(claim)을 표현하는 간결하고 URL에 안전한 수단으로 정의한다. 클레임은 JSON 객체로 인코딩되어 JWS(서명) 구조의 payload나 JWE(암호화) 구조의 평문으로 들어간다. 흔히 말하는 JWT는 대부분 서명만 한 JWS 형태다.

구조

Header, Payload, Signature 세 개의 부분으로 구성되어 있다. 각 부분을 Base64URL로 인코딩해 점(.)으로 이어 붙인다.

1
2
xxxxx.yyyyy.zzzzz
Header.Payload.Signature
  • Header는 Signature를 만들 때 쓰는 알고리즘 정보(alg)와 토큰 타입을 담고 있다.
  • Payload는 서버와 클라이언트가 주고받는 시스템에서 실제로 사용될 정보에 대한 내용을 담고 있다. RFC는 발급자(iss), 주체(sub), 만료 시각(exp), 발급 시각(iat) 같은 등록된 클레임 이름을 정의한다.
  • Signature는 토큰의 유효성 검증을 위한 문자열이다. Header와 Payload를 비밀 키(또는 개인 키)로 서명한 값이라서, 서버는 이 문자열로 토큰이 위조되거나 변조되지 않았는지 검사할 수 있다.

여기서 자주 오해하는 부분이 있다. 서명한 JWT의 Payload는 암호화된 것이 아니라 Base64URL로 인코딩만 된 것이다. 누구나 디코딩해서 내용을 읽을 수 있으므로 비밀번호나 개인정보를 넣으면 안 된다. 서명이 보장하는 것은 내용이 바뀌지 않았다는 사실이지, 내용을 숨기는 것이 아니다.

JWT 장점

  • 중앙의 인증 서버, 데이터 스토어에 대한 의존성이 없다. 토큰 자체에 필요한 정보와 서명이 있으므로 어느 서버든 키만 있으면 검증할 수 있다. 시스템 수평 확장에 유리하다.
  • Base64 URL Safe Encoding을 쓰므로 URL, Cookie, Header 모두 사용 가능하다.

JWT 단점

  • Payload의 정보가 많아지면 매 요청마다 실어 보내는 크기가 커지므로 네트워크 사용량이 증가한다. 어떤 클레임을 넣을지 데이터 설계를 고려해야 한다.
  • 토큰이 클라이언트에 저장되므로 서버에서 클라이언트의 토큰을 조작할 수 없다. 즉 한 번 발급한 토큰은 만료 시각(exp) 전까지 서버가 무효화하기 어렵다. 그래서 액세스 토큰의 만료 시간을 짧게 두고 리프레시 토큰으로 재발급하거나, 강제 로그아웃이 필요하면 차단 목록을 서버에 따로 두는 방식을 함께 쓴다. 차단 목록을 두는 순간 “서버 상태가 없다”는 장점 일부를 포기하는 셈이다.

검증할 때 주의할 점

RFC 8725 (JWT Best Current Practices)는 라이브러리가 호출자가 허용한 알고리즘만 쓰고, Header의 alg가 실제로 사용하는 알고리즘과 같은지 확인해야 한다고 요구한다. 공격자가 alg를 none으로 바꾸는 공격이 알려져 있기 때문이다. 토큰이 들고 온 Header를 그대로 믿지 말고, 서버가 기대하는 알고리즘을 명시해서 검증해야 한다.

참고한 자료외부 출처 3

외부 출처

이 글은 저작권자의 CC BY 4.0 라이선스를 따릅니다.

변경이력

2번 수정

  1. docs(posts): write every reference entry as title, then publisher
  2. docs(til): fill out the thin 2022 tils

댓글

아직 댓글이 없습니다