ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • JWT (Json Web Token)
    개발에 필요한 기초 지식 2022. 3. 21. 16:40

    프로젝트를 진행하면서 JWT를 사용했음에도 불구하고 정확히 어떤 것인지 모른 채 사용해서

    이 기회에 정리하고자 합니다.

     

    JWT에 대해 높은 수준으로 이해하고자 한다면 세션과 쿠키에 대한 정리가 우선되어야 한다고 봅니다.

    그래서 이 글 다음에 세션과 쿠키 그리고 OAuth 2.0 에 대해서 정리하겠습니다.

     

    # JWT보다 먼저 사용되고 있던 방식은 무엇이며 어떤 문제가 있었을까?

    서버 기반의 인증 방식 <출처 : https://tansfil.tistory.com/58>

     

    먼저 사용되고 있던 방식은 서버 기반의 인증 방식이다.

     

    사용자 인증을 서버의 세션을 사용하여 서버 측(서버의 램이나 디스크, 데이터베이스)에서 사용자 정보를 관리하는 것을 말한다.

     

    그런데 이 방식은 다음과 같은 문제들을 가지고 있었다.

     

    확장성 제약

    서버에서 클라이언트의 요청을 계속 저장해둬야 하기에 STATEFUL 하다는 의미가 된다.

    예를 들어 1번 서버에서 A라는 사용자의 인증을 진행 중이었는데 많은 요청으로 인해 로드 밸런싱을 통해 2번 서버로 바뀌게 된다면 2번 서버에는 A 사용자의 인증 정보가 없기에 처음부터 다시 인증을 해야 하는 문제가 발생한다.

     

    서버 부하

    그렇기에 요청이 많아질수록 서버가 저장해야 할 사용자 정보도 많아지기에 서버 부하가 발생할 수 있다.

     

    CORS (Cross Origin Resource Sharing)

    세션을 사용할 때 쿠키를 사용하게 되는데 쿠키는 단일 도메인 및 서브 도메인에서만 동작을 하게 됩니다. 그렇기 때문에 여러 도메인에서 세션을 사용하게 될 경우 관리하는 것이 어렵습니다.

     

    이런 단점들을 해결하기 위해 토큰 기반의 인증 방식이 등장했다.

     

    인증에 성공한 사용자에게 토큰을 발급하면 클라이언트가 이를 가지고 있는다.

    인증이 필요한 경우 클라이언트가 HTTP 헤더에 토큰을 담아 전달하면 서버가 이를 확인하는 방식이다.

     

    서버가 사용자 정보를 일일이 저장하지 않아도 되기에 STATELESS 하고 확장성을 가질 수 있다.

     

     

    # JWT란

    Json Web Token

    Json 객체(포맷)를 활용하여 사용자에 대한 정보를 저장하는 Claim* 기반의 웹 토큰이다.

    OAuth를 적용하기 위한 하나의 도구

    * Claim : Key 와 Value 형식으로 이루어진 한 쌍의 정보

     

    이 부분은 제가 몰랐던 부분인데 망나니개발자 님께서 잘 써주셔서 인용함을 말씀드립니다.

    애플리케이션이 실행될 때, JWT를 static 변수와 로컬 스토리지에 저장하게 된다.
    static 변수에 저장되는 이유는 HTTP 통신을 할 때마다 JWT를 HTTP 헤더에 담아서 보내야 하는데,
    이를 로컬 스토리지에서 계속 불러오면 오버헤드가 발생하기 때문이다.
    클라이언트에서 JWT를 포함해 요청을 보내면 서버는 허가된 JWT인지를 검사한다.
    또한 로그아웃을 할 경우 로컬 스토리지에 저장된 JWT 데이터를 제거한다.
    실제 서비스의 경우에는 로그아웃 시, 사용했던 토큰을 blacklist라는 DB 테이블에 넣어 해당 토큰의 접근을 막는 작업을 해주어야 한다.

    출처: https://mangkyu.tistory.com/56

     

     

    # JWT 특징

    Self-contained

    토큰 자체에 사용자의 권한이나 정보가 포함되어 있다.

     

    Stateless  =>  Scalability

    서버에서 사용자의 정보를 저장하지 않고 요청 시마다 클라이언트에서 HTTP 헤더에 토큰을 담아서 전달하므로 Stateless 하고 이 점 덕분에 Scalability (확장성)를 가지고 있다.

     

    # JWT 동작 원리

    JWT 동작 원리 <출처 : https://tansfil.tistory.com/58>

    토큰이 없는 경우

    1. 사용자가 로그인한다.

    2. 사용자 정보를 DB에 저장하고 토큰 발급하여 사용자에게 헤더에 담아서 응답

    3. 클라이언트는 로컬 스토리지 또는 쿠키에 저장

    4. 토큰을 헤더에 담아 데이터 요청하면 서버에서 토큰 유효성 검사 후 이상 없으면 요청한 데이터를 응답

     

    토큰이 있는 경우

    1. 사용자가 로그인한다.

    2. 토큰 유효성 검사 후 해당 유저의 정보를 DB에서 조회

    3. 서버는 발급한 토큰을 다시 헤더에 담아서 사용자(클라이언트)에게 전달

    4. 클라이언트는 로컬 스토리지 또는 쿠키에 저장

    5. 토큰을 헤더에 담아 데이터 요청하면 서버에서 토큰 유효성 검사 후 이상 없으면 요청한 데이터를 응답

     

     

    # 로컬 스토리지 저장과 쿠키 저장의 차이점

    로컬 스토리지 저장

    • CSRF 공격에는 안전할 수 있다.
    • XSS 공격에 취약하다.

    쿠키 저장

    • 로컬 스토리지에 비해 XSS 공격에 안전하다.
    • CSRF 공격에 취약하다.

     

    이런 보안 관련된 부분에 대해서는 나중에 좀 더 자세히 알아보고 글을 쓰고자 합니다.

     

    # Access Token 과 Refresh Token 이란?

    Access Token

    기본적으로 우리가 위에서 얘기했던 토큰은 Access Token을 의미한다.

    사용자 인증이 필요한 작업에 이 토큰을 통해 인증하는 것이다.

     

    유효 기간을 길게 하면 사용자 입장에서 자주 로그인을 안 해도 돼서 편할 수는 있겠지만

    해킹에 취약할 수밖에 없다.

    그렇다고 너무 짧게 하면 자주 로그인을 해야 해서 사용에 불편함을 초래한다.

    그래서 유효기간을 1시간, 2시간처럼 상대적으로 짧게 잡아둔다.

     

    이런 문제점을 보완하고자 나온 것이 Refresh Token이다.

     

    Refresh Token

    Access Token의 보안적인 측면을 보완하고자 나온 것이 Refresh Token이다. (Access Token과 같은 형태)

    Access Token이 만료되어도 Refresh Token이 있다면 이를 통해 Access Token을 다시 발급받을 수 있다.

     

    Refresh Token을 활용하여 해킹에 완벽한 토큰이 되는 것은 절대 아니다.

    그런 방법은 없다고 봐야 한다.

    Refresh Token도 탈취당하면 문제가 될 수 있기에 보통 유효기간을 2주 ~ 1달 정도로 한다고 한다.

     

    # Access Token 과 Refresh Token 에 대한 간략한 설명

    토큰 발급 과정 <출처 : webaura.tistory.com>

    최초 인증 시 사용자 인증 후 사용자 정보를 payload에 담아 토큰을 발급한다.

    이후 사용자 인증이 필요한 작업의 경우 클라이언트가 HTTP 헤더에 토큰을 담아 서버에 전달한다.

     

    자동 로그인 과정 <출처 : webaura.tistory.com>

    클라이언트가 헤더에 토큰을 담아 전달하면 아래와 같은 과정을 거친다.

    • 토큰 전달 --> 인증 성공 --> 로그인 완료
    • 토큰 전달 --> Access Token 만료 --> Resfresh Token 요청 --> 성공 --> Access Token 발급 --> 로그인 완료
    • 토큰 전달 --> Access Token 만료 --> Resfresh Token 요청 --> 실패 --> 재로그인

     

     

    # JWT의 구성요소 3가지

     

    Json 형태인 각 부분은 Base64로 인코딩 되어 있다.

    형태 - aaa.bbb.ccc

     

    Header

    • alg : Signature를 해싱할 알고리즘
    • typ : 토큰 타입
    {
      "alg": "HS256",
      "typ": "JWT"
    }

     

    Payload

    • 실제 사용할 데이터의 조각들인 Claim이 담겨 있다.
    {
      "id": 123456,
      "nickname": "bruno",
      "iat": 123412345,
      "exp": 123456789
    }

     

    Signature

    • 헤더 + 페이로드 + secret key 를 합친 것을 헤더에서 정의한 알고리즘으로 암호화
    HMACSHA256(
      base64UrlEncode(header) + "." +
      base64UrlEncode(payload),
      secret key
     )

     

    # Payload 3가지 종류

    Registered claim

    • iss (issuer) - 발행자
    • iat (issued at) - 발행 시간
    • exp (expiration time) - 만료 시간
    • jti (JWI ID)
    • sub (subject) - 제목

    Public claims

    사용자가 정의할 수 있는 클레임으로 공개용 정보 전달이 목적

    • url

    Private claims

    당사자들 간에 정보 공유하기 위해 만든 클레임

     

     

    # JWT의 페이로드에 들어가서는 안 될 내용은? 그 이유는?

    https://jwt.io/ 에서 JWT를 입력하면 누구나 복호화할 수 있다.

    그래서 유저의 비밀번호, 주민번호와 같은 민감한 정보는 payload 에 담지 않아야 한다. 

     

     

    # JWT의 한계점

    Q. 만료기간이 아직 남은 Refresh Token이 있고 Access Token은 만료되었다고 가정할 때

         토큰을 탈취당하면 그냥 유효기간이 남은 Access Token이 탈취당한 것과 같은 것 아닌가?

     

    토큰 탈취에 대한 보안 우려

    완벽하진 않지만 Access Token은 로그가 그대로 노출되는 경우가 많기에 Access Token의 유효기간을 짧게 하고 상대적으로 잘 노출되지 않는 Refresh Token의 유효기간을 보다 길게 설정

     

    상대적으로 탈취에는 강해지지만 서버와 통신을 더 많이 해야 하기에 서버에 부하, 자원 낭비가 될 수도 있고 구현이 복잡해진다는 단점이 있다.

     

    payload에 과도한 데이터  =>  네트워크 부하

    payload에 많은 데이터를 담을 경우 토큰의 사이즈가 커져 네트워크에 부하를 줄 수 있다.

    그러나 실제 서비스 배포 시에 어느 정도 영향을 줄지에 대해서는 아직 감이 오지 않는다.

     

     

     

    # JWT의 유효기간을 어떻게 설정했으며 그 이유는?

    <추후 작성 예정>

     

    # JWT를 활용하여 이상적인 Scalable한 인증서버를 만들려고 하고자 할 때 어떻게 구성을 할 것인가?

    <추후 작성 예정>

     

    # JWT 변조 공격에 어떻게 대처하겠는가?

    <추후 작성 예정>

     

     

    Q. Token 과 JWT 차이점은?

     

     

     

    세션 기반 방식부터 JWT까지 전체적으로 읽기 쉽게 잘 설명해 주셔서 공유합니다.

    https://inpa.tistory.com/entry/WEB-%F0%9F%93%9A-JWTjson-web-token-%EB%9E%80-%F0%9F%92%AF-%EC%A0%95%EB%A6%AC

     

    [WEB] 📚 JWT(Json Web Token )란? 💯 정리

    Cookie & Session [WEB] 🌐 세션/ 쿠키 🍪 정리 비연결성(Connectionless)과 비상태성(Stateless) HTTP 프로토콜에는 비연결성(Connectionless)과 비상태성(Stateless)이라는 특징이 있습니다. 이는 서버의 자원..

    inpa.tistory.com

     

    현업에서 실제로 어떤 식으로 사용하는지에 대해 적어주셔서 도움이 많이 되어서 공유합니다. 

    https://mangkyu.tistory.com/56

     

    [Server] JWT(Json Web Token)란?

    현대 웹서비스에서는 토큰을 사용하여 사용자들의 인증 작업을 처리하는 것이 가장 좋은 방법이다. 이번에는 토큰 기반의 인증 시스템에서 주로 사용하는 JWT(Json Web Token)에 대해 알아보도록 하

    mangkyu.tistory.com

     

    이 글을 통해 JWT의 단점에 대해 알 수 있습니다.

    https://yceffort.kr/2021/05/drawback-of-jwt

     

    Home

    yceffort

    yceffort.kr

     

    JWT 보안 측면에 대해 중점적으로 쓰셔서 보시길 추천드립니다.

    https://velog.io/@0307kwon/JWT%EB%8A%94-%EC%96%B4%EB%94%94%EC%97%90-%EC%A0%80%EC%9E%A5%ED%95%B4%EC%95%BC%ED%95%A0%EA%B9%8C-localStorage-vs-cookie

     

    JWT는 어디에 저장해야할까? - localStorage vs cookie

    이번에 지하철 미션을 만들면서 JWT를 클래스 property에 저장했었는데 리뷰어 분께 해당 부분을 피드백 받으면서 어디에 JWT를 저장하는 것이 좋을까 에 대해 고민해보게 되었다. 0. 기본 지식 JWT Js

    velog.io

     

    제목처럼 JWT의 한계점에 대해 쉽게 설명해주셔서 이해하시기 좋을겁니다.

    https://www.youtube.com/watch?v=THFmV5LPE6Y&t=71s 

     

    댓글

Designed by Tistory.