跳转至正文

如何为 Capacitor App 添加身份验证(2026)

对比为 Capacitor 应用添加身份验证的所有方案:原生 Google/Apple 登录、OIDC SSO、Firebase、Supabase、Neon、Better Auth、passkeys 以及生物识别。

Capacitor 应用的登录界面,支持社交登录、SSO 和 passkey 登录

要在 Capacitor 应用中添加身份验证,请选择一个身份源(您自己的后端、Firebase、Supabase 或 Neon 等托管服务、Auth0、Okta 或 Entra ID 等 OIDC 提供商,或者 Better Auth 等自托管库),使用 native plugins 处理任何打开提供商登录页面的操作,在服务器上验证 token,并将生成的 session 存储在 Keychain 或 Keystore 中。随后,通过生物识别和 passkeys 可以实现快速二次登录。

本指南将每种常见选项映射到正确的 Capacitor plugin 和流程,并针对所有应用通用的部分(即登录调用、token 验证、session 存储和生物识别解锁)提供 code。内容已更新至 2026 年 10 月的 Capacitor 8 版本。下方链接了各提供商的具体分步指南。

每个 Capacitor 应用最终都会采用的身份验证流程

无论您选择哪个提供商,其核心逻辑都是一致的:

  1. 识别 用户:通过 native social sheet、系统浏览器中的提供商登录页、passkey prompt 或提交邮箱密码的表单。
  2. 获取凭证: 即 ID token、授权 code 或来自身份验证服务器的 session token。
  3. 在服务器端进行验证:验证签名、发行者、受众和有效期,然后创建或查找用户。
  4. 签发会话:使用你自己的 token 或提供商的 token,并制定刷新策略。
  5. 安全存储 在设备上,并将其附加到 API 调用中。
  6. 快速解锁 下次使用生物识别技术,并处理注销和账号删除。

步骤 1 和 2 会随提供商而异。除了完全托管的 BaaS(由 SDK 处理大部分工作)外,步骤 3 到 6 在所有方案中都是你的职责。

为什么 WebView 登录页面会失效

