跳到主要内容

OpenID Connect

OpenID Connect(OIDC)是基于 OAuth 2.0 协议的身份认证层。它在 OAuth 2.0 的授权功能之上,添加了标准化的身份认证能力,允许客户端验证用户身份并获取用户基本信息。

为什么需要 OpenID Connect?

OAuth 2.0 是一个授权协议,它解决了"第三方应用如何安全地访问用户资源"的问题。但 OAuth 2.0 并没有标准化用户身份信息的传递方式。

OpenID Connect 解决了这个问题:

  1. 标准化身份认证 - 统一的用户信息获取方式
  2. 单点登录(SSO) - 一次登录,多处访问
  3. 身份提供商生态 - 支持 Google、Microsoft、Apple 等主流身份提供商
  4. 简化开发 - 无需为每个身份提供商写不同的集成代码

核心概念

ID Token

ID Token 是 OpenID Connect 引入的核心概念,它是一个包含用户身份信息的 JWT。

ID Token 结构

{
"iss": "https://accounts.google.com",
"sub": "1234567890",
"aud": "your-client-id",
"exp": 1234567890,
"iat": 1234567800,
"name": "John Doe",
"email": "[email protected]",
"picture": "https://example.com/photo.jpg"
}

标准声明(Standard Claims)

声明说明
sub用户的唯一标识符(Subject)
name用户全名
given_name
family_name
email电子邮件地址
email_verified邮箱是否已验证
picture头像 URL
updated_at信息最后更新时间

与 OAuth 2.0 的关系

┌─────────────────────────────────────────────────────┐
│ OpenID Connect │
│ ┌─────────────────────────────────────────────┐ │
│ │ OAuth 2.0 │ │
│ │ ┌─────────────────────────────────────┐ │ │
│ │ │ HTTP + TLS │ │ │
│ │ └─────────────────────────────────────┘ │ │
│ └─────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────┘
  • OAuth 2.0 提供授权框架
  • OpenID Connect 在之上添加身份认证层

认证流程

授权码模式(Authorization Code Flow)

最常用、最安全的流程,适用于有后端的应用。

┌─────────┐                                    ┌─────────┐
│ Client │ │ OpenID │
│ │ │ Provider│
└────┬────┘ └────┬────┘
│ │
│ 1. 认证请求 (scope 包含 openid) │
│ ───────────────────────────────────────────> │
│ │
│ 2. 用户登录并授权 │
│ │
│ 3. 返回授权码 │
│ <─────────────────────────────────────────── │
│ │
│ 4. 用授权码交换令牌 │
│ ───────────────────────────────────────────> │
│ │
│ 5. 返回 ID Token + Access Token │
│ <─────────────────────────────────────────── │
│ │
│ 6. 可选:使用 Access Token 获取用户信息 │
│ ───────────────────────────────────────────> │
│ │
│ 7. 返回用户信息 │
│ <─────────────────────────────────────────── │

隐式模式(Implicit Flow)

⚠️ 已被标记为不安全,不推荐使用

混合模式(Hybrid Flow)

结合了授权码模式和隐式模式的特点,某些场景下使用。

Discovery 端点

OpenID Connect 提供 Discovery 机制,客户端可以通过一个 URL 获取所有配置信息。

Discovery URL 格式

https://&#123;issuer&#125;/.well-known/openid-configuration

示例(Google):

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"],
"grant_types_supported": ["authorization_code", "refresh_token"],
"id_token_signing_alg_values_supported": ["RS256"]
}

常用 Scope

Scope说明
openid必需,表示使用 OpenID Connect
profile访问用户基本资料(姓名、头像等)
email访问用户邮箱地址
address访问用户地址信息
phone访问用户电话号码
offline_access获取 Refresh Token

单点登录(SSO)

OpenID Connect 是实现单点登录的标准方案。

SSO 流程

┌─────────┐     ┌─────────┐     ┌─────────┐
│ App A │ │ IdP │ │ App B │
└────┬────┘ └────┬────┘ └────┬────┘
│ │ │
│ 1. 登录 │ │
│ ─────────────>│ │
│ │ │
│ 2. 认证成功 │ │
│ <─────────────│ │
│ │ │
│ 3. 访问 App B│ │
│ │ │
│ │ 4. 自动登录 │
│ │ <─────────────│
│ │ │
│ │ 5. 已认证 │
│ │ ─────────────>│

