JWT 문제점에 관한 고찰

Hyeon-Uk·2023년 7월 18일
0

끄적끄적

목록 보기
3/4
post-thumbnail

JWT란?

JSON Web Tokens are an open, industry standard RFC 7519 method for representing claims securely between two parties.

(출저 : jwt.io)
주로 사용자의 인증/인가 정보를 서버-클라이언트간에 안전하게 주고 받기 위해 사용되는 Json형태의 token입니다.

구조는 어떻게 이루어져있나?

JWT는 크게 3부분으로 이루어져 있습니다.

헤더부분에는 토큰의 유형(typ), 서명에 사용된 알고리즘(alg)가 명시되어 있습니다.

payload

페이로드 부분은 크게 3가지 부분으로 나누어져있습니다.

Registered(등록)

등록된 클레임부분에는 토큰에 대한 정보를 담기 위한 이미 정해진 클레임들이 담겨있습니다.

  • iss : 토큰 발급자
  • sub : 인증에 대한 주체
  • exp : 토큰의 만료 시간
  • iat : 토큰이 발급된 시간

Public(공개)

공개 클레임에는 사용자가 정의하는 클레임들이 담겨 있습니다.

Private(비공개)

등록된 클레임도 아니고, 공개된 클레임도 아닌 클레임들입니다. 이는 서버와 클라이언트간의 협의 하에 사용되는 클레임들을 담아놓습니다.

Signature

서명란에는 해당 JWT가 위변조등을 검증하기 위한 서명이 들어갑니다.
여기서 서명은 Header와 Payload를 각각 인코딩하여 합친 후 설정한 비밀키를 이용하여 해싱한 결과값입니다. 이 해쉬를 Base64형태로 인코딩한 부분이 Signature부분입니다.

JWT의 장점?

JWT에 대한 장단점을 알기 위해서는 먼저 다른방법의 인증/인가 수단과의 비교가 필요합니다.

JWT와 비교할 수 있는 인증/인가 방법은 Session-Cookie 인증/인가 방법이 있습니다.

Session-Cookie기반의 인증방식


