ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 🤔 JWT
    공부방 2022. 10. 14. 20:40

    ⌨️ 로그인 방식


    로그인을 처리하는 방법으로 생각할 수 있는 방법

    1. 유저에게 ID / Password를 받아 서버의 DB에 있는 데이터와 비교하는 방법
    2. 세션 방식 사용
    3. Token 방식 사용

    ID / Password 사용 방법 👎

    • 로그인 유지가 되지 않는다.
      • 페이지를 이동할 때마다 로그인을 다시 해야한다.

    ⇒ 로그인을 유지하면서 안전한 방법이 필요하다.

    세션 방식 👊 - 서버 유지

    세션 방식은 서버의 메모리, DB와 같은 서버의 자원들을 사용해 사용자의 정보를 유지시키는 방식이다.

    • 토큰 방식보다 보안에 강하다

    세션을 사용하는 경우 매 Request마다 서버는 쿠키를 받아, 세션 ID를 보고 해당 ID와 일치하는 유저를 찾아야한다.

    • 요청이 있을 때마다 세션 DB를 조회해야 한다.

    ⇒ 유저가 증가할 수록 DB 리소스가 더 필요하다.

     

    단점

    1. 서버의 확장성이 떨어진다.
    2. 서버의 자원이 많이 필요하다
    3. 트래픽을 분산하기 위해 여러 대의 서버를 사용할 때, 사용자는 처음 로그인한 서버에만 요청을 보내야한다.
    4. (만들어진 세션을 참조해야 하기 때문에)

    Token 방식 👍 - 클라이언트 유지

    토큰 방식은 사용자가 로그인을 하면 서버에서 발행한 토큰을 통해 브라우저의 저장소에 토큰을 유지시키는 방법

    토큰 = JWT

    • 세션 DB가 필요가 없다.
    • 유저 인증을 하기 위해 서버가 많은 일을 하지 않아도 된다.

    유저 인증을 하는데 필요한 정보를 토큰에 저장한다.

    • 이 토큰을 클라이언트(브라우저)에 전달한다.
    • 페이지 요청시 서버는 해당 토큰이 유효한지만 검증하면 된다.

    🚨 JWT는 암호화 되지 않았다

    → 누구나 열어서 해당 컨텐츠를 볼 수 있다.

    따라서, 비밀정보를 JWT안에 뒤서는 안된다.

     

    서버에 저장을 하지 않아 서버에 확장성이 있다.

    - 로그인시 해당 토큰이 유효한지만 체크하면 어떤 서버로 요청을 보내도 상관이 없다.

    🔥 JWT


    💡 JWT (JSON Web Token)
    두 개체에서 JSON 객체를 사용하여 가볍고 자가수용적인(self-contained)방식으로 정보를 안전성있게 전달

    당사자 간의 정보를 안전하게 전송하기 위한 컴팩트하고 독립적인 방법을 정의하는 개방형 표준(RFC 7519)

    JWT는 JSON 데이터를 Base64 URL-safe Encode를 통해 인코딩하여 직렬화 한 것이고 토큰 내부에는 위변조 방지를 위해 개인키를 통한 전자서명도 들어있다.

    Base64 URL-safe Encode

    • 일반적인 Base64 Encode에서 URL에서 오류 없이 사용하기 위해
    • ‘+’, ‘/’ 를 각각 ‘-’, ‘_’로 표현한 것.

    JWT가 유용한 시나리오

    • 회원 인증
    • 두 개체 사이에 정보 전달을 할 때 사용

    특징

    1. 자가수용적이다 (Self-contained)
      • JWT는 필요한 모든 정보를 자체적으로 가지고 있다.
      • JWT 시스템에서 발급된 토큰은 토큰에 대한 기본정보, 전달 할 정보, 토큰이 검증되었다는 것을 증명해주는 signature를 포함하고 있다.
    2. 쉽게 전달 가능하다.
      • 자가수용적이기 때문에 두 개체에서 손쉽게 전달 가능
      • HTTP 헤더에 넣어서 전달, URL 파라미터로 전달 가능 등
    3. HMAC 알고리즘으로 비밀 또는 RSA 또는 ECDSA를 사용하는 공용키/비밀키 쌍을 사용하여 서명할 수 있다.

    ⚒ Structure


    JWT는 . 을 기준으로 세 파트로 나뉜다.

    1. Header

    {
      "alg": "서명 시 사용하는 알고리즘",
      "typ": "타입"
    }

    JWT에서 사용할 타입과 해시 알고리즘의 종류가 담겨져 있다.

    2. Payload

    {
      "sub": "hyeonsu.jung",
      "exp": 1623235123,
      "name": "beom seok"
    }

    토큰에서 사용할 정보의 조각들인 Claim 이 담겨 있다. (JWT를 통해 실제 알 수 있는 데이터)

    • payload에는 여러 claim을 담을 수 있다.
    • 서버와 클라이언트가 주고받는 시스템에서 실제로 사용될 정보에 대한 내용을 담고 있다.

    Claim

    key - value 형식으로 이루어진 한 쌍의 정보

    Claim 종류

    • registered(등록된) claim
    • public(공개) claim
    • private(비공개) claim

    registered claim

    • 토큰에 대한 정보를 담기위한 미리 정의된 클레임의 집합

    public claim

    • 사용자 정의 클레임, 공개용 정보 전달을 위해 사용한다.

    private claim

    • 비공개 클레임은 당사자간에 정보를 공유하기 위해서 만들어진 사용자지정 클레임이다.
    • 이름이 중복되어 충돌이 일어날 수 있어 유의해야 한다.

    3. Signature

    • 시그니처에서 사용하는 알고리즘은 헤더에서 정의한 알고리즘 방식(alg)을 활용한다.
    signature = Base64Url(Header) + . + Base64Url(Payload) + . + server's key

    Header, Payload를 Base64 URL-safe Encode를 한 이후 Header에 명시된 해시함수를 적용해, 개인키(Private Key)로 서명한 전자서명이 담겨 있다.

    Header / Payload는 단순히 인코딩된 값이라 제 3자가 복호화 및 조작할 수 있다.

    • 하지만, Signature는 서버 측에서 관리하는 비밀키가 유출되지 않는 이상 복호화 할 수 없다. ❌
    • 따라서, Signature는 토큰의 위변조 여부를 확인하는데 사용된다.

    ❗ How


    인증 과정

    1. 사용자가 ID, Password를 입력하여 서버에 로그인 인증 요청
    2. 서버에서 클라이언트로부터 인증 요청을 받으면, [ Header, PayLoad, Signature ] 를 정의한다.
      • Header, PayLoad, Signature를 각각 Base64로 암호화하여 JWT를 생성하고 이를 쿠키에 담아 클라이언트에게 발급한다.
    3. 클라이언트는 서버로부터 받은 JWT를 로컬 스토리지에 저장한다.
      • API는 서버에 요청시 Authorization header에 AccessToken을 담아 보낸다.
    4. 서버는 Header에 담아 보낸 JWT가 서버에서 발행한 토큰인지 일치 여부 확인, 일치 여부 확인 후 인증 통과 시켜준다.
    5. 인증이 되면 페이로드에 있는 유저의 정보를 select해서 클라이언트에 돌려준다.
    6. 클라이언트가 서버에 요청을 했을 때, 엑세스 토큰이 만료되면 클라이언트는 리프레쉬 토큰을 이용해 서버로 부터 새로운 엑세스 토큰을 받는다.

    토큰 인증 신뢰성

    서버는 토큰이 유효한 토큰인지 확인하는 것이 중요하다.

    → 클라이언트로 부터 받은 JWT 헤더, payLoad를 서버의 Key 값을 이용해 시그니처를 다시 만들고 이를 비교해서 일치한 경우만 인증을 통과한다

    JWT 장, 단점


    JWT 장점

    • Header와 PayLoad를 가지고 Signature를 생성하므로 데이터 위변조를 막을 수 있다.
    • 인증 정보에 대한 별도의 저장소가 필요없다.
    • JWT는 토큰에 대한 기본 정보와 전달한 정보 및 토큰이 검증됐음을 증명하는 서명 등 필요한 모든 정보를 자체적으로 가지고 있다.
    • 서버는 무상태가 된다(Stateless)
    • 확장성이 좋다.
    • 토큰 기반으로 다른 로그인 시스템에 접근 및 권한 공유가 가능하다
    • 모바일 어플리케이션 환경에서도 잘 동작한다(세션은 불가능)

    JWT 단점

    • JWT는 토큰의 길이가 길어, 인증 요청이 많아지면 네트워크 부하가 심해진다.
    • PayLoad는 암호화 되지 않아 중요 정보는 담을 수 없다.
    • 토큰을 탈취당하면 대처하기 어렵다.

    🔑 Access Token & Refresh Token


    Refresh Token이 필요한 이유

    Access Token 만 사용하는 인증 방식의 문제는 제 3자에게 탈취당할 경우 보안에 취약하다는 점 이다

    • Access Token은 토큰이 만료되기 전까지, 토큰을 획득한 사람은 누구나 접근이 가능하기 때문

    JWT는 토큰에 유효시간을 부여하는 식으로 탈취 문제에 대응

    • 유효기간을 짧게 하면 그만큼 로그인을 자주해서 새로운 Token을 발급받아야 하는 불편함이 있다.
    • 유효기간을 길게 하면 토큰을 탈취당했을 때 보안에 취약해진다.

    유효기간을 짧게 하는 좋은 방법??? ⇒ Refresh Token

    Refresh Token

    Access Token과 똑같은 JWT이다.

    Access Token은 접근에 관여, Refresh Token은 재발급에 관여하는 토큰

    처음 로그인 시 서버는 클라이언트에게 Access Token과 Refresh Token을 동시에 발급한다.

    • 서버는 DB에 Refresh Token을 저장하고
    • 클라이언트는 Access Token 과 Refresh Token을 쿠키, 세션 혹은 웹 스토리지에 저장한다.
    • 요청이 있을 때 마다 이 둘을 헤더에 담아서 보낸다.

    Refresh Toekn은 긴 유효기간을 가지고, Access Token이 만료됐을 때 새로 재발급을 해주는 열쇠가 된다.

    • Access Token이 만료되었다면, 서버는 같이 보내진 Refresh Token을 DB에 있는 것과 비교해서 일치할 시 다시 Access Token을 재발급하는 원리

    사용자가 로그아웃을 할 경우 저장소에서 Refresh Token을 삭제해 사용이 불가능하도록 한다.

    • 새로 로그인하면 서버에서 다시 재발급하여 DB에 저장

    📦 Redis 로 JWT Refresh Token 관리하기


    Refresh Token은 저장소에 저장을 해두고 사용자가 토큰을 재발급을 요청하면 검사를 해야한다.

    • Refresh Token도 유효기간이 있기 때문

    이때, Refresh Token을 RDBMS에 저장하면 배치를 이용해 주기적으로 삭제를 해줘야 하는 불편함이 생긴다.

    • 이때, redis를 사용하면 생성할 때 유효기간을 정해두고 따로 작업이 필요없이 만료된 토큰은 삭제된다.

    Why Redis ❓

    Redis는 key-value 쌍으로 데이터를 관리할 수 있는 데이터 스토리지이다.

    기본적으로 레디스는 in-memory로 데이터를 관리해, 저장된 데이터가 영속적이지 않다.

    • 데이터를 영구적으로 저장할 수 없는 대신, 굉장히 빠른 엑세스 속도를 보장받을 수 있다.

    빠른 엑세스 속도와 휘발성이라는 특징으로 캐시의 용도로 레디스를 사용한다.

     

    Refresh Token의 저장소로 레디스를 선택한 이유

    1. 빠른 엑세스 속도로 사용자 로그인시 병목이 되지 않는다.
    2. 레디스는 기본적으로 데이터의 유효기간(time to live)을 지정할 수 있다.
      • refresh token을 저장하기에 적합하다.
    3. refresh token은 제거되어도 다른 데이터에 비해 덜 치명적이다
      • 로그아웃 되는 정도

    참고 자료

    https://jwt.io/introduction/

    https://www.youtube.com/watch?v=tosLBcAX1vk&t=5s&ab_channel=노마드코더NomadCoders

    https://velog.io/@junghyeonsu/프론트에서-로그인을-처리하는-방법

    https://velog.io/@ypo09/JWTJSON-Web-Token-란-무엇인가

    https://inpa.tistory.com/entry/WEB-📚-JWTjson-web-token-란-💯-정리

    https://inpa.tistory.com/entry/WEB-📚-Access-Token-Refresh-Token-원리-feat-JWT

    https://hudi.blog/refresh-token-in-spring-boot-with-redis/

    https://wildeveloperetrain.tistory.com/21

     

    '공부방' 카테고리의 다른 글

    에러 로그 발생시 슬랙 알림 보내기  (0) 2022.11.23
    Swagger 설정  (1) 2022.10.27

    댓글

Designed by Tistory.