[React] 리액트 JWT (JSON Web Token)

2022. 11. 8. 22:33·🍞 FrontEnd/React

✅ JWT란

JWT(JSON Web Token)의 약자로, Json 포맷을 이용해 인증에 필요한 정보를 암호화 한 웹 토큰이다. JWT는 아래 사진 같이 긴 암호화 된 토큰으로, 토큰 자체를 정보로 사용하는 Self-Contained 방식으로 안전성을 보장한다. 주로 회원 인증이나 정보 전달을 위해 쓰이며, Access Token(JWT)을 HTTP 헤더에 넣어 서버와 통신한다.

 

 

JWT.IO

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

jwt.io

 

✅ JWT 구조

JWT 공식 사이트에 들어가면 암호화된 토큰을 볼 수 있다. 위에 사진을 보면 토큰이 세 가지 색깔로 구분이 되어있다. 자세히 보면 빨강, 분홍, 하늘 색깔 사이에 온점이 있는데, 이 온점이 바로 토큰을 구성하는 세 가지 요소를 구분하는 기준이다.

 

토큰을 만들기 위해서는 세 가지 요소 "Header, Payload, Verify Signature"가 필요하다.

header + "." + payload + "." + signature

Header: 토큰 타입, 암호화 알고리즘 지정

Payload: 서버에서 보내는 데이터, 토큰에서 사용할 정보의 조각들인 '클레임'이 담겨있음

Signature: 토큰을 인코딩하거나 유효성 검증을 할 때 사용하는 고유한 암호화 코드

 

따라서 일반적으로 JWT는 아래와 같은 구조를 띈다.

xxxxx.yyyyy.zzzzz


1. Header (헤더)

JWT 토큰의 헤더는 typ와 alg 두 가지 정보로 구성된다. alg는 signature를 암호화 할 알고리즘 방식을 지정하고, typ는 토큰의 타입을 지정한다.

- alg: 암호화 알고리즘 방식을 지정한다. 서명(Signature)을 암호화 하거나, 토큰 검증에 사용된다. (ex. HS256, RSA)
- typ: 토큰의 타입을 지정한다. (ex. JWT)

{
  "alg": "HS256",
  "typ": "JWT"
}

 

2. Payload (페이로드)

Payload에는 토큰에 담을 정보가 들어간다. Payload에 담는 정보의 한 조각을 클레임(claim) 이라고 부르며, 토큰에는 여러개의 클레임을 넣을 수 있다. 클레임은 총 세 가지로 나뉘며 Json(Key/Value) 형태로 다수의 정보를 넣을 수 있다.

 

- 등록된 클레임(Registered Claim)

등록된 클레임들은 이름이 이미 정해져있는 클레임으로 토큰에 대한 정보들을 담기 위해 사용된다. (사용자가 정한 이름이 아님) 등록된 클레임은 선택적으로 사용할 수 있으며, JWT를 간결하게 하기 위해 key는 모두 세 문자열로 이뤄져 있다.

iss: 토큰 발급자 (issuer)
sub: 토큰 제목 (subject). subject로는 unique한 값을 사용하는데, 사용자 이메일을 주로 사용함.
aud: 토큰 대상자 (audience)
exp: 토큰 만료시간 (expiraton), NumericDate 형식. (예: 1480849147370) 현재 시간 이후로 설정되야 함.
nbf: 토큰 활성 날짜 (not before). NumericDate 형식. 해당 날짜가 지나기 전까지는 토큰 비활성화
iat: 토큰 발급 시간 (issued at). 토큰 발급 이후 경과된 시간을 알 수 있음.
jti: JWT 토큰 식별자(JWT ID). 중복 처리를 방지하기 위해 사용. 일회용 토큰(Access Token)등에 사용하면 유용.

 

- 공개 클레임(Public Claim)

공개 클레임은 사용자 정의 클레임으로, 공개용 정보를 위해 사용된다. 충돌 방지 (collision-resistant) 를 위해 클레임 이름을 URI 포맷으로 적는다.

{
  "https://uiop5809.tistory.com/": true
}

 

- 비공개 클레임(Private Claim)

비공개 클레임은 사용자 정의 클레임으로, 클라이언트와 서버간 협의하에 사용되는 클레임 이름들이다. 공개 클레임과는 달리 이름이 중복되어 충돌이 될 수 있으니 사용할때에 유의해야한다.

{
  "username": "pyj"
}

 

payload

{ 
  // 등록된 클레임 
  "sub": "23442s5b-1adf-4sff-sdf939-6sdf0c0b91f7", // 토큰 제목
  "iss": "https://cognito-idp.ap-northeast-2.amazonaws.com/ap-northeast-2_~~", // 토큰 발급자
  "iat": 1925144429, // 토큰이 발급된 시간
  "exp": 1925148029, // 토큰의 만료 시간
  "jti": "89adf5-e434-w20d-3432f-456c4adf73", // JWT의 고유 식별자
  // 공개 클레임 
  "https://uiop5809.tistory.com/": true,
  // 비공개 클레임
  "username": "pyj"
  "event_id": "893a4c1b-3d67-4b8d-a57f-4ed8bcf90c6c", 
  "token_use": "access",
  "scope": "aws.cognito.signin.user.admin",
  "auth_time": 1625144429,
  "client_id": "79307ehbtr2o3ln1ip8dcb9v6p",
}

 