(사진출저 : https://hackernoon.com/using-session-cookies-vs-jwt-for-authentication-sd2v3vci)

Session-Cookie기반의 인증방식을 요약하면 아래와 같습니다.

1. 로그인 정보를 입력한 뒤 로그인을 요청한다.
2. 서버에서 해당 정보의 유저가 존재하는지 인증과정을 거친 뒤, 해당 유저에 대한 세션을 서버의 세션 메모리에 저장한다.
3. 해당 세션메모리에 접근할 수 있는 JSESSIONID를 발급한 뒤, 요청한 클라이언트에게 JSESSIONID를 쿠키로 저장하라고 Resonse한다.
4. 해당 유저는 인증이 필요한 기능에 접근 시, 서버에서 JSESSIONID를 확인하여 서버측 세션메모리에서 유저에 대한 인증 정보를 확인하여 서비스를 수행한다. 

JWT기반의 인증방식


(사진출저 : https://hackernoon.com/using-session-cookies-vs-jwt-for-authentication-sd2v3vci)

Token 기반의 인증방식을 요약하면 아래와 같습니다.

1. 로그인 정보를 입력한 뒤 로그인을 요청한다.

2. 서버에서 해당 정보의 유저가 존재하는지 인증과정을 거친 뒤, 해당 유저의 인증정보를 담은 Token을 생성한다.

3. 해당 토큰을 유저에게 전달해준다.

4. 해당 유저는 인증이 필요한 기능에 접근 시, 인증때 받은 Token을 함께 서버로 전달한다.

5. 서버는 해당 토큰의 유효성 검사와 만료일을 검사한 뒤, 문제가 없으면 해당 토큰에 담긴 인증정보를 이용하여 서비스를 수행한다.

그래서 둘의 차이점은 뭔가요???

1. 세션은 서버측 메모리를 사용한다.

    - 서버측 메모리를 사용하기 때문에, 서버의 재부팅, 원치않는 서버의 종료가 발생한다면 세션메모리가 초기화되기 때문에 다시 인증과정을 거쳐야한다.
    - 서버측 메모리를 사용하기 때문에, 스케일 아웃으로 서버를 증설하게 된다면, 각 서버끼리의 세션 불일치를 해결해야 하는 추가적인 리소스가 필요합니다.
    - 서버측 메모리를 사용하기 때문에, 한 서버에 동시 접속자가 많아지면 서버측 heap메모리의 사용량이 급격하게 증가하게 됩니다.

2. JWT는 서버측 메모리를 사용하지 않는다.

- 서버측 메모리에 유저의 인증정보를 저장하는것이 아닌, 토큰으로 만들어 유저에게 위임하기 때문에 서버측 메모리 사용량이 세션에 비해 현저히 적다.
- 서버측에 상태를 저장하지 않고, 토큰을 해석하며 인증정보를 확인하기 때문에 스케일아웃으로 서버를 증설한다 해도, 세션불일치가 일어나는 일이 없다.


실제로 인증을 통해 로그인을 하는 간단한 프로젝트를 생성한 뒤, 인증 방식만 바꾼 뒤 서버 메모리를 체크해봤습니다. 위의 사진과 같이 Session을 이용한 메모리는 1000명이 동시에 로그인을 진행하는 상황에 메모리 사용량이 눈에띄게 늘었지만, JWT를 이용한 서버의 메모리는 메모리 사용량이 늘지 않는것을 볼 수 있었습니다.

즉 JWT는 서버측 메모리를 사용하지 않아 Stateless한 HTTP의 특성을 살릴 수 있고, 인증정보에 대한 메모리 사용량을 아낄 수 있으며, 이로 인해 스케일아웃을 진행 시 추가적인 Resource가 필요하지 않다! 라는 장점이 존재합니다.

그럼 JWT는 무조건 좋은건가요?

아니요. 무조건 좋지 않습니다.
많은 사람들이 착각을 하는것이 "JWT는 암호화가 되어있다! 그러니까 보안적으로 안전하다!" 라는것 입니다.

JWT토큰을 jwt.io와 같은 사이트에서 jwt를 입력하면 아래와 같이 정보가 바로 노출되게 됩니다.

Base64 디코딩 사이트로 JWT를 디코딩하는 장면


jwt.io 사이트를 이용하여 JWT를 디코딩하는 장면

암호화가 되어있다면, 복호화를 하기 위해서 대칭키 혹은 비대칭키를 입력해야 복호화를 할 수 있는데, 해당 사이트는 어떻게 알까요?

위에서 말했듯이 JWT는 암호화가 아닌 "Base64로 인코딩된 토큰" 이기때문에 사이트에 입력을 한다면, 또는 base64디코딩 사이트에 토큰을 입력만 한다면 인증을 위해서 Payload부분에 넣어놓은 정보들이 모두 노출이 됩니다.

또한 Claim에 넣어놓은 정보들이 많아지면 많아질수록 Encoding되는 JWT의 길이가 길어지기 때문에, 토큰을 실어 보내는 네트워크의 트래픽이 가중된다는점 입니다.

문제점을 요약하면 아래와 같습니다.

1. 네트워크 트래픽 가중

  • 토큰에 담는 인증정보가 많아지면 많아질수록 토큰의 길이가 더욱더 길어짐.
  • 인증이 필요한 서비스를 요청할 때 토큰을 함께 보내야 하므로, 인증정보가 많아지면 많아질수록 트래픽이 증가하게 됩니다.

2. 보안 문제

  • 사용자에게 전달되는 토큰은 정보가 “암호화” 되지 않고, Base64로 “인코딩”된 문자열입니다.
  • 따라서 Base64로 디코딩을 하게되면, 토큰에 들어있는 인증정보를 모두 확인할 수 있습니다.

그래서 문제점을 어떻게 해결할건가?

여기서부터는 개인적으로 고민해본 부분이기 때문에, 정답이라 할 수 없고 효율적이다 라고 확신할 수 없습니다.

문제 인식

암호화된 토큰이 아닌 인코딩된 토큰이기 때문에 인증정보가 노출된다는 점이 가장 큰 문제라고 생각합니다.

토큰의 발생지, 토큰을 해석하는 주최는 “서버”기 때문에, 클라이언트는 해당 토큰을 가지고 인증을 위해서 토큰을 건네줄 뿐, 클라이언트측에서 토큰을 해석하여 어떠한 일을 한다는것 자체가 모순이라 생각했습니다.

문제 해결 방법 고안

토큰을 만들어서 클라이언트에게 전달하기 전에 서버측에서 암호화를 진행하여 클라이언트에게 전달해줍니다.

클라이언트는 인증이 필요한 서비스를 이용할 때 암호화된 토큰을 보내게 되면, 서버측에서 이를 복호화, 토큰에 담긴 인증정보를 해석하여 서비스 로직을 수행합니다.

문제 해결 방법에 대한 문제점

  • 암/복호화
    - JWT를 Provide하는 과정에 걸리는 수행시간 + 암/복호화를 진행하는데 걸리는 수행시간이 들기 때문에, 서비스를 서빙하는데 기존의 JWT보다 오래걸립니다.
  • 네트워크 트래픽 가중
    - 기존 jwt토큰도 Claim이 길어지면 길어질수록 토큰의 길이가 길어지는 문제점이 존재합니다. 이를 암호화 하게되면 기존jwt보다 더 길어질 수 있는 문제가 생깁니다.
    • 기존 JWT 길이

      - 암호화한 JWT길이

최적화

사람의 삶은 양자택일입니다. 하나를 선택하면 하나를 포기해야하는것은 어쩔 수 없기때문에 적절하게 Trade Off를 진행해야 합니다.

저는 네트워크 트래픽 가중과 보안의 문제중 보안의 문제를 더 중요하다 생각하기 때문에 과감하게 암/복호화를 진행하게 되었습니다.

하지만 암/복호화를 진행하며 소모되는 수행시간에 대한 문제를 어떻게 최적화 할 지 고민했습니다.

대칭키 알고리즘 vs 비대칭키 알고리즘의 비교

  • 대칭키
    - 개념 : 동일 비밀키 기반 암/복호화 알고리즘
    • 장점 : 비트 단위 암호화로 빠른 속도를 제공
    • 단점 : 비밀키 유출 시 데이터 노출 위험
  • 비대칭키
    - 개념 : 개인키/공개키 쌍 기반 암/복호화 알고리즘
    • 장점 : 키 공유 용이 , 여러 분야에 응용 가능
    • 단점 : 암/복호화 속도가 느림

저는 토큰의 발생지, 토큰을 해석하는 주최는 “서버”라고 생각하기 때문에 클라이언트는 토큰을 해석할 필요가 없다. 라는 생각을 하게되었습니다.
따라서 키 공유를 할 필요가 없으며, 암/복호화의 속도가 비교적 빠른 대칭키 알고리즘을 이용하여 토큰을 암/복호화를 진행했습니다.

AES암호화 알고리즘을 이용한 JWT Provider깃헙

profile
Hi🖐

2개의 댓글

comment-user-thumbnail
2023년 7월 18일

아주 유용한 정보네요!

1개의 답글