# 第八章:OpenID Connect 身份认证 > "OAuth 2.0 告诉你'这个人授权了',OIDC 告诉你'这个人是谁'。" ```{mermaid} mindmap root((OpenID Connect)) 核心概念 ID Token UserInfo Claims 流程 Authorization Code Implicit Hybrid 发现 Discovery JWKS 提供商 Keycloak Auth0 Okta ``` ## 8.1 OIDC 与 OAuth 2.0 的关系 OIDC(OpenID Connect)是建立在 OAuth 2.0 之上的**身份认证层**: ``` ┌─────────────────────────────────────┐ │ OpenID Connect │ │ (身份认证 — 你是谁?) │ │ ID Token, UserInfo, Claims │ ├─────────────────────────────────────┤ │ OAuth 2.0 │ │ (授权 — 你能做什么?) │ │ Access Token, Scope, Grant │ ├─────────────────────────────────────┤ │ HTTP / TLS │ └─────────────────────────────────────┘ ``` | 维度 | OAuth 2.0 | OIDC | |------|-----------|------| | 目的 | 授权(访问资源) | 认证(确认身份) | | 核心 Token | Access Token | ID Token | | 用户信息 | 不标准 | UserInfo Endpoint | | 发现机制 | 无 | .well-known/openid-configuration | | Scope | 自定义 | openid, profile, email | ## 8.2 ID Token ID Token 是一个 JWT,包含用户身份信息: ```json { "iss": "https://auth.example.com", "sub": "user-123", "aud": "my-client-app", "exp": 1709510400, "iat": 1709506800, "nonce": "abc123", "name": "Walter Fan", "email": "walter@example.com", "email_verified": true, "picture": "https://example.com/photo.jpg" } ``` ### 标准 Claims | Claim | 说明 | 必须 | |-------|------|------| | iss | 签发者 | ✅ | | sub | 用户唯一标识 | ✅ | | aud | 受众(Client ID) | ✅ | | exp | 过期时间 | ✅ | | iat | 签发时间 | ✅ | | nonce | 防重放攻击 | 条件必须 | | name | 用户全名 | ❌ | | email | 邮箱 | ❌ | | picture | 头像 URL | ❌ | ## 8.3 OIDC 授权码流程 ``` ┌──────────┐ ┌──────────────┐ │ 用户 │ 1. 访问应用 │ │ │ (浏览器) │──────────────────▶│ Client │ │ │ │ (Web App) │ │ │ 2. 重定向到 IdP │ │ │ │◀──────────────────│ │ │ │ └──────────────┘ │ │ 3. 登录 + 授权 │ │──────────────────▶ ┌──────────────┐ │ │ │ IdP │ │ │ 4. 重定向回 Client│ (OIDC Provider)│ │ │ + auth code │ │ │ │◀──────────────────│ │ │ │ └──────┬───────┘ │ │ │ └────┬─────┘ │ │ │ ▼ │ ┌──────────────┐ 5. code → tokens │ │ Client │──────────────────────▶│ │ (后端) │ 6. id_token + │ │ │ access_token │ │ │◀──────────────────────│ │ │ │ │ │ 7. 验证 id_token │ │ │ 8. 获取 UserInfo │ │ │──────────────────────▶│ │ │ 9. 用户信息 │ │ │◀──────────────────────│ └──────────────┘ ``` ## 8.4 OIDC Discovery 每个 OIDC 提供商都有一个发现端点: ``` GET https://auth.example.com/.well-known/openid-configuration { "issuer": "https://auth.example.com", "authorization_endpoint": "https://auth.example.com/authorize", "token_endpoint": "https://auth.example.com/oauth/token", "userinfo_endpoint": "https://auth.example.com/userinfo", "jwks_uri": "https://auth.example.com/.well-known/jwks.json", "scopes_supported": ["openid", "profile", "email"], "response_types_supported": ["code", "id_token", "token id_token"], "id_token_signing_alg_values_supported": ["RS256", "ES256"], "subject_types_supported": ["public", "pairwise"] } ``` ## 8.5 OIDC 提供商对比 | 特性 | Keycloak | Auth0 | Okta | Google | |------|----------|-------|------|--------| | 类型 | 开源自托管 | SaaS | SaaS | SaaS | | 协议 | OIDC/SAML/OAuth2 | OIDC/SAML | OIDC/SAML | OIDC | | 定价 | 免费 | 免费层+付费 | 付费 | 免费 | | 自定义 | 高 | 中 | 中 | 低 | | 企业功能 | 完整 | 完整 | 完整 | 有限 | | 部署 | 自托管/K8s | 云 | 云 | 云 | ## 8.6 Python OIDC 客户端 ```python from authlib.integrations.starlette_client import OAuth from starlette.config import Config from fastapi import FastAPI, Request from starlette.middleware.sessions import SessionMiddleware app = FastAPI() app.add_middleware(SessionMiddleware, secret_key="session-secret") oauth = OAuth() oauth.register( name='keycloak', server_metadata_url='https://auth.example.com/realms/myrealm/.well-known/openid-configuration', client_id='my-app', client_secret='my-secret', client_kwargs={'scope': 'openid profile email'}, ) @app.get('/login') async def login(request: Request): redirect_uri = request.url_for('auth_callback') return await oauth.keycloak.authorize_redirect(request, redirect_uri) @app.get('/callback') async def auth_callback(request: Request): token = await oauth.keycloak.authorize_access_token(request) id_token = token.get('id_token') userinfo = token.get('userinfo') # 用户已认证 return { "sub": userinfo["sub"], "name": userinfo.get("name"), "email": userinfo.get("email"), } ``` ## 8.7 小结 - OIDC 是 OAuth 2.0 之上的**身份认证层**,提供标准化的用户身份信息 - **ID Token** 是 JWT 格式,包含用户身份 Claims - **Discovery** 端点使客户端可以自动发现 OIDC 配置 - Keycloak 是最流行的开源 OIDC 提供商,适合自托管场景 - OIDC 是零信任架构中人类身份认证的首选协议