登出(Logout)

OpenID Connect 定义了两种登出方式:

  1. RP-Initiated Logout - 客户端发起的登出
  2. Session Management - 会话管理,检测登录状态变化

身份提供商(IdP)

主流身份提供商

提供商Discovery URL
Googlehttps://accounts.google.com/.well-known/openid-configuration
Microsofthttps://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration
Applehttps://appleid.apple.com/.well-known/openid-configuration
Auth0https://{tenant}.auth0.com/.well-known/openid-configuration
Oktahttps://{tenant}.okta.com/.well-known/openid-configuration

自建身份提供商

  • Keycloak - 开源,功能丰富
  • Authelia - 轻量级,适合家庭/小团队
  • Casdoor - 国产开源方案

安全最佳实践

验证 ID Token

必须验证以下声明:

  • iss - 发行者是否可信
  • aud - 受众是否为自己的 client_id
  • exp - 令牌是否过期
  • iat - 签发时间是否合理
  • 签名 - 使用 IdP 的公钥验证

使用 PKCE

所有客户端(包括机密客户端)都应该使用 PKCE。

状态管理

  • 使用 state 参数防止 CSRF
  • 使用 nonce 防止重放攻击

OAuth 2.0 vs OpenID Connect

特性OAuth 2.0OpenID Connect
主要目的授权认证
令牌类型Access TokenAccess Token + ID Token
用户信息通过 API 获取包含在 ID Token 中
标准化授权协议认证层(基于 OAuth 2.0)
使用场景第三方授权单点登录、身份认证
Discovery不支持支持
登出机制无标准标准登出流程

代码实现

Node.js (openid-client)

const { Issuer, generators } = require('openid-client');

// Discovery - 自动获取配置
const googleIssuer = await Issuer.discover('https://accounts.google.com');

const client = new googleIssuer.Client({
client_id: process.env.GOOGLE_CLIENT_ID,
client_secret: process.env.GOOGLE_CLIENT_SECRET,
redirect_uris: ['http://localhost:3000/callback'],
response_types: ['code']
});

// 登录
app.get('/login', (req, res) => {
const nonce = generators.nonce();
const state = generators.state();
req.session.nonce = nonce;
req.session.state = state;

const url = client.authorizationUrl({
scope: 'openid email profile',
nonce,
state
});
res.redirect(url);
});

// 回调
app.get('/callback', async (req, res) => {
const params = client.callbackParams(req);
const tokenSet = await client.callback(
'http://localhost:3000/callback',
params,
{ nonce: req.session.nonce, state: req.session.state }
);

// 验证 ID Token
const claims = tokenSet.claims();
console.log('User:', claims.sub, claims.email);

res.redirect('/dashboard');
});

Python (python-oauth2)

from authlib.integrations.requests_client import OAuth2Session

# 配置 OIDC
client = OAuth2Session(
client_id=os.getenv('GOOGLE_CLIENT_ID'),
client_secret=os.getenv('GOOGLE_CLIENT_SECRET'),
scope='openid email profile'
)

@app.route('/login')
def login():
uri, state = client.create_authorization_url(
'https://accounts.google.com/o/oauth2/v2/auth'
)
session['oauth_state'] = state
return redirect(uri)

@app.route('/callback')
def callback():
token = client.fetch_token(
'https://oauth2.googleapis.com/token',
authorization_response=request.url,
state=session['oauth_state']
)
# 获取用户信息
userinfo = client.get('https://openidconnect.googleapis.com/v1/userinfo').json()
return redirect('/dashboard')

小结

  1. 核心要点

    • OpenID Connect 在 OAuth 2.0 之上添加身份认证
    • ID Token 是核心概念,包含用户身份信息
    • 支持 Discovery,简化配置
  2. 主要优势

    • 标准化的身份认证
    • 单点登录(SSO)
    • 丰富的身份提供商生态
    • 简化多身份源集成
  3. 适用场景

    • 第三方登录(微信、GitHub、Google 等)
    • 企业内部单点登录
    • 多应用统一身份管理
    • 零信任架构身份验证