3. Signature (서명)

서명(Signature)은 토큰을 인코딩하거나 유효성 검증을 할 때 사용하는 고유한 암호화 코드이다.
Signature은 헤더(Header)와 페이로드(Payload)의 값을 각각 BASE64로 인코딩하고, 인코딩한 값을 비밀키로 해싱을 하여, 이 값을 다시 BASE64로 인코딩하여 생성한다. 이때 비밀키로 해싱하는 알고리즘은 (Header)에서 정의한 알고리즘을 사용한다. 비대칭 키 방식인 RS256(RSA Sinature with SHA-256)와 대칭키 방식인 HS256(HMAC with SHA-256)를 주로 사용한다. 

 

✅ JWT 토큰 사용

생성된 JWT 토큰은 HTTP 통신을 할 때 헤더에 넣어서 사용한다. 헤더에 넣을 때 Authorization이라는 key의 value로 사용되며, 일반적으로 Bearer라는 문자열이 앞에 붙여진다.

{ 
  "Authorization": "Bearer {JWT token 값}"
}

 

✅ JWT 토큰 사용시 주의사항

최종적으로 JWT 토큰은 Encoded Header + "." + Encoded Payload + "." + Verify Signature 형태를 띄게 된다. 이때, Header, Payload는 인코딩 될 뿐(16진수로 변경), 따로 암호화되지 않는다. JWT 토큰에서 Header, Payload는 누구나 디코딩하여 확인할 수 있기 때문에 비밀번호와 같은 중요한 정보는 넣지 말아야 한다.

다행히도, Verify Signature는 secret_key를 알지 못하면 복호화할 수 없다. 즉, B라는 해커가 A의 정보가 든 payload를 조작해서 인코딩 후 서버에 보내더라도, Verify Signature는 A의 Payload를 기반으로 암호화되었기 때문에 유효하지 않는 토큰으로 간주한다. 즉, secret_key를 알지 못하면 토큰을 조작할 수는 없다.

저작자표시 (새창열림)

'🍞 FrontEnd > React' 카테고리의 다른 글

[React] 간단한 토글 메뉴 구현하기  (0) 2022.11.21
[React] 리액트 프로젝트에 구글 폰트 적용하기  (0) 2022.11.18
[Recoil] Recoil 상태관리 라이브러리  (0) 2022.11.02
[React] Uncaught TypeError index.js  (0) 2022.11.02
[MSW] 데이터 모킹 라이브러리 (Mock Service Worker)  (0) 2022.11.01
'🍞 FrontEnd/React' 카테고리의 다른 글
  • [React] 간단한 토글 메뉴 구현하기
  • [React] 리액트 프로젝트에 구글 폰트 적용하기
  • [Recoil] Recoil 상태관리 라이브러리
  • [React] Uncaught TypeError index.js
박빵이
박빵이
2025년에도 갓생살기
  • 박빵이
    기억보다 기록
    박빵이
  • 전체
    오늘
    어제
    • 분류 전체보기 (337)
      • 🍞 FrontEnd (97)
        • HTML+CSS (4)
        • JavaScript (17)
        • TypeScript (4)
        • React (52)
        • Next.js (2)
        • Android (15)
      • 🍞 BackEnd (24)
        • Java (15)
        • Node.js (6)
        • Spring (1)
      • 🍞 Cloud & Infra (0)
        • AWS SAA (0)
        • Microsoft Azure (0)
      • 🍞 Algorithm (147)
        • C++ (4)
        • Baekjoon (41)
        • Programmers (97)
      • 🍞 Computer Science (18)
        • 운영체제 (1)
        • 데이터 통신 (6)
        • 네트워크 (6)
        • 데이터베이스 (1)
      • 🍞 대외활동 & 부트캠프 (42)
        • 삼성 청년 SW 아카데미 (1)
        • LG유플러스 유레카 (0)
        • 한국대학생IT경영학회 (1)
        • IT연합동아리 UMC (17)
        • 길벗 블로깅 멘토 (18)
        • IT연합동아리 피로그래밍 (3)
        • 개발 컨퍼런스 (2)
  • 블로그 메뉴

    • Admin
  • 링크

    • GitHub
  • 인기 글

  • 태그

    코딩자율학습
    umc
    Java
    react
    C++
    유니온파인드
    Front
    프로그래머스
    안드로이드
    level1
    길벗 블로깅 멘토
    Android
    JavaScript
    level2
    map
    코틀린
    백준
    위상정렬
    알고리즘
    길벗 블로깅 멘토링
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
박빵이
[React] 리액트 JWT (JSON Web Token)
상단으로

티스토리툴바