ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • JWT (Json Web Token)
    보안/웹보안 2021. 3. 10. 20:57

    JWT는 Json 을 이용해 안전하게 정보를 전달할 수 있는 웹 표준이다. 클라이언트가 서버에 인증을 요청할 때 사용된다.

     

    인증을 위해 쿠키를 사용할 수도 있고 세션을 사용할 수도 있다.

    그러나..

     

    쿠키를 사용하면 클라이언트가 브라우저에 정보를 raw 하게 저장하기 때문에 보안에 취약하고

    세션을 사용하면 서버가 여러대인 경우 모두 세션ID 를 가지고 있어야 인증이 가능하기 때문에 부담스럽다.

     

    결론부터 얘기하면 JWT를 사용하면 클라이언트가 정보를 가지고 있으면서 위변조 또한 불가능하기 때문에 서버 입장에서 편리해진다.

    왜 일까? 

     

    JWT의 구조

    JWT의 구조를 보기전에 알아야 할 배경 지식은 JWT는 base64 인코딩과 해싱이 사용된다는 사실이다.

     

    {Header} . {Payload} . {Signature}

    Header, Payload, Signature가 '.'(dot) 을 기준으로 나누어져있다. 

     

     

    Header Playload 는 base64 인코딩 되어있다.

    Header 에는 해싱 알고리즘과 토큰의 종류가 기재된다.

    Payload 에는 주고받을 데이터가 입력된다. (base64 인코딩은 암호화가 아니므로 쉽게 디코딩된다. 중요한 정보를 입력하면 안된다.)

     

    Signature 가 중요하다. SignatureHeader와 Payload 그리고 서버에서만 가지고 있는 Secret Key 가 합쳐져 해싱되어 있다.

    즉 Header와 Payload (데이터)의 값이 바뀌면  다시 해싱했을 때 이 Signature도 바뀐다는 것을 명심하자!  

     

     

    JWT를 통한 인증 과정

    우선 이 과정은 로그인한 유저가 서버의 리소스를 취득할 권한이 있는지 확인하는 과정이다.

     

    기본적인 프로세스는은 다음과 같다.

    1. 유저가 id/pw 를 입력하고 로그인 요청을 한다.
    2. 서버는 유저를 확인하고 JWT를 생성하여 유저에게 넘겨준다.
    3. 유저는 리퀘스트 헤더에 JWT를 포함하여 요청을 서버에게 보낸다.
    4. 서버는 요청을 받으면 JWT를 우선 확인하고 유효하다면 요청을 처리한다. (리소스를 제공한다) 

    여기서 궁금한 점은

    • 왜 유저는 정보를 위/변조할 수 없을까?
    • 서버는 어떻게 토큰이 유효한지 확인할까?

    정답은 Signature에 있다.

    위에서 언급했듯

    Signature는 Header와 Payload 그리고 서버에서만 가지고 있는 Secret Key 가 합쳐져 해싱되어 있고

    Header와 Payload (데이터)의 값이 바뀌면 다시 해싱했을 때 Signature도 바뀐다.

     

    왜 위변조가 안되는지 예를 들어보자 (+ 서버의 토큰확인)

    • 유저 Adam이 로그인 요청을 했다. (유저 이름 : Adam)
    • 서버는 사용자가 로그인 가능함을 확인하고, {헤더}와 사용자정보 {Adam} 그리고 자기만 아는 Secret Key를 넣어서 해싱한다.
      • 이게 바로 Signature 이다. (Signature 는 1234abcd 라고 하자.)
    •  JWT를 생성하여 유저에게 준다.
      • JWT는  {인코딩된 헤더}.{인코딩된 Adam}.{1234abcd}  라고 하자.
    • <유저의 조작시도 시작> 유저는 자신을 Bob 이라고 속이고 싶다. 그래서 Payload 에 있는 Adam을 Bob으로 슬쩍 바꿨다.
      • 현재 유저가 가진 JWT는 {인코딩된 헤더}.{인코딩된 Bob}.{1234abcd}  가 되었다.
      • 클라이언트가 해싱을 하진 않으므로 클라이언트가 가지고 있는 JWT에서 Signature는 그대로이다.
    • 바꾼 JWT를 헤더에 담고, 무언가 서버에 요청한다. (나 Bob인데, 내 비밀번호 바꿔줘 등)
    • 서버 유저의 요청을 받았고, JWT를 확인해야한다.
      • 유저가 보낸 JWT {인코딩된 헤더}.{인코딩된 Bob}.{1234abcd} 중에서 {인코딩된 헤더}.{인코딩된 Bob} 와 서버의 Secret  Key 로 해싱했을 때 Signature인 {1234abcd} 가 나와야 한다.
      • 그러나 해싱했을 때 {1234abcd}가 나오지 않는다.
      • 왜냐하면 {1234abcd}는 Payload 데이터에 {인코딩된 Adam} 이 있을 때 나오는 해시값이기 때문이다.
    • 이렇게 인증 실패.

    유저는 해싱에 필요한 Secret Key도 모르므로 공격에 성공하는 Signature를 예상할 수도 없다.

     

     

     

    댓글

Designed by Tistory.