Front-end/etc

JWT를 이용해서 인증하기

개발중인제이 2024. 1. 12. 23:56

 

 

1. JWT(JSON Web Token)란?

  • 서명 검증을 통해 토큰의 위변조 유무를 확인할 수 있도록 사용하는 JSON 기반의 토큰
  • 서명이 검증되어 payload가 위변조되지 않았다는 것이 확인되면 payload 정보를 신뢰하여 사용한다.

 

💡 토큰이 발급되면 누군가가 함부러 변경하지 못하게 서명을 사용한다. 

 

2. JWT의 구조

https://jwt.io/

 

 

  • JWT는 . 을 기준으로 header(헤더)  / payload(내용)  / signature(서명) 으로 이루어져 있다.
  • 누군가가 payload을 변경하려고 하면 서명도 같이 변경해 줘야한다.

 

💡JWT 어떻게 구성되는지는 알았는데 실제 작동은 어떻게 할까?

HMAC(Hash based Message Authentication Code)

  • 송신자와 수신자는 공통 비밀키(secret key)를 하나 씩 가지고 있다.
  • hash 값을 구해서 공통 비밀키를 암호화 하는데 이것을 서명 생성이라고 한다.
  • 이때 서명은 데이터와 비밀키 둘 중 하나만 바껴도 바뀐다.
  • 송신자가 데이터를 수신자(네트워크)로 보낼 때 데이터+서명을 같이보낸다.
  • 수신자(네트워크)는 받은 데이터와 서명을 분리함 → 사전서명
  • 분리한 데이터를 자신이 가지고 있던 공통 비밀키와 결합해 다시 새로운 서명을 만들어 냄 → 사후서명
  • 사전 서명과 사후 서명을 비교한다.
  • 이런식으로 네트워크는 데이터가 위변조되지 않았다는 걸 확인함 → 무결성 검사

 

3. JWT 의 검사 방식

JWT는 두가지의 검증 방식으로 payload의 위변조를 감시해서 잘못된 접근을 방지한다. 

 

3.1 HS 방식

  • HMAC-SHA
  • secret을 이용해 서명생성, 검증 (비밀키 방식)
  • 백엔드에서 가지고 있는 secret키가 있다.
  • 예를들어 사용자가 로그인하고 서버에서 인증해서 사용자 확인까지 하면 JWT를 생성한다.
  • 생성된 JWT을 응답하고 이렇게 받은 토큰을 브라우저는 저장소에 저장한다.
  • 이때 브라우저 내부 저장소는 indexedDB / localStorage / HttpOnly Cookie 등이 있다. 
  • 이렇게 발급받은 토큰은 서버에 있는 리소스에 접근할 때 사용 된다.
  • 서버는 토큰을 검증 후 접근을 허용한다. (위변조되지 않았는지)

💡 그럼 해커가 토큰을 똑같이 위조할수도 있는거 아닌가?

백엔드에서 가지고 있는 secret키를 모르기 때문에 그렇게 하기가 어려움 

 

3.2 RS 방식

  • RSA-SHA
  • 서명생성은 Private Key, 서명 검증은 Public Key를 이용함 (public key + private key = key pair)
  • 서명 생성과 서명 검증이 나누어질 뿐 응답하고 받은 토큰으로 접근하는건 HS와 같다.

 

4. 클라이언트에서 구현해야 할 기능

  • 백엔드와 통신을 위해 로그인 후 받아온 JWT 토큰을 브라우저 내부 저장소에 저장한다.
  • 대표적인 세가지 저장소
    • IndexedDB
    • LocalStorage
    • HttpOnly Cookie
  • 인증된 사용자만을 위한 리소스 API에 접근할 때 Authorization 요청 헤더를 이용해 Bearer 토큰으로 전달한다.

 

💡이때, 프론트엔드에서 해야할 것은?

  • 저장된 JWT에 접근하는 코드를 만들어야 한다.
  • 앱 내부에서 접근 제어를 해야 한다.
  • 즉, 로그인하지 않고 리소스에 접근하면 로그인 화면으로 이동시켜야 한다.(react-router를 이용)

 

5. WebStorage

localStorage sessionStorage IndexedDB
key-value 형식의 텍스트 key-value 형식의 텍스트 객체 타입을 저장
브라우저 종료 후 재시작해도 정보 ⭕ 브라우저가 종료되면 사라짐 비동기 방식
다른 창, 탭을 통해서도 접근 ⭕ 다른 탭, 창에서 접근 ❌  
동기방식 동기방식  

 

6. 세가지 저장방식의 단점

WebStorage Httponly Cookie Google Firebase
자바스크립트 코드로 접근하기 때문에 XSS 공격의 위험이 존재 자바스크립트 코드로 쿠키를 열람할 수 없기 때문에 XSS 공격에 대해 상대적으로 안전 IndexedDB 사용
자동 네트워크 전송을 지원하지 않기 때문에 클라이언트 애플리케이션이 직접 전송 HTTPS를 반드시 사용해야 하고 domain, sameSite와 같은 설정이 번거롭고 테스트가 힘듬 XSS 공격에 대한 방어를 철저히 하는 것이 가장 중요함
  XSS 취약점을 노려서 외부 API를 호출하는 방법으로 XSS 공격이 가능  

 

 

💡그럼 대체 토큰은 어떤 저장소에 저장해야할까?

  • refresh_token은 HttpOnly Secure Cookie 혹은 localStorage, IndexedDB
  • access_token은 유효시간을 짧게 하여 localStorage, IndexedDB, 브라우저 메모리 중 한 곳에 저장

 

이때, XSS 공격을 방어할 수 있는 처리가 필수인데 리액트는 리액트는 상대적으로 XSS로 부터 안전하다. 따라서 localStorage를 사용해도 무방하다. 

 

7. protected route란?

  • react-router를 이용해 권한이 있어야만 접근할 수 있는 Route
  • ProtectedRoute의 구성을 잘 이해하고 있는것이 중요하다.

 

📌

원형섭 강사님 실시간 강의