본문 바로가기

Spring Boot

헤더/토큰 기반 인증 : JWT(JSON Web Token)

JWT 공식 사이트 : https://www.jwt.io/

 

JSON Web Token

 - 기본 개념

 - 구조(헤더, 페이로드, 시그니처)

 - JWT가 생성되고 검증되는 과정

 - 안전하게 관리하는 방법, 보안 고려사항

 - 실무 환경

 

JWT(JSON Web Token)

데이터를 안전하고 간결하게 전송하기 위해 고안된 인터넷 표준 인증 방식

토큰 기반 인증(Authentication)에서 가장 범용적으로 사용됨

 - JSON 포맷으로 사용자의 정보를 담음

 - 담긴 정보를 Base64URL로 인코딩함

 - Secret Key와 알고리즘을 이용해서 서명(Signature)을 추가하여 위변조를 방지함

 

1. JWT와 일상속 토큰의 비유

 - 놀이공원 입장권 : 돈을 내고 토큰을 보여주면 놀이기구를 탈 수 있음

 - 오락실 게임 동전 : 동전을 넣으면 게임을 할 수 있음

 - 교통 토큰 : 지하철 등을 통과할 수 있는 권한을 줌

애플리케이션 보안에서 JWT는 출입 카드와 비슷한 개념으로, 특정 권한을 가진 사용자가 시스템을 이용할 수 있게 해줌

 

 

JWT의 구조

JWT는 세 부분으로 나뉘며, 각각 점으로 구분된다.

 - Header(헤더) : 어떤 알고리즘으로 서명했는지, 어떤 타입의 토큰인지 정의함

 - Payload(페이로드) : 사용자의 정보와 클레임(Claim) 데이터가 담겨있음

 - Signature(서명) : 헤더와 페이로드가 변조되지 않았음을 검증함

 

1. Header(헤더)

예시

{
  "alg": "HS256" // 사용할 서명 알고리즘
  "typ": "JWT" // 토큰 타입
}

 - 이 JSON 객체를 Base64URL로 인코딩하면 JWT의 첫번째 부분이 됨

 

2. Payload(페이로드)

{
  "sub": "user123", // 고유 정보 1
  "name": "Alice", // 고유 정보 2
  "iat": 1516239022 // 토큰 발급 시간
}

 

 - 민감한 정보는 직접 담아서는 안된다

 - Base64URL로 인코딩하면 두번째 부분이 됨

 

3. Signature(서명)

HMACSHA256(
  base64UrlEncode(header) + "." + base64UrlEncode(payload),
  secret
)

 

 - 서버의 비밀 키로 생성됨(Secret key)

 - 클라이언트가 보낸 토큰이 변조되지 않았음을 검증함

 

 

JWT의 동작 흐름

JWT의 동작 흐름

클라이언트가 서버에게 로그인 요청

- > 서버에서 사용자 인증을 확인하고 클라이언트에게 Access Token(JWT) 발급

- > 클라이언트가  리소스에다가 Authorization 헤더(인증) JWT 포함 요청

- > 리소스가 서버에 JWT 검증 요청

- > 서버에서 리소스에 JWT 유효성 확인 결과를 반환해줌

- > 리소스가 클라이언트에 요청한 데이터를 응답함

* 리소스 서버에 사용자의 ID, PW는 들어가지 않게 됨

 

Access Token과 Refresh Token

JWT는 보통 두가지 종류의 토큰과 함께 사용된다

  Access Token Refresh Token
목적 API 요청시 인증, 인가 Access Token 재발급
유효기간 짧음(분, 시간 단위) 매우 김(일, 주 단위)
보관위치 보통 메모리, 스토리지 안전하게 보관해야함

 

엑세스 토큰만 있으면 권한 요청이 가능하지만, 탈취될 경우 큰 피해가 발생할 수 있으니 짧게 설정한다.

그리고 Refresh Token을 발급해주고 안전하게 보관한다

 

 

JWT 사용 예시

가상의 애플리케이션 A가 Gmail과 연동되어 이메일을 읽어와야 하는 경우,

 1. 사용자가 Gmail 인증서버에 로그인(ID,PW 제출)

 2. 인증에 성공하면 서버는 JWT 발급

 3. 앱 A는 JWT를 Authorization 헤더에 넣어서 리소스에 Gmail API를 요청함

 4. Gmail 서버(리소스)는 JWT의 서명을 검증하고 이메일 데이터를 반환해줌

- > 사용자는 Gmail 비밀번호를 애플리케이션 A에 직접 제공하지 않아도 안전하게 데이터를 연동할 수 있음

 

* JWT는 편리하지만 잘못 사용하면 보안에 취약할 수 있다

1) 민감한 정보 포함 금지

 - JWT는 Base64URL로 인코딩되어 있을 뿐, 암호화는 되어있지 않음

 - 따라서 토큰 안에 비밀번호, 주민등록번호같은 민감한 정보를 절대 넣지 말아야함 - > 범죄임

 

2) 토큰 만료 시간 설정

 - 토큰은 만료 시간(exp)을 반드시 설정해야함

 - 만료시간이 없는 토큰은 탈취될 경우 영구적으로 악용될 수 있음

 

3) HTTPS 사용

 - JWT는 네트워크를 통해 전달되므로 반드시 HTTPS를 통해 암호화된 채널에서 전송해야만 한다

 

4) 저장 위치

 - 로컬 스토리지 대신 HTTPOnly 쿠키 또는 보안이 강화된 세션 스토리지 사용을 권장함

 - 로컬 스토리지는 XSS 공격에 취약하다

 

5) 토큰 무효화 전략

 - JWT는 기본적으로 발급 후 만료 전까지 무효화할 수 없음

 - 이를 보완하기 위해 서버측에서 블랙리스트를 관리하거나 Redis같은 인메모리 DB를 사용할 수 있음

 

 

정리

  설명
JWT JSON 데이터를 인코딩 + 서명하여 인증에 사용하는 토큰
구조 Header, Payload, Signature 세 부분으로 구성
장점 서버 확장성, 세션 불일치 문제 없음
단점 토큰 무효화가 어려움, 탈취 시 보안 위협
사용 예시 OAuth API 인증, 마이크로서비스간 통신