本页目录
OAuth2 与 OpenID Connect
OAuth2 是授权框架(让应用以你的名义访问你的资源),OIDC 在它之上加了一层认证(让应用确认你是谁)。authorization code + PKCE 是当前最佳实践,implicit flow 已死。
概述
OAuth2(RFC 6749, 2012)是互联网授权的标准框架——"让第三方应用访问我的资源,但不需要我的密码"。核心是 Authorization Code + PKCE 流程:浏览器重定向到授权服务器 → 用户登录 → 浏览器携带 code 返回 → client 用 code 换 access token。OIDC(OpenID Connect, 2014)在 OAuth2 上加入身份认证(id_token),成为"Login with Google/GitHub"的基础。JWT 是 OAuth2 最常用的 access token 格式——自包含、可验证、无状态。
OAuth2: 授权 (不是认证)
四个角色:
Resource Owner: 用户
Client: 第三方应用
Authorization Server: 授权服务器
Resource Server: API 服务器
Authorization Code + PKCE (唯一推荐的 web flow):
1. Client: 生成 code_verifier (随机), code_challenge = SHA256(verifier)
2. Browser redirect:
GET /authorize?response_type=code
&client_id=grafana
&redirect_uri=https://grafana.example.com/login/callback
&scope=openid profile email
&state=random123
&code_challenge=<base64url(challenge)>
&code_challenge_method=S256
3. User 登录 + consent
4. Browser redirect back: https://grafana.example.com/login/callback?code=AUTH_CODE&state=random123
5. Client → Authorization Server (backchannel):
POST /token
grant_type=authorization_code
&code=AUTH_CODE
&redirect_uri=...
&code_verifier=<verifier> ← server 验证 SHA256(verifier)==challenge
6. Response: { "access_token", "refresh_token", "id_token", "token_type":"Bearer", "expires_in":3600 }
7. Client: 用 access_token 请求 API (Authorization: Bearer <token>)
PKCE 为什么需要
传统 flow 中 code 可以被拦截 (mobile app 的 redirect URI 可能被其他 app 注册)。PKCE 保证即使 code 泄露,没有 code_verifier 也换不来 token。
JWT
格式: base64(header).base64(payload).signature
Header: {"alg":"RS256","typ":"JWT","kid":"key-2025"}
Payload (claims):
iss: 签发者
sub: 用户 ID (subject)
aud: 接收方 (audience, 此 token 给谁用)
exp: 过期时间 (unix)
iat: 签发时间
email, name, groups: 自定义 claims
Signature: RSA-SHA256(base64(header)+"."+base64(payload))
验证:
1. 获取 JWKS (https://auth.example.com/.well-known/jwks.json) → 取 kid 对应公钥
2. 验证签名
3. 检查 exp (未过期), aud (此 token 是给我的), iss (来自信任的 issuer)
OpenID Connect (OIDC)
OIDC = OAuth2 + 用户身份 (id_token):
id_token (JWT): 给 client 证明"用户是谁" (不是用来调 API 的)
access_token: 给 API 证明"client 有权访问" (不包含用户信息)
Client Credentials (机器间)
POST /token
grant_type=client_credentials
&client_id=my-app
&client_secret=secret
→ { "access_token":"...", "expires_in":3600 }
→ 没有用户参与
参考
- jwt.io: debug JWT
- Keycloak: open source identity provider
- OIDC playground: openidconnect.net
Keywords: OAuth2, PKCE, JWT, OIDC, id_token, client credentials, JWKS, Keycloak