본문으로 건너뛰기
김신건의 로그

[Auth] OpenID Connect (OIDC): OAuth 위의 인증 레이어

· 수정 · 📖 약 2분 · 873자/단어 #oidc #oauth #auth #sso #backend
OIDC, OpenID Connect, id_token, userinfo endpoint, discovery, .well-known/openid-configuration

정의

OpenID Connect (OIDC)OAuth 2.0 위에 얹은 인증 (authentication) 표준. OAuth 가 권한 위임 (authorization), OIDC 가 “누구인지” 알려준다.

핵심 추가:

  1. id_token (JWT): 사용자 식별 정보
  2. /userinfo endpoint: 추가 프로필 정보
  3. Discovery: .well-known/openid-configuration 으로 자동 설정
  4. Scope openid: OIDC 활성화 신호

사용 시나리오

상황OIDC 역할
SPA / 모바일 앱 로그인Authorization Code + PKCE
기업 SSOOkta / Keycloak → 여러 앱 자동 인증
소셜 로그인Google / Kakao → 내 앱에서 id_token 검증
K8s API 인증OIDC Provider 와 kube-apiserver 연동

흐름

sequenceDiagram
    autonumber
    participant U as User
    participant App as Client App
    participant Idp as OIDC Provider
    Note over App: scope=openid profile email
    App->>U: redirect to Idp
    U->>Idp: 로그인 + 동의
    Idp-->>App: code (Authorization Code)
    App->>Idp: POST /token<br/>code + verifier
    Idp-->>App: { access_token, id_token, refresh_token }
    App->>App: id_token (JWT) 검증
    App->>Idp: GET /userinfo (옵션)<br/>Bearer access_token
    Idp-->>App: { sub, name, email, picture, ... }

PKCE 상세 흐름

PKCE (Proof Key for Code Exchange) 는 Authorization Code 탈취 방지. 공개 클라이언트 (SPA, 모바일) 필수.

sequenceDiagram
    autonumber
    participant App as Client
    participant Idp as OIDC Provider

    App->>App: code_verifier = random 43-128자
    App->>App: code_challenge = BASE64URL(SHA256(verifier))
    App->>Idp: GET /auth?code_challenge=XXX&code_challenge_method=S256
    Idp-->>App: redirect + code
    App->>Idp: POST /token<br/>code + code_verifier
    Idp->>Idp: SHA256(verifier) == code_challenge?
    Idp-->>App: tokens

code 만 탈취해도 verifier 없이는 token 교환 불가. SPA 에서 PKCE 없는 Authorization Code Flow 는 안전하지 않음.

id_token 의 표준 클레임

클레임의미
issIssuer (Idp URL)
subSubject (사용자 ID, 영구 식별자)
audAudience (Client ID)
exp만료
iat발급 시각
auth_time사용자가 마지막으로 인증한 시각
noncereplay 방지
acrAuthentication Context Class Reference
amrAuthentication Methods (["pwd", "mfa"])
azpAuthorized Party
프로필name, given_name, family_name, email, email_verified, picture

id_token 검증 절차

id_token 은 단순히 받는 것으로 충분하지 않음. 반드시 서버에서 검증.

flowchart TD
    T["id_token 수신"]
    T --> V1["1. JWT 서명 검증<br/>(JWKS 에서 키 가져오기)"]
    V1 --> V2["2. iss 검증<br/>(기대 Idp URL?)"]
    V2 --> V3["3. aud 검증<br/>(내 Client ID?)"]
    V3 --> V4["4. exp 검증<br/>(만료 안 됐나?)"]
    V4 --> V5["5. nonce 검증<br/>(replay 방지)"]
    V5 --> OK["인증 완료"]
# python-jose 예시
from jose import jwt

payload = jwt.decode(
    id_token,
    jwks,           # JWKS 에서 가져온 공개키
    algorithms=["RS256"],
    audience="my-client-id",
    issuer="https://accounts.google.com",
)
# payload["sub"] 가 사용자 영구 ID

Discovery: .well-known/openid-configuration

curl https://accounts.google.com/.well-known/openid-configuration
{
  "issuer": "https://accounts.google.com",
  "authorization_endpoint": "https://accounts.google.com/o/oauth2/v2/auth",
  "token_endpoint": "https://oauth2.googleapis.com/token",
  "userinfo_endpoint": "https://openidconnect.googleapis.com/v1/userinfo",
  "jwks_uri": "https://www.googleapis.com/oauth2/v3/certs",
  "scopes_supported": ["openid", "email", "profile"],
  "response_types_supported": ["code", "token", "id_token", ...],
  "id_token_signing_alg_values_supported": ["RS256"],
  ...
}

클라이언트는 Idp URL 하나만 알면 모든 endpoint 자동 발견. 신규 OIDC Provider 통합이 1줄.

JWKS (JSON Web Key Set)

