Tan Kim

인증 & 인가 (Authentication & Authorization)

JWT (JSON Web Token)

세 부분이 .으로 구분된 Base64URL 인코딩 토큰.

Header.Payload.Signature
eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjMifQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

구성

// Header
{ "alg": "HS256", "typ": "JWT" }
 
// Payload (공개 정보 — 민감 정보 금지)
{
  "sub": "1234567890",  // Subject (사용자 ID)
  "iat": 1516239022,    // Issued At
  "exp": 1516242622,    // Expiration
  "role": "admin"
}
 
// Signature
HMACSHA256(base64(header) + "." + base64(payload), secret)

Access Token + Refresh Token 패턴

Access Token  — 짧은 만료 (15분~1시간), API 요청에 사용
Refresh Token — 긴 만료 (7일~30일), DB에 저장, Access Token 재발급용
// Node.js (jsonwebtoken)
import jwt from 'jsonwebtoken'
 
const ACCESS_SECRET = process.env.JWT_ACCESS_SECRET!
const REFRESH_SECRET = process.env.JWT_REFRESH_SECRET!
 
function issueTokens(userId: number) {
  const accessToken = jwt.sign({ sub: userId }, ACCESS_SECRET, { expiresIn: '15m' })
  const refreshToken = jwt.sign({ sub: userId }, REFRESH_SECRET, { expiresIn: '7d' })
  return { accessToken, refreshToken }
}
 
function verifyAccess(token: string) {
  return jwt.verify(token, ACCESS_SECRET) as { sub: number }
}

JWT 취약점 & 주의사항

취약점 설명 대응
alg: none 공격 서명 검증 우회 알고리즘 명시적으로 지정
약한 시크릿 브루트포스 가능 256비트 이상 랜덤 시크릿
Payload 민감 정보 Base64 디코딩으로 열람 가능 민감 정보 포함 금지
XSS로 토큰 탈취 localStorage 저장 시 취약 HttpOnly Cookie 사용

OAuth 2.0

제3자에게 권한을 위임하는 표준 프로토콜.

Authorization Code Flow (웹 서버)

User → Client → AuthServer: 인증 요청
AuthServer → User: 로그인 + 동의
AuthServer → Client: Authorization Code
Client → AuthServer: Code + Client Secret
AuthServer → Client: Access Token + Refresh Token
Client → ResourceServer: Access Token으로 API 호출

세션 vs JWT

항목 세션 JWT
상태 Stateful (서버에 저장) Stateless
확장성 수평 확장 어려움 쉬움
로그아웃 즉시 무효화 가능 만료까지 유효 (블랙리스트 필요)
저장 위치 서버 메모리/DB 클라이언트

메모