Jwt vs. Basic Authentication
JWT(JSON Web Token)
개요
JWT는 당사자 간에 정보를 JSON 객체로 안전하게 전송하기 위한 개방형 표준(RFC 7519)이다. 이 정보는 디지털 서명되어 있어 신뢰할 수 있다. JWT는 HMAC 알고리즘이나 RSA/ECDSA를 사용한 공개/개인 키 쌍으로 서명될 수 있다.
구조
JWT는 세 부분으로 구성되며, 각 부분은 점(.)으로 구분된다:
- 헤더(Header): 토큰 유형과 사용된 서명 알고리즘을 지정한다.
- 페이로드(Payload): 클레임(claim)이라고 불리는 엔티티와 추가 데이터를 포함한다.
- 서명(Signature): 헤더와 페이로드를 인코딩한 값과 비밀 키를 사용하여 생성된 서명이다.
결과적으로 JWT는 다음과 같은 형태를 가진다:
|
|
작동 방식
- 사용자가 자격 증명(보통 사용자 이름과 비밀번호)으로 로그인한다.
- 서버는 자격 증명을 검증하고, 비밀 키를 사용하여 JWT를 생성한다.
- 서버는 JWT를 클라이언트에게 반환한다.
- 클라이언트는 JWT를 로컬 스토리지나 쿠키에 저장하고, 이후의 요청에 이 토큰을 Authorization 헤더에 포함시킨다.
- 서버는 토큰의 서명을 검증하고, 요청을 처리한다.
- 토큰이 만료되면 사용자는 다시 로그인하거나 리프레시 토큰을 사용해야 한다.
장점
- 무상태(Stateless): 서버가 사용자 세션 정보를 저장할 필요가 없어 확장성이 좋다.
- 자급자족(Self-contained): 토큰 자체에 필요한 모든 정보를 포함한다.
- 크로스 도메인: 다른 도메인 간에도 쉽게 사용할 수 있다.
- 유연성: 다양한 정보를 페이로드에 포함할 수 있다.
- 확장성: 분산 시스템과 마이크로서비스 아키텍처에 적합하다.
- 모바일 호환성: 모바일 애플리케이션에서도 쉽게 사용 가능하다.
단점
- 토큰 크기: 페이로드에 많은 정보를 포함하면 크기가 커질 수 있다.
- 보안 관리: 토큰이 탈취되면 만료될 때까지 액세스를 차단하기 어렵다.
- 키 관리: 서명 키의 보안 유지가 중요하다.
- 구현 복잡성: 기본 인증보다 구현이 복잡할 수 있다.
- 클라이언트 저장소: 토큰을 클라이언트 측에 안전하게 저장하는 메커니즘이 필요하다.
기본 인증(Basic Authentication)
개요
기본 인증은 HTTP 프로토콜의 일부로, RFC 7617에 정의되어 있다. 이는 HTTP 요청에 사용자 자격 증명을 직접 포함시키는 가장 단순한 인증 방식 중 하나이다.
구조
기본 인증은 “Authorization” HTTP 헤더를 사용하며, 다음과 같은 형식을 가진다:
|
|
여기서 <credentials>
는 “사용자 이름:비밀번호” 문자열을 Base64로 인코딩한 값이다.
작동 방식
- 클라이언트가 보호된 리소스에 접근을 시도한다.
- 서버는 401 Unauthorized 응답과 함께 “WWW-Authenticate: Basic” 헤더를 반환한다.
- 브라우저는 사용자에게 자격 증명을 요청하는 팝업을 표시한다.
- 사용자가 자격 증명을 입력하면, 브라우저는 사용자 이름과 비밀번호를 콜론으로 결합하고 Base64로 인코딩한다.
- 브라우저는 “Authorization: Basic [인코딩된 자격 증명]” 헤더와 함께 요청을 재전송한다.
- 서버는 자격 증명을 확인하고 유효하면 요청된 리소스에 접근을 허용한다.
장점
- 단순성: 구현이 매우 간단하다.
- 표준 호환성: HTTP 프로토콜에 내장되어 있어 대부분의 클라이언트가 지원한다.
- 무상태: 서버 측에서 상태를 유지할 필요가 없다.
- 빠른 설정: 개발 환경이나 간단한 시스템에서 빠르게 설정할 수 있다.
- 직관적: 이해하기 쉽고 디버깅이 간단하다.
단점
- 보안 취약점: 자격 증명이 단순히 Base64로 인코딩되므로, HTTPS 없이는 매우 취약하다.
- 자격 증명 노출: 모든 요청마다 자격 증명이 전송된다.
- 제한된 기능: 추가 정보나 권한을 전달하는 메커니즘이 없다.
- 로그아웃 메커니즘 부재: 표준화된 로그아웃 방법이 없다.
- 사용자 경험: 브라우저의 기본 팝업은 사용자 경험이 좋지 않다.
- 자격 증명 변경: 자격 증명이 변경되면 모든 클라이언트를 업데이트해야 한다.
성능 및 확장성 비교
- JWT
- 네트워크 오버헤드: 토큰 크기가 클 수 있어 네트워크 오버헤드가 발생할 수 있다.
- 처리 속도: 서명 검증에 약간의 CPU 리소스가 필요하다.
- 확장성: 서버 측 상태를 저장하지 않아 수평적 확장이 용이하다.
- 캐싱 효율: 토큰이 클라이언트 측에 저장되므로 서버 캐시 부담이 감소한다.
- 기본 인증
- 네트워크 오버헤드: 상대적으로 작은 헤더 크기로 네트워크 오버헤드가 적다.
- 처리 속도: 단순한 Base64 디코딩만 필요하므로 빠르다.
- 확장성: 무상태 특성으로 확장이 용이하지만, 사용자 DB 조회가 필요하다.
- 캐싱 효율: 매 요청마다 자격 증명을 검증해야 한다.
보안 비교
- JWT
- 전송 중 보안: HTTPS와 함께 사용하면 안전하다.
- 저장 보안: 클라이언트 측 저장소(로컬 스토리지, 쿠키)의 보안에 의존한다.
- 토큰 탈취: 토큰이 탈취되면 만료될 때까지 악용될 수 있다.
- 키 관리: 서명 키의 보안이 중요하다.
- 취약점: XSS(Cross-Site Scripting) 공격에 취약할 수 있다.
- 기본 인증
- 전송 중 보안: 반드시 HTTPS와 함께 사용해야 한다.
- 저장 보안: 사용자 자격 증명이 서버에 안전하게 저장되어야 한다.
- 취약점: 중간자 공격, 네트워크 스니핑에 매우 취약하다.
사용 사례 비교
- JWT에 적합한 사례
- 단일 페이지 애플리케이션(SPA): 프론트엔드와 백엔드가 분리된 아키텍처
- 마이크로서비스: 분산된 서비스 간 인증
- 모바일 애플리케이션: 네이티브 모바일 앱과 서버 간 통신
- API 게이트웨이: API 관리 및 액세스 제어
- 크로스 도메인 인증: 여러 도메인 간의 인증 공유
- 기본 인증에 적합한 사례
- 내부 도구 및 관리 인터페이스: 제한된 사용자가 접근하는 내부 시스템
- 개발 환경: 빠른 설정이 필요한 개발 및 테스트 환경
- API 디버깅: 간단한 API 테스트 및 디버깅
- 단순한 B2B API: 비즈니스 간 통합을 위한 단순한 API
- 레거시 시스템 통합: 기존 기본 인증을 사용하는 시스템과의 호환성
구현 복잡성
- JWT
JWT 구현은 일반적으로 다음과 같은 단계를 포함한다:- JWT 라이브러리 선택 및 통합
- 생성 및 서명 로직 구현
- 검증 및 파싱 로직 구현
- 갱신 메커니즘 설계
- 언트 측 토큰 저장 및 전송 구현
- 기본 인증
기본 인증 구현은 매우 간단하다:- 인코딩/디코딩 로직 구현 (대부분의 라이브러리에 내장)
- 증명 검증 로직 구현
- 언트에 Authorization 헤더 추가
표준 및 호환성
JWT
- RFC 7519에 정의된 표준
- 대부분의 현대적인 웹 프레임워크 및 라이브러리에서 지원
- OAuth 2.0 및 OpenID Connect와 잘 통합됨
기본 인증
- RFC 7617에 정의된 HTTP 표준의 일부
- 거의 모든 HTTP 클라이언트 및 서버에서 지원됨
- 레거시 시스템과의 호환성이 높음
Jwt vs. Basic Authentication
특성 | JWT | 기본 인증 |
---|---|---|
작동 방식 | 서명된 JSON 토큰 | Base64로 인코딩된 자격 증명 |
상태 관리 | 무상태(Stateless) | 무상태(Stateless) |
전송 방법 | Authorization 헤더(Bearer) 또는 쿠키 | Authorization 헤더(Basic) |
데이터 포맷 | 헤더.페이로드.서명 | 사용자 이름:비밀번호 (Base64 인코딩) |
보안 수준 | 중간~높음(서명 알고리즘에 따라) | 낮음(HTTPS 필수) |
암호화 | 서명됨(필요시 암호화 가능) | 단순 인코딩(암호화 아님) |
자격 증명 노출 | 직접 노출 없음(서버 측 검증) | 매 요청마다 자격 증명 전송 |
구현 복잡성 | 중간~높음 | 매우 낮음 |
사용자 경험 | 원활함(배경에서 처리) | 제한적(브라우저 기본 팝업) |
로그아웃 메커니즘 | 클라이언트 측 토큰 삭제 | 미지원(표준 메커니즘 없음) |
토큰 크기 | 중간~큼(페이로드에 따라) | 작음(자격 증명 길이에 따라) |
확장성 | 매우 좋음(완전 무상태) | 좋음(DB 조회 필요) |
처리 오버헤드 | 중간(서명 검증 필요) | 낮음(간단한 디코딩) |
크로스 도메인 | 쉬움 | 가능하지만 제한적 |
만료 관리 | 내장 기능(exp 클레임) | 미지원(표준 메커니즘 없음) |
권한 포함 | 가능(페이로드에 권한 정보 포함) | 불가능(자격 증명만 전달) |
토큰 취소 | 어려움(블랙리스트 필요) | 자격 증명 변경으로 가능 |
리프레시 메커니즘 | 지원(리프레시 토큰 사용) | 미지원 |
적합한 용도 | SPA, 모바일 앱, 마이크로서비스 | 내부 도구, 개발 환경, 간단한 API |
모바일 앱 지원 | 좋음 | 가능하지만 제한적 |
표준 준수 | RFC 7519 | RFC 7617 |
브라우저 지원 | 모든 현대 브라우저 | 거의 모든 브라우저 |
개발자 생태계 | 활발함(많은 라이브러리) | 기본 지원(특별한 라이브러리 불필요) |
디버깅 용이성 | 복잡함(디코딩 도구 필요) | 매우 간단(Base64 디코딩) |
XSS 취약성 | 있음(로컬 스토리지 사용 시) | 낮음(브라우저 관리) |
CSRF 취약성 | 낮음(Authorization 헤더 사용 시) | 낮음(Authorization 헤더) |
현대적인 인증 아키텍처와의 통합
현대 웹 애플리케이션은 종종 다양한 인증 방식을 조합하여 사용한다:
OAuth 2.0 + JWT
- OAuth 2.0은 권한 부여 프레임워크로, JWT는 액세스 토큰 포맷으로 사용
- 소셜 로그인, 타사 API 통합 등에 적합
- 복잡한 권한 관리가 필요한 시스템에 유용
JWT + 세션 하이브리드
- JWT를 서버 측 세션 ID로 사용
- 토큰 무효화 등의 세션 관리와 JWT의 풍부한 페이로드 장점 결합
- 중간 규모 애플리케이션에 좋은 균형 제공
다층 인증 전략
- 민감한 API는 추가 인증 레이어 적용
- 공개 API에는, 기본 인증이나 API 키 사용
- 사용자 인증에는 JWT 사용
용어 정리
용어 | 설명 |
---|---|