애플리케이션 보안

OpenID Connect

meellon 2026. 6. 24. 08:00

학습 목표

OpenID Connect(OIDC) 가 OAuth 2.0 위 identity layer임을 설명할 수 있다.

ID tokenaccess token의 목적·검증 차이를 구분할 수 있다.

Authorization Code + PKCE로 OIDC 로그인 흐름을 단계별로 설명할 수 있다.

nonce·iss·aud·exp 검증과 UserInfo endpoint 역할을 설명할 수 있다.

문제 상황

  • OAuth access token만 받고 sub로그인 ID로 썼다
    • access token은 API 위임용 — 신원 증명 표준이 아님
  • Google "로그인" 후 이메일을 UserInfo 없이 access token payload에서 읽었다
    • provider마다 형식이 다르고 검증 규칙도 없다
  • ID token 서명 검증 없이 Base64 디코딩만 했다
    • JWT를 Base64 디코딩만 했다 — 위조·algorithm confusion 위험 (앞서 JWT)
  • SPA가 ID token을 localStorage에 저장했다
    • XSS 시 로그인 세션 탈취
  • Authorization 요청에 nonce가 없어 replay를 막지 못했다
    • 동일 ID token 재전송 공격

OAuth 2.0에서 위임·PKCE를 봤다. OIDC는 같은 흐름에 "누가 로그인했는가" 를 표준 JWT(ID token)로 추가한다.

본 글의 흐름·예제는 방어·구현 학습 목적이다. 타인 계정·토큰에 대한 무단 접근은 불법이다.

1. OpenID Connect란

OpenID Connect — OAuth 2.0 위에 올린 인증(authentication) 프로토콜.

  OAuth 2.0 OpenID Connect
목적 접근 위임 — API scope 신원 확인 — 로그인
핵심 토큰 access token ID token (+ access token)
"누구" Resource Owner 동의로 간접 ID token claims로 표준화
discovery (없음) /.well-known/openid-configuration

  • Relying Party(RP) — 로그인을 받는 앱 (Client와 동일 주체)
  • OpenID Provider(OP) — Google, Keycloak, Auth0 등 — Authorization Server + identity
  • OIDC는 OAuth를 대체하지 않음openid scope를 추가한 확장

2. ID token vs access token

  ID token access token
형식 JWT (JWS) — signed JWT 또는 opaque
용도 인증 — "이 사용자가 로그인함" 인가 — API 호출
검증 RP가 서명·iss·aud·exp·nonce 검증 Resource Server가 scope·exp 검증
전달 RP 백엔드에서 검증 후 세션 생성 Authorization: Bearer
API 호출 UserInfo 등 일부 endpoint Resource Server 일반 API
{
  "iss": "https://accounts.example.com",
  "sub": "user-8f3a",
  "aud": "shop-web-client",
  "exp": 1719003600,
  "iat": 1719000000,
  "nonce": "n-0d8f2c1a",
  "email": "user@example.com",
  "email_verified": true
}
  • sub — OP 내 사용자 고유 ID (앱 간 안정적 식별자)
  • nonce — authorize 요청의 nonce와 일치해야 함 (replay 방지)
  • email 등은 scope·OP 정책에 따라 ID token 또는 UserInfo에만 올 수 있음

access token으로 "로그인" 판단하지 말 것 — OIDC는 ID token 또는 UserInfo + access token 조합을 쓴다.

예시 claims는 code/oidc-id-token-claims.json 참고.

3. Discovery와 JWKS

OP 메타데이터로 endpoint·키를 자동 발견.

GET https://accounts.example.com/.well-known/openid-configuration
필드 용도
authorization_endpoint /authorize
token_endpoint code → token
userinfo_endpoint access token으로 프로필
jwks_uri ID token 서명 검증용 공개키
GET https://accounts.example.com/.well-known/jwks.json
  • JWT RS256이면 JWKS에서 kid에 맞는 키 선택 (앞서 JWT)
  • iss는 discovery URL의 issuer와 exact match
  • 키 로테이션 — JWKS 캐시 TTL·실패 시 재fetch

4. Authorization Code + PKCE (로그인)

웹·SPA·모바일 소셜 로그인 표준 — 앞서 본 PKCE에 OIDC 파라미터 추가.

authorize (브라우저)

GET /authorize?
  response_type=code
  &client_id=shop-web
  &redirect_uri=https://shop.example/callback
  &scope=openid profile email
  &state=RANDOM_CSRF
  &nonce=RANDOM_NONCE
  &code_challenge=E9Mel...
  &code_challenge_method=S256
파라미터 의미
scope=openid OIDC 요청 — 필수
profile email 선택 claims / UserInfo scope
state CSRF 방지 (OAuth와 동일)
nonce ID token replay 방지 — 필수 권장

token (백채널)

POST /token
grant_type=authorization_code
&code=AUTH_CODE
&redirect_uri=https://shop.example/callback
&client_id=shop-web
&code_verifier=ORIGINAL_VERIFIER

응답:

{
  "access_token": "eyJhbG...",
  "token_type": "Bearer",
  "expires_in": 3600,
  "id_token": "eyJhbG...",
  "refresh_token": "..."
}

RP 처리 순서

  1. state 검증
  2. ID token — 서명, exp, iss, aud(client_id), nonce
  3. (선택) UserInfo — access token으로 추가 claims
  4. RP 세션 생성 — HttpOnly cookie 등 (앞서 인증 기초)
  5. ID token은 브라우저 장기 저장 금지 — 검증 후 폐기 또는 BFF 내부만

전체 HTTP 예시는 code/oidc-requests.http 참고.

5. UserInfo endpoint

ID token만으로 부족한 claims — access token으로 OP에 질의.

GET /userinfo HTTP/1.1
Authorization: Bearer eyJhbG...
{
  "sub": "user-8f3a",
  "name": "Kim",
  "email": "user@example.com",
  "email_verified": true
}
  ID token UserInfo
시점 token 응답 즉시 필요 시 추가 호출
검증 JWT 서명 + nonce access token 유효 + HTTPS
용도 로그인 핵심 신원 프로필·이메일 보강
  • sub는 ID token과 UserInfo에서 동일해야 함 — 불일치면 거부
  • access token scope에 profile·email 없으면 필드 미반환

6. 보안 체크리스트

항목 내용
scope openid 포함 — 없으면 OAuth만
nonce authorize·ID token 매칭
ID token 검증 alg allowlist, JWKS, iss, aud, exp
access token API·UserInfo만 — 세션 키로 쓰지 않음
저장 ID token localStorage 금지 — RP 세션·BFF
HTTPS authorize·token·UserInfo 전 구간
logout OP end_session_endpoint + RP 세션 삭제
mix-up 여러 OP 사용 시 iss·redirect_uri 엄격 분리
안티패턴 이유
access token = login proof 표준 아님, scope만 증명
ID token을 API Bearer로 audience·용도 불일치
nonce 생략 ID token replay
implicit flow (id_token fragment) URL·히스토리 유출 — code flow 사용

7. 정리

  • OIDC = OAuth 2.0 + identity layer소셜 로그인 표준
  • ID token(JWT)으로 신원, access token으로 API·UserInfo
  • Authorization Code + PKCE + openid + nonce가 웹·SPA 기본
  • discovery·JWKS로 OP endpoint·키 자동화
  • 검증 후 RP 세션 — ID token 장기 보관하지 않음

다음에 다룰 것

  • 인가 모델
  • RBAC, ABAC, policy engine

해당 내용은 OpenID Connect Core 1.0, RFC 6749 (OAuth 2.0), OWASP OAuth2 Cheat Sheet 의 내용을 기반으로 합니다.

'애플리케이션 보안' 카테고리의 다른 글

Injection  (0) 2026.06.26
인가 모델  (0) 2026.06.25
OAuth 2.0  (0) 2026.06.23
JWT  (0) 2026.06.22
인증 기초  (0) 2026.06.21