Capacitor 应用在 WKWebView (iOS) 或 Android WebView 中运行你的 Web code,并具有本地 Origin(capacitor://localhost 或 https://localhost)。在 WebView 中加载提供商的登录页面会导致三个问题:

  • Google 会返回 disallowed_useragent 并拒绝显示该页面。
  • 由于 App 无法证明该页面是真实的提供商,因此 RFC 8252 建议原生 App 使用系统浏览器。
  • 全页重定向会脱离你的 bundled app,并导致状态丢失。

因此,以下每种流程都会使用原生 SDK (Apple, Google, Facebook) 或系统浏览器会话(ASWebAuthenticationSession iOS 上为 Safari,Android 上为 Chrome Custom Tabs),并通过自定义 scheme 返回 App。

方案概览

方案 最适合 Capacitor 插件 后端工作 指南
通过 Apple 登录 任何集成第三方登录的 iOS App @capgo/capacitor-social-login 验证 ID token Apple 指南
Google 登录 消费者应用,Android 优先 @capgo/capacitor-social-login 验证 ID token Google 指南
Auth0 支持多种连接的托管登录 @capgo/capacitor-social-login (OAuth2) 验证 access token Auth0 指南
Okta 员工身份与 B2B SSO @capgo/capacitor-social-login (OAuth2) 验证 access token Okta 指南
Microsoft Entra ID Microsoft 365 组织 @capgo/capacitor-social-login (OAuth2) 验证 Access Token, Graph Entra ID 指南
更好的身份验证 自托管,自主掌控用户数据库 better-auth 客户端 + Social Login 运行 Better Auth 服务端 Better Auth 指南
Supabase Auth 内置身份验证的 Postgres 后端 社交登录 + supabase-js 极小 Supabase 指南
Neon Auth 集成托管 Better Auth 的 Neon Postgres @capgo/capacitor-neon 极小 Neon 插件文档
Firebase Authentication 已使用 Firebase 的应用 @capgo/capacitor-firebase-authentication 极小 Firebase 文档
Passkeys 在自有域名实现无密码登录 @capgo/capacitor-passkey WebAuthn 服务器 Passkey 文档
邮箱和密码 简单应用,自有后端 无 (HTTP) 哈希、重置、速率限制 本文

原生社交登录 (Apple, Google, Facebook)

一个插件即可覆盖三大主流消费级提供商,并内置通用 OAuth2 引擎:

bun add @capgo/capacitor-social-login
bunx cap sync
import { SocialLogin } from '@capgo/capacitor-social-login';

await SocialLogin.initialize({
  apple: { clientId: 'com.example.app' },
  google: {
    webClientId: 'WEB_CLIENT_ID.apps.googleusercontent.com',
    iOSClientId: 'IOS_CLIENT_ID.apps.googleusercontent.com',
  },
});

const { result } = await SocialLogin.login({ provider: 'google', options: {} });
// send result.idToken to your server

在以下设置中关闭不使用的提供商: capacitor.config.ts (plugins.SocialLogin.providers) 这样它们的 SDK 就不会被编译进 App 中。如果你不使用 Facebook,这还会移除 Facebook SDK 的广告 ID 权限。

每个 provider 都有原生配置:Apple 需要在 Xcode 中开启 Capability,并为 Android 配置 Services ID;Google 需要 SHA-1 指纹和反向的 Client ID URL scheme。这些 Apple 以及 Google 指南会讲解每个步骤和常见错误。

基于 OAuth 2.0 和 OpenID Connect 的企业 SSO

对于 Auth0、Okta、Microsoft Entra ID、Keycloak、Cognito、OneLogin 或你自己的 OIDC 服务器,请使用插件的 oauth2 provider。它通过 PKCE 运行授权 code 流程,在 ASWebAuthenticationSession iOS 上以及 Android 的 Custom Tabs 中,当你设置 androidUseCustomTabs: true:

await SocialLogin.initialize({
  oauth2: {
    corp: {
      issuerUrl: 'https://sso.example.com/realms/mobile', // OIDC discovery
      clientId: 'mobile-app',
      redirectUrl: 'com.example.app://oauth/corp',
      scope: 'openid profile email offline_access',
      pkceEnabled: true,
      androidUseCustomTabs: true,
    },
  },
});

const { result } = await SocialLogin.login({
  provider: 'oauth2',
  options: { providerId: 'corp' },
});

你可以在同一个 map 中注册多个 provider,并选择其中一个 providerId,这正是多租户 B2B 应用让每个客户自带 IdP 的方式。该插件还会处理刷新 (SocialLogin.refresh), 并支持注销: id_token_hint以及兼容 Ionic Auth Connect 的封装层 (SocialLoginAuthConnect),方便从 Auth Connect 迁移的团队。各服务商指南: Auth0, Okta, Entra ID。关于协议背景,请参阅 在 Capacitor 应用中实现 OAuth2 的 5 个步骤.

托管后端:Firebase、Supabase 和 Neon

如果你的数据已存储在 Firebase、Supabase 或 Neon 中,请直接使用它们的 auth,这样无需额外开发即可实现安全规则和行级安全性(RLS)。

  • Supabase:通过 Social Login 插件获取 ID token 并调用 supabase.auth.signInWithIdToken({ provider: 'google', token })。Supabase 会验证该 token 并返回 session。完整配置如下: 使用 Capacitor Social Login 的 Supabase.
  • Neon: Neon Auth 是运行在你的 Neon 分支上的托管版 Better Auth。 @capgo/capacitor-neon 支持通过系统浏览器使用邮箱密码、邮箱 OTP、Google、GitHub 或 Vercel 进行原生登录。它会返回一个用于 Neon Data API 的 JWT,因此行级安全性(row-level security)同样适用。完整配置如下: Neon 插件文档.
  • Firebase:你可以选择使用 @capgo/capacitor-firebase-authentication,它封装了原生的 Firebase Auth SDK;或者通过 Social Login 获取 ID token,然后在 JS SDK 中据此创建 Firebase 凭据。详情请参阅 Firebase Google 登录文档.

自托管:Better Auth

Better Auth 是一个开源的 TypeScript 认证库,可将用户信息存储在您自己的数据库中。在您信任应用 origin 并切换到 Bearer Token 后,它即可在 Capacitor 中正常工作,因为跨站 Cookie 在 WKWebView 中并不稳定。社交登录通过原生 plugin 和 ID token 交接完成。具体步骤如下: 如何在 Capacitor 应用中使用 Better Auth.

Passkeys

Passkeys 使用存储在 iCloud Keychain 或 Google Password Manager 中的密钥对来取代密码。这需要您的应用与您的网站域名相关联(apple-app-site-association 在 iOS 上, assetlinks.json 在 Android 上)以及一个 WebAuthn 服务器。

@capgo/capacitor-passkey 让您可以保留标准 WebAuthn code。Relying Party 配置在 capacitor.config.ts,在启动时调用一次 shim,然后 navigator.credentials.create() 以及 .get() 会被路由到原生 Passkey API:

import { CapacitorPasskey } from '@capgo/capacitor-passkey';

await CapacitorPasskey.autoShimWebAuthn();

// existing WebAuthn code keeps working
const assertion = await navigator.credentials.get({
  publicKey: requestOptionsFromServer,
});

像 Better Auth 这样的库,以及 Auth0 和 Okta 等托管服务商,都可以充当 WebAuthn 服务器。请参阅 passkey 插件页面.

使用自有后端实现邮箱和密码登录

无需插件,只需 fetch即可实现。工作量主要在服务端:使用 Argon2id 或 bcrypt 进行哈希处理、限制登录尝试频率、发送验证和重置邮件,并支持账号注销。通过 Universal Links 和 App Links 在 App 内打开重置和验证链接,确保链接能准确跳转到手机上的对应位置。除非你有必要完全自主掌控这些逻辑,否则使用 Better Auth 这样的库或托管服务可以在降低风险的同时获得相同的功能。

务必在服务端验证 token

客户端检查可以被绕过。无论使用哪种服务商,服务端在创建 session 之前都必须验证 token:

import { createRemoteJWKSet, jwtVerify } from 'jose';

type IssuerConfig = {
  jwks: ReturnType<typeof createRemoteJWKSet>;
  issuer: string | string[];
  audience: string[];
};

const issuers: Record<'google' | 'apple', IssuerConfig> = {
  google: {
    jwks: createRemoteJWKSet(new URL('https://www.googleapis.com/oauth2/v3/certs')),
    issuer: ['https://accounts.google.com', 'accounts.google.com'],
    audience: ['WEB_CLIENT_ID.apps.googleusercontent.com', 'IOS_CLIENT_ID.apps.googleusercontent.com'],
  },
  apple: {
    jwks: createRemoteJWKSet(new URL('https://appleid.apple.com/auth/keys')),
    issuer: 'https://appleid.apple.com',
    audience: ['com.example.app', 'com.example.app.signin'],
  },
};

export async function verifyIdToken(provider: 'google' | 'apple', idToken: string) {
  const cfg = issuers[provider];
  const { payload } = await jwtVerify(idToken, cfg.jwks, {
    issuer: cfg.issuer,
    audience: cfg.audience,
  });
  return payload; // use payload.sub as the stable provider user ID
}

服务商侧的关键用户标识 sub (加上服务商名称),而非邮箱。仅在服务商将其标记为已验证时,才通过邮箱进行账号绑定 (email_verified: true)。Meta 的 Limited Login token 不包含该声明。

请安全地存储会话

localStorage 且 Capacitor Preferences 仅为普通文件。请将长期有效的 token 存放在 Keychain (iOS) 或经过 Keystore 加密的存储中 (Android)。 @capgo/capacitor-native-biometric 有简单的 setData, getData 以及 deleteData 实现方法:

bun add @capgo/capacitor-native-biometric
bunx cap sync
import { NativeBiometric } from '@capgo/capacitor-native-biometric';

export const sessionStore = {
  async save(token: string) {
    await NativeBiometric.setData({ key: 'session.token', value: token });
  },
  async load(): Promise<string | null> {
    try {
      const { value } = await NativeBiometric.getData({ key: 'session.token' });
      return value;
    } catch {
      return null;
    }
  },
  async clear() {
    await NativeBiometric.deleteData({ key: 'session.token' }).catch(() => {});
  },
};

让 access token 保持短期有效,并通过 refresh token 或服务端 session 刷新。我们的 安全 Token 存储指南 更深入地介绍轮换和撤销。

生物识别:用于解锁,而非身份

Face ID 和指纹只能证明拿着手机的人能解锁设备。用它们来控制对已存储 session 的访问:

import { AccessControl, NativeBiometric } from '@capgo/capacitor-native-biometric';

// after a real login, offer biometric unlock
await NativeBiometric.setData({
  key: 'session.refresh',
  value: refreshToken,
  accessControl: AccessControl.BIOMETRY_ANY,
});

// next app start
const { value } = await NativeBiometric.getSecureData({
  key: 'session.refresh',
  reason: 'Unlock your account',
});
// exchange `value` with your server for a fresh access token

使用 accessControl 设置后,只有在生物识别检查成功后,OS 才会释放该值,因此保护由 Keychain 或 Keystore 强制执行,而非 JavaScript。配合服务端 session 过期机制使用;对于高风险应用,还应加入 root 和越狱检测。更多内容见 Capacitor 应用中的生物识别认证.

选择分发方式

如果你… 使用
在 iOS 和 Android 上发布面向消费者的 App 通过 Social Login 接入 Apple + Google,外加邮箱或 passkeys
面向使用 Microsoft 365 的企业销售 通过 OAuth2 provider 接入 Entra ID
每个客户都需要对接多个企业级 IdP 使用 Auth0 或 Okta 作为 broker,或通过多个 OAuth2 provider providerId
已经在用 Supabase 或 Firebase 使用其 Auth,通过原生 ID token 登录
已经在用 Neon Neon Auth 接入 @capgo/capacitor-neon
想自己掌控用户表,不依赖第三方供应商 更好的身份验证
想要无密码登录 Passkeys,并提供邮件 magic link 等回退方式
需要快速重新登录 在上述任一方案基础上,通过生物识别解锁已保存的 Session

影响登录的 App Store 和 Play Store 规则

  • Apple 4.8 登录服务:将第三方登录作为主要账号系统时,必须提供同等的隐私保护选项。Sign in with Apple 即可满足。
  • Apple 5.1.1(v):创建账号时必须支持应用内账号注销,且应撤销 Sign in with Apple 的 token。请参阅 账号注销合规性.
  • Google Play 账号注销: 带有账号功能的 App 必须在 App 内及 Play Console 声明的网页链接中提供注销选项。
  • 审核人员访问权限: 为审核人员提供可用的演示账号。如果仅支持 SSO 登录,请提供一个测试租户用户。
  • Xcode 26: 自 2026 年 4 月起,App Store Connect 要求使用 Xcode 26 和 iOS 26 SDK 进行构建,因此在提交新增身份验证功能的版本前请务必更新。

安全发布身份验证变更

Auth bugs block every user, so you want to fix them fast. Native changes (entitlements, URL schemes, intent filters) need a store build. Everything in TypeScript, like provider config, scopes, error handling and UI, can be pushed with Capgo 实时更新 并在出现问题时进行回滚。 Capgo 构建 当确实需要发布新的 Native Build 时,可以在云端生成已签名的 iOS 和 Android 二进制文件。

后续步骤

选择您的 provider 并参考相应的指南:

为 Capacitor 应用提供 Live Updates

当 Web 层出现线上 Bug 时,通过 Capgo 发布修复,而不用等 App Store 审核好几天。用户会在后台收到更新,原生变更则仍走正常审核流程。

博客最新动态

Capgo 为你提供打造真正专业的移动应用所需的最有价值的洞察。