要在 Capacitor app 中使用 Okta 登录,请创建一个 OIDC 原生应用 在 Okta 管理控制台中,注册一个登录重定向 URI,例如 com.example.app://oauth/okta,并在系统浏览器中运行带有 PKCE 的授权 code 流程。使用 @capgo/capacitor-social-login ,你只需配置一次 Okta 的 issuer 和 client ID,然后调用 SocialLogin.login({ provider: 'oauth2', options: { providerId: 'okta' } }).
本指南涵盖 Okta 应用集成、授权服务器策略、用于 iOS、Android 和 Web 的插件 code、token 刷新、用户资料、登出,以及最常见的 Okta 错误。目标为 2026 年 10 月版本的 Capacitor 8。
准备工作
- 一个具有管理员权限的 Okta 组织(Workforce Identity 或 Customer Identity),用于创建应用集成。
- 一个 Capacitor 8 应用。
- 您的 Capacitor
appId,稍后将其用作重定向 scheme。 - 可选:一个用于验证 Okta access token 的后端 API。
Okta 登录在 Capacitor 应用中的工作原理
您的应用不会显示密码表单。它会在安全浏览器中打开 Okta 登录页面,由 Okta 处理 MFA 和策略,然后携带 code 重定向回您的应用。应用随后使用 code 加上 PKCE verifier 换取 token。
| 平台 | 浏览器 | 您需要配置的内容 |
|---|---|---|
| iOS | ASWebAuthenticationSession |
在 Info.plist |
| Android | 使用 Chrome Custom Tabs 和 androidUseCustomTabs: true (默认使用 WebView) |
重定向方案的 Intent 过滤器 |
| Web 端 | 弹窗或重定向 | CORS 可信源 |
在 Android 上优先使用 Custom Tabs。Okta Verify、FastPass 和 passkeys 在系统浏览器中的表现优于嵌入式 WebView,且 SSO Cookie 可与 Chrome 共享。
步骤 1:创建 Okta 应用集成
- 在 Okta 管理控制台中,前往 应用程序 > 应用程序 > 创建应用集成.
- 选择 OIDC - OpenID Connect 以及 原生应用.
- 命名后,在下方 授权类型 保留 Code 授权 并勾选 刷新令牌 如果希望用户保持登录状态。
- 登录重定向 URI:
com.example.app://oauth/okta。添加https://app.example.com/auth/callback如果你发布 Web 构建。 - 登出重定向 URI:
com.example.app://oauth/logout(如有需要,还包括 Web URL)。 - 分配:选择谁可以使用该应用。未被分配的用户在登录时会收到错误提示。
- 保存,然后复制 客户端 ID。在 客户端凭证中,客户端身份验证应设为 无 以及 需要 PKCE 应处于开启状态。
Okta 要求使用反向域名格式的私有用途 scheme 作为原生重定向 URI。您的 bundle ID 或应用 ID 即可满足此要求。
检查授权服务器
前往 安全 > API > 授权服务器。大多数配置使用 default 自定义授权服务器、签发者 https://your-org.okta.com/oauth2/default.
| 签发者 | 适用场景 |
|---|---|
https://your-org.okta.com/oauth2/default (自定义) |
当您自己的 API 验证访问令牌,且需要自定义 scope 或 claims 时 |
https://your-org.okta.com (组织) |
仅需 ID token 或调用 Okta API |
打开服务器的 访问策略 选项卡。必须为您的应用(或所有客户端)分配一条策略,其中的规则允许 Code 授权 授权,并且 刷新令牌 (如果您使用了它)。缺少规则会导致“Policy evaluation failed for this request”错误。
Web 可信来源
如果您在 Web 上运行相同的 code,请在以下位置添加您的 Web 来源: 安全 > API > 可信来源 配合 CORS 已检查。如果没有它,浏览器会阻止 token 请求。
第 2 步:安装插件
bun add @capgo/capacitor-social-login
bunx cap sync
如果 Okta 是唯一的提供商,请在中关闭捆绑的社交 SDK capacitor.config.ts:
plugins: {
SocialLogin: {
providers: { google: false, facebook: false, apple: false, twitter: false },
},
},
步骤 3:添加 Android 重定向 intent filter
在 android/app/src/main/AndroidManifest.xml,位于 MainActivity activity 中:
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="com.example.app" android:host="oauth" />
</intent-filter>
MainActivity 必须保持 android:launchMode="singleTask",这是 Capacitor 的默认值,以便重定向到达正在运行的 activity。
步骤 4:初始化 Okta
import { Capacitor } from '@capacitor/core';
import { SocialLogin } from '@capgo/capacitor-social-login';
const OKTA_ISSUER = 'https://your-org.okta.com/oauth2/default';
const isWeb = Capacitor.getPlatform() === 'web';
export async function initAuth() {
await SocialLogin.initialize({
oauth2: {
okta: {
appId: 'YOUR_OKTA_CLIENT_ID',
authorizationBaseUrl: `${OKTA_ISSUER}/v1/authorize`,
accessTokenEndpoint: `${OKTA_ISSUER}/v1/token`,
resourceUrl: `${OKTA_ISSUER}/v1/userinfo`,
redirectUrl: isWeb
? 'https://app.example.com/auth/callback'
: 'com.example.app://oauth/okta',
scope: 'openid profile email offline_access',
pkceEnabled: true,
logoutUrl: `${OKTA_ISSUER}/v1/logout`,
postLogoutRedirectUrl: isWeb
? 'https://app.example.com/'
: 'com.example.app://oauth/logout',
androidUseCustomTabs: true,
},
},
});
}
更短的替代方案:设置 issuerUrl: OKTA_ISSUER 并移除 endpoint URL。插件将加载 /.well-known/openid-configuration 并自动填充。从 Ionic Auth Connect 迁移的团队可以使用 SocialLoginAuthConnect 配合 okta 预设(issuer, clientId, redirectUrl),详见 迁移指南.
第 5 步:登录并读取用户信息
import { SocialLogin } from '@capgo/capacitor-social-login';
export async function signInWithOkta() {
try {
const { result } = await SocialLogin.login({
provider: 'oauth2',
options: { providerId: 'okta' },
});
const profile = result.resourceData as {
sub: string;
email?: string;
name?: string;
preferred_username?: string;
} | null;
return {
accessToken: result.accessToken?.token,
idToken: result.idToken,
refreshToken: result.refreshToken,
scopes: result.scope,
profile,
};
} catch (error: any) {
if (error?.code === 'USER_CANCELLED') return null;
throw error;
}
}
resourceData 保存由 /userinfo 端点返回的 JSON,因此无需再次请求即可获取用户资料。若要读取 ID token 的 claims 用于展示,请使用 SocialLogin.decodeIdToken({ idToken })。该调用不会验证签名。
值得了解的登录选项:
loginHint自动填充用户名。prompt: 'login'即使 Okta 会话仍有效,也会强制重新认证。additionalParameters: { idp: '0oa...' }直接跳转到 Okta 中配置的指定身份提供商。
在 Web 端使用 flow: 'redirect',调用 SocialLogin.handleRedirectCallback() 在回调页完成交换。
第 6 步:在您的 API 上验证 Okta token
import { createRemoteJWKSet, jwtVerify } from 'jose';
const ISSUER = 'https://your-org.okta.com/oauth2/default';
const jwks = createRemoteJWKSet(new URL(`${ISSUER}/v1/keys`));
export async function verifyOktaAccessToken(token: string) {
const { payload } = await jwtVerify(token, jwks, {
issuer: ISSUER,
audience: 'api://default', // the Audience value of your authorization server
});
return payload; // payload.uid is the Okta user ID, payload.sub the login
}
在授权服务器的 设置 选项卡中找到 audience。请勿在您的 API 中验证来自组织授权服务器的 access token。Okta 不支持此操作。
步骤 7:刷新 token
import { SocialLogin } from '@capgo/capacitor-social-login';
export async function ensureFreshOktaToken() {
const { isLoggedIn } = await SocialLogin.isLoggedIn({ provider: 'oauth2', providerId: 'okta' });
if (!isLoggedIn) {
await SocialLogin.refresh({ provider: 'oauth2', options: { providerId: 'okta' } });
}
const { accessToken } = await SocialLogin.getAuthorizationCode({ provider: 'oauth2', providerId: 'okta' });
return accessToken;
}
如果 refresh token 已过期或被吊销, refresh 会拒绝请求。捕获该错误并将用户重定向回 signInWithOkta().
查看 刷新令牌 应用集成部分。使用 每次使用后轮换令牌,每次刷新都会返回一个新的刷新令牌,旧令牌在短暂的宽限期后失效。插件会自动替换其存储的副本。如果您自行持有刷新令牌(例如通过 Keychain 存储) @capgo/capacitor-native-biometric setData), 使用 SocialLogin.refreshToken({ provider: 'oauth2', providerId: 'okta', refreshToken }) 并保存返回的值。
第 8 步:退出登录
await SocialLogin.logout({ provider: 'oauth2', providerId: 'okta' });
该插件会清除已存储的 token,然后打开 /v1/logout 配合 id_token_hint 以及 post_logout_redirect_uri。Okta 会结束会话并重定向到你的注销 URI,该 URI 必须列在应用集成中。在移动端,注销页面会在系统浏览器中打开。
若要在服务端同时撤销 refresh token,请调用 Okta 的 /v1/revoke 端点(由你的后端或应用在退出登录前调用)。请参阅我们的 token 撤销指南 了解具体做法。
故障排除
| 错误 | 原因 | 修复 |
|---|---|---|
invalid_request: The 'redirect_uri' parameter must be a Login redirect URI in the client app settings |
重定向未注册 | 请将完整 URI 添加到 Sign-in redirect URIs |
User is not assigned to the client application |
缺少分配 | 请在 Assignments 中分配用户或组 |
Policy evaluation failed for this request |
该客户端或授权类型没有访问策略规则 | 请在授权服务器上添加策略和规则 |
invalid_client 在 token endpoint 处 |
应用类型为 Web 或 SPA,或认证方式不为 None | 请使用 client authentication 为 None 的 Native app |
| 缺少 Refresh Token | Refresh Token 授权已关闭, offline_access 缺失或被规则拦截 |
启用授权,添加 scope,并在规则中允许 |
| API 因 issuer 错误拒绝 Token | Token 来自组织服务器 | 使用自定义 Authorization Server 的 issuer |
Web:出现 CORS 错误 /v1/token |
Origin 不受信任 | 添加支持 CORS 的 Trusted Origin |
| Android 登录后仍停留在浏览器 | Intent filter 不匹配 | 将 scheme 和 host 匹配为 redirectUrl |
开启 logsEnabled: true 调试时在 provider 配置中开启,以便在 native logs 中查看 authorize URL 和 token 响应。
发布 Okta 变更
企业客户在上线后经常会更改策略或 claims。像 scopes、claim 处理或错误页面这类客户端变更,可以通过 Capgo 实时更新 发布,而无需经过完整的应用商店审核。但 native 部分(intent filter、新 scheme)仍需重新构建。