IDP · OAuth2 · JWT 정리
IDP, OAuth2, JWT는 현대 인증/인가 구조의 핵심 요소다. 로그인 구현이나 MSA 환경에서 자주 사용되지만, 개념이 혼동되거나 잘못 적용되는 경우가 많다.
이 글에서는 인증과 인가의 구분, OAuth2 흐름, JWT의 본질, 그리고 실무 보안 관점으로 정리해 보았다.
1. 인증(Authentication) vs 인가(Authorization)
- 인증: 누군지 확인
- 인가: 무엇을 할 수 있는지 판단
항상 순서:
인증 → 인가
인가만 단독으로 존재할 수 없다.
2. OAuth 주요 Grant
Authorization Code Grant
- 사용자(User)가 로그인
- 브라우저는 로그인 UI만 담당
- authorization code는 임시 표식
- code → token 교환은 반드시 백엔드에서 수행
목적:
- 토큰을 브라우저 JS로부터 분리
- 보안 강화
공개 클라이언트(SPA 등):
반드시 PKCE 적용
Client Credentials Grant
- 사용자 없이 서버 간 인증
client_id+client_secret사용- 백엔드 ↔ 백엔드 통신
3. OAuth 역할 구분
-
Authorization Server: 토큰 발급
예: Keycloak -
Client: 토큰 요청 및 사용
-
Resource Server: 토큰 검증 및 리소스 제공
4. Authorization Code Grant 흐름 / Authorization Code Grant (RFC 6749 §4.1)
- 브라우저 → 로그인 페이지 이동
- 로그인 성공 → authorization code 수신
- 백엔드 → code 전달
- Authorization Server → 토큰 발급
- 백엔드 → 토큰 저장
권장:
- HTTP-only Cookie
- 또는 서버 세션(opaque id)
5. 브라우저의 역할
브라우저는 최대한 단순하게 유지한다.
- JWT 저장하지 말 것
- localStorage 저장하지 말 것
- Authorization 헤더 직접 구성하지 말 것
쿠키 자동 전송만 사용한다.
6. JWT를 브라우저 JS에서 다루면 안 되는 이유
JavaScript 실행 환경은 신뢰할 수 없다.
위험 요소:
- XSS → 토큰 탈취
- localStorage → 항상 노출
- 악성 스크립트 삽입
결론:
JWT 관리는 백엔드 책임
7. 권장 아키텍처 — BFF / Gateway
Browser
↓ (HTTP-only Cookie)
Backend / BFF
↓ (Authorization: Bearer <token>)
Resource Servers
JWT는 백엔드만 처리한다. 브라우저는 세션과 유사한 UX로 동작한다.
8. JWT 구조와 본질
구조:
header.payload.signature
header / payload:
- Base64URL 인코딩
- 암호화 아님
- 누구나 디코딩 가능
따라서:
- 민감 정보 저장 금지
- 개인정보 저장 금지
signature:
- 위조 방지 목적
- 암호화 아님
JWT는 숨기는 값이 아니다.
9. JWT 검증 — 실무 체크리스트
서명 검증만 수행하면 부족하다.
필수 검증:
- signature 유효성
- exp (만료)
- nbf (사용 가능 시점)
- iss (발급자)
- aud (대상)
인가 판단:
- scope
- roles / authorities
Payload 설계 원칙:
- 암호화되지 않음을 전제
- 민감 정보 저장 금지
- 개인정보 저장 금지
- 최소 정보만 포함
매 요청마다 검증 및 인가를 수행한다.
10. JWT 탈취의 본질
JWT는 bearer token이다.
의미:
- 토큰을 가진 사람이 사용자로 인정됨
- 사용자 비밀번호 불필요
따라서:
JWT의 위험은 위조가 아니라 탈취
JWT는 현금과 유사하다. 유효하면 누구나 사용 가능하다.
11. JWT 탈취 대응 전략
대응 전략은 두 가지 관점으로 나눌 수 있다.
- 훔치지 못하게 한다
- 훔쳐도 쓸모없게 한다
12. 훔치지 못하게 하는 방법
HTTPS 사용
- 스니핑 방지
- 중간자 공격 방지
토큰 기반 인증에서는 필수 조건이다.
토큰 저장 위치
위험:
- localStorage
- sessionStorage
이유:
- JavaScript 접근 가능
- XSS 시 탈취 가능
권장:
- HTTP-only Cookie
장점:
- JS 접근 불가
- XSS로 직접 탈취 어려움
SameSite 설정
쿠키 기반 구조에서 필수.
- Strict
- Lax
- None (+ Secure 필수)
로그 보안
- Authorization 헤더 로그 금지
- 토큰 마스킹 처리
- 로그 접근 통제
로그를 통한 토큰 유출 사고 빈번.
13. 훔쳐도 쓸모없게 하는 방법
Access Token 수명 단축
전략:
- Access Token → 짧게
- Refresh Token → 상대적으로 길게
탈취 피해 시간 최소화 목적.
Refresh Token Rotation
동작:
- 갱신 시 새 Refresh Token 발급
- 이전 토큰 무효화
- 이전 토큰 재사용 감지
효과:
- 탈취 탐지 가능
Reuse Detection
이미 사용된 Refresh Token 재사용 시:
- 모든 토큰 폐기
- 세션 종료
- 재로그인 요구
JTI 기반 블랙리스트
JWT의 jti 활용:
- 로그아웃 시 저장
- 재사용 시 차단
저장소 예:
- Redis
단점:
- 완전 Stateless 포기
SID + JTI 세션 추적
전략:
- SID → 세션 식별자
- JTI → 토큰 식별자
구조:
Key: SID
Value: 현재 유효 JTI
TTL: Refresh Token 만료 시간
효과:
- 토큰 재사용 탐지
- 세션 강제 폐기 가능
환경 바인딩 (보조 수단)
예:
- User-Agent 해시
- 디바이스 정보
완벽한 방어는 아니며 이상 징후 탐지용.
중요 기능 추가 인증
대상:
- 비밀번호 변경
- 결제
- 송금
- 권한 변경
전략:
- 재인증
- MFA / 2FA
14. Stateless vs Stateful 현실적 선택
| 전략 | 특징 |
|---|---|
| 순수 JWT | 확장성 높음 / 통제 약함 |
| Refresh 서버 관리 | 통제 강함 / 상태성 증가 |
실무에서 목적에 따라 trade off가 필요하다
15. 실무 권장 조합
일반 서비스 기준:
- HTTPS
- HTTP-only Cookie
- SameSite 설정
- Access Token 수명 단축
- Refresh Rotation
- 중요 기능 재인증
보안 민감 서비스:
- Refresh Token 서버 저장
- Reuse Detection
- 세션 추적
16. 핵심 요약
- JWT는 bearer token이다
- 위조보다 탈취가 위험하다
- 저장 전략이 보안의 핵심이다
- 짧은 수명 + Rotation이 기본 대응이다
- 완전 Stateless에 집착하지 않는다
보안은 기술 문제가 아니라 설계 문제
같이보면 좋은 글
Leave a comment