OpenID Connect — 是一个构建在 OAuth 2.0 之上的身份验证协议,它在标准授权的基础上增加了用户身份验证层。与纯粹的 OAuth 2.0 不同,在 OAuth 2.0 中访问令牌在无需用户信息的情况下提供对资源的访问,而 OpenID Connect 返回 ID Token — 带有经过验证的个人资料数据的 JWT。根据 OpenID Foundation, 2026 的数据,该协议得到所有主要身份提供商 — Google、Apple、Microsoft 和 Auth0 的支持。
要点
OpenID Connect (OIDC) — 是一个开放的身份验证协议,作为一层构建在 OAuth 2.0 之上。它标准化了 OAuth 2.0 所缺少的内容:用户身份验证。如果 OAuth 2.0 回答了 “哪个应用程序有权限?” 的问题,那么 OIDC 回答了 “这个用户究竟是谁?” 的问题。
该协议使用 ID Token — JSON Web Token (JWT),其中包含一组声明:主体的唯一标识符、电子邮件、姓名、头像、签发和过期时间戳。客户端应用程序可以以加密方式验证 ID Token — 服务器使用 RS256 或 ES256 签署令牌,客户端则通过 JWKS 端点获得的公钥验证签名。
根据 Auth0, 2025 的数据,使用第三方身份验证的移动应用程序中超过 78% 通过 Google Sign-In 或 Sign in with Apple 应用 OIDC。这使得该协议成为社交登录和企业身份验证的事实标准。
OpenID Connect 根据客户端类型定义多种流程。对于移动应用程序,标准是带有授权码证明密钥交换 (PKCE) 的授权码流程 — 即使在设备上没有客户端密钥也能提供保护。
Identity Provider (IdP) — 是执行用户身份验证并颁发令牌的服务器。在 OIDC 生态系统中,IdP 提供两个关键端点:用于用户登录的授权端点和用于将代码交换为令牌的 令牌端点。客户端通过发现 URL — 标准路径 /.well-known/openid-configuration(返回包含提供商完整配置的 JSON 文档)了解这些端点的地址。
每个 IdP 发布自己的 JWKS (JSON Web Key Set) — 用于验证 ID Token 签名的公钥集。客户端缓存这些密钥,并用于验证每个收到的令牌,无需查询服务器。
Authorisation Code Flow — 是一个三步过程。首先,移动应用程序生成一个 code verifier(长度为 43-128 个字符的随机字符串)及其哈希值 — code challenge。应用程序打开浏览器或 WebView,URL 包含 client_id、redirect_uri、scope (openid profile email) 和 code challenge。用户在 IdP 页面上输入凭据并确认同意。IdP 将浏览器重定向回应用程序,并附带授权码。
在第二步中,应用程序将授权码、code verifier 和 client_id 发送到服务器的令牌端点。服务器根据存储的 code challenge 验证 code verifier,并返回 ID Token、Access Token 和可选的 Refresh Token。在第三步中,应用程序 验证 ID Token:通过 JWKS 验证签名,检查 issuer (iss)、audience (aud) 和过期时间 (exp)。如果验证成功 — 用户被视为已通过身份验证。
PKCE (Proof Key for Code Exchange) 消除了公共客户端中标准授权码流程固有的漏洞。由于移动应用程序无法安全地存储客户端密钥,截获了授权码的攻击者可以将其交换为令牌。Code verifier 解决了这个问题:即使代码被截获,没有原始的 code verifier,交换也是不可能的。OAuth Security Best Practices (RFC 9700) 要求所有公共客户端(包括移动应用程序)使用 PKCE。
OpenID Connect 返回两个根本不同的令牌:ID Token 和 Access Token。ID Token — 始终是 JWT,客户端可以独立读取和验证。它包含用户信息,用于身份验证,而不是用于访问 API。
ID Token 由 header、payload 和 signature 组成,以 Base64 编码并用点分隔。Header 包含 alg(签名算法)和 kid(密钥标识符)。Payload 包含必需的声明:iss (issuer — 令牌颁发者)、sub (subject — 用户的唯一 ID)、aud (audience — 客户端标识符)、exp (expiration)、iat (issued at)。可选的 — name、email、picture、locale。
来自 Google 的解码后的 ID Token payload 示例:
{
"iss": "https://accounts.google.com",
"sub": "1234567890",
"aud": "my-app-123.apps.googleusercontent.com",
"exp": 1812345678,
"iat": 1812342078,
"name": "伊万·彼得罗夫",
"email": "ivan@example.com"
}
Access Token — 是一个不透明令牌(任意字符串)或 JWT,客户端在 API 请求中传递。与 ID Token 不同,access Token 不设计为客户端可读 — 其格式和内容仅资源服务器和授权服务器知晓。Access Token 具有 scope — 访问权限限制 — 和较短的生命周期,通常为 15-60 分钟。
OAuth 2.0 — 是一个授权框架,定义了应用程序如何获取对用户资源的访问权限。OpenID Connect — 是向此过程添加身份验证的一层。关键区别:OAuth 2.0 不定义令牌格式,也不为应用程序提供方法来确定究竟是谁发出了请求。
| 参数 | OAuth 2.0 | OpenID Connect |
|---|---|---|
| 目的 | 授权访问资源 | 身份验证 + 授权 |
| 身份令牌 | 无 | ID Token (JWT) |
| Scope | api:read, api:write | openid, profile, email |
| UserInfo 端点 | 可选 | 标准化 |
| Single Logout | 无 | OpenID Connect Session Management 规范 |
当应用程序需要 识别用户 而不仅仅获取对其数据的访问权限时,OpenID Connect 是必需的。如果您使用 “通过 Google 登录” 或 “Sign in with Apple” — 这就是 OIDC。如果您的应用程序代表用户调用第三方 API 而无需知道其身份 — 纯粹的 OAuth 2.0 就足够了。对于具有单点登录 (SSO) 的企业系统,选择是明确的:只有 OpenID Connect,因为它提供标准化的登出和会话管理。
将 OpenID Connect 集成到移动应用程序需要选择适当的库和正确配置流程。对于 Android,使用 credential manager (AndroidX Credentials) 或 AppAuth 库。对于 iOS — 使用带有 ASWebAuthenticationSession 的 AuthenticationServices 框架。
以下是使用 AppAuth-Android 库启动授权码流程的示例。应用程序创建授权请求,打开浏览器供用户登录,并处理带有令牌的回调。
val authRequest = AuthorizationRequest.Builder(
serviceConfig,
clientId,
"code",
Uri.parse("com.example.app:/oauth")
)
.setScope("openid profile email")
.build()
val authService = AuthorizationService(this)
val intent = authService.getAuthorizationRequestIntent(authRequest)
startActivityForResult(intent, REQUEST_CODE)
override fun onActivityResult(
requestCode: Int,
resultCode: Int,
data: Intent?
) {
if (requestCode == REQUEST_CODE) {
val response = AuthorizationResponse.fromIntent(data)
if (response?.authorizationCode != null) {
exchangeCodeForTokens(response.authorizationCode)
}
}
}
Apple 的 ASWebAuthenticationSession 为 OIDC 流程提供内置浏览器,通过 iCloud Keychain 支持 SSO。会话从授权 URL 启动,回调通过 completion handler 处理。
在选择 OpenID Connect 的库时,请考虑开箱即用的 PKCE 支持:AppAuth-Android 和 AppAuth-iOS 默认支持 PKCE。Firebase Authentication 在底层为 Google Sign-In、Sign in with Apple 和 Microsoft 使用 OIDC — 开发人员无需手动实现流程。对于具有自己 IdP 的企业系统(例如 Keycloak 或 Okta),AppAuth 仍然是标准选择,可以完全控制配置和错误处理。
let authURL = URL("https://accounts.google.com/o/oauth2/v2/auth")!
let callbackURL = URL("com.example.app://oauth")!
let session = ASWebAuthenticationSession(
url: authURL,
callbackURLScheme: callbackURL.scheme!
) { url, error in
guard let url = url else { return }
let components = URLComponents(url: url)
let code = components?.queryItems?.first(where: { $0.name == "code" })?.value
if let code = code { exchangeCode(code) }
}
session.start()
常见问题
OpenID Connect — 是 OAuth 2.0 之上的一层,添加了 身份验证。OAuth 2.0 仅负责对资源的访问授权。OIDC 引入了 ID Token — 带有用户数据的 JWT,标准化了 UserInfo 端点,并增加了单点登录和登出的功能。
对于移动应用程序,推荐使用 带有 PKCE 的授权码流程。它不需要客户端密钥,防止授权码被拦截,并得到所有主要身份提供商的支持。隐式流程已过时,不应在新项目中使用。
ID Token 分三步验证:通过 JWKS 端点的公钥验证签名、检查声明 (iss、aud、exp) 以及解码 payload。大多数 SDK — AppAuth、MSAL、Google Sign-In — 在收到令牌时自动执行此验证。
Scope openid — 是区分 OIDC 请求与普通 OAuth 2.0 的必需参数。没有它,服务器不会返回 ID Token。额外的 scope — profile、email、address — 确定令牌中将包含哪些关于用户的具体声明。
从技术上讲 — 可以,通过 Resource Owner Password Credentials 流程,但不推荐。浏览器流程确保凭据隔离 — 应用程序永远不会看到用户的密码。Apple 和 Google 要求对其服务使用浏览器身份验证。
总结
我们将开发一款交钥匙移动应用程序
IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。