curl https://www.googleapis.com/oauth2/v3/certs
{
  "keys": [
    {
      "kty": "RSA",
      "alg": "RS256",
      "use": "sig",
      "kid": "abc123",
      "n": "...",
      "e": "AQAB"
    }
  ]
}
  • Idp 가 공개키 공개.
  • 클라이언트가 id_token 의 kid해당 키 찾아 검증.
  • 키 회전복수 키 동시 공존.

OIDC 흐름 종류

Flow응답 타입사용
Authorization Code Flow + PKCEresponse_type=code권장 (모든 클라이언트)
Implicit Flowresponse_type=id_token token폐기
Hybrid Flowresponse_type=code id_token일부 경우

SSO (Single Sign-On)

flowchart LR
    User --> App1[App 1]
    User --> App2[App 2]
    User --> App3[App 3]
    App1 --> Idp[OIDC Provider]
    App2 --> Idp
    App3 --> Idp
    Idp --> Login[중앙 로그인 1회]

한 번 로그인 → 여러 앱 자동 인증. 기업 SSO (Okta, Auth0, Keycloak) 의 토대.

로그아웃 흐름

OIDC 는 로그아웃 도 표준화. 세 가지 방식:

방식설명
RP-Initiated Logout앱이 Idp 에 로그아웃 요청. Idp 세션 종료
Front-Channel LogoutIdp 가 모든 연결 앱에 로그아웃 알림 (iframe)
Back-Channel LogoutIdp 가 서버-서버로 로그아웃 알림 (더 안정)
# RP-Initiated Logout
GET https://idp.example.com/logout?
  id_token_hint=<id_token>&
  post_logout_redirect_uri=https://myapp.com/

WARNING

로컬 세션만 지우는 것 은 완전한 로그아웃이 아님. Idp 세션도 종료 해야 SSO 전체에 영향.

K8s + OIDC 통합

kube-apiserver 에 OIDC Provider 를 연결해 kubectl 사용자 인증 에 활용:

# kube-apiserver 플래그
--oidc-issuer-url=https://accounts.google.com
--oidc-client-id=my-k8s-client
--oidc-username-claim=email
--oidc-groups-claim=groups
# kubeconfig 에 OIDC 토큰 설정
kubectl config set-credentials alice \
  --auth-provider=oidc \
  --auth-provider-arg=idp-issuer-url=https://accounts.google.com \
  --auth-provider-arg=client-id=my-k8s-client \
  --auth-provider-arg=id-token=<id_token>

OIDC 로 인증된 사용자 email / group 을 RBAC 의 subject 로 사용. 중앙 IdP 로 K8s 접근 제어 통합.

사용 라이브러리

언어라이브러리
Nodepassport-openidconnect, openid-client
Pythonauthlib, python-jose
Javaspring-security-oauth2-client, Nimbus JOSE
Gogo-oidc, oidc-mw
Rubyomniauth-openid-connect

OIDC vs OAuth vs SAML

OAuth 2.0OIDCSAML 2.0
목적권한 위임인증인증 + 권한
토큰access_token+ id_token (JWT)SAML Assertion (XML)
페이로드bearerJWTXML
모바일 친화좋음최고떨어짐
기업일부모던 표준옛 표준, 여전히 많음

흔한 함정

WARNING

  1. id_token 만 신뢰 = aud, iss, exp, nonce 모두 검증해야 함.
  2. JWKS 매 요청 fetch = 캐싱 필요 (보통 24h). 단 key rotation 시 빠르게 갱신.
  3. sub 변경 = 같은 Idp 의 같은 사용자는 sub 가 영구 동일. 다른 Idp 의 같은 이메일은 다른 sub.
  4. email 만 보고 사용자 식별 = 이메일 변경 가능. 항상 sub 로 매핑.
  5. Implicit Flow 아직 사용 = 폐기된 방식. PKCE 있는 Authorization Code Flow 로 전환.

관련 위키

이 글의 용어 (4개)
[Auth] JWT: 구조, 서명, 만료, refresh tokenauth-security
정의 JWT (JSON Web Token) (RFC 7519) 은 base64url 인코딩된 JSON + 서명 형태의 self-contained token. 서버가 세션 저장 없…
[Auth] OAuth 2.0 / 2.1: Authorization Code + PKCEauth-security
정의 OAuth 2.0 (RFC 6749, 2012) 은 제3자 앱이 사용자 동의로 자원에 접근 하게 하는 권한 위임 프레임워크. 인증 (authentication) 이 아니라 …
[Auth] SAML 2.0: XML 기반 기업 SSOauth-security
정의 SAML 2.0 (Security Assertion Markup Language) 는 XML 기반 기업 SSO 표준. 2005년 OASIS 표준화. 모바일 친화도 / 단순성…
[Auth] Session Cookie: HttpOnly, SameSite, Secure flagauth-security
정의 Session Cookie 는 서버가 발급한 임의 ID 를 쿠키에 보관. 매 요청 자동 첨부. 서버 측 세션 store (Redis, DB) 와 짝. [!IMPORTANT]…

💬 댓글

사이트 검색 / 명령어

검색

스크롤 = 확대/축소 · 드래그 = 이동 · 0 = 원래 크기 · ESC = 닫기