要在 Capacitor 应用中添加 Google 登录,请在 Google Cloud 中创建一个 Web、一个 iOS 以及一个或多个 Android OAuth 客户端 ID,然后安装 @capgo/capacitor-social-login,调用 SocialLogin.initialize({ google: { webClientId, iOSClientId } }),然后 SocialLogin.login({ provider: 'google' }). Android 使用 Google 的 Credential Manager,iOS 使用 Google Sign-In SDK,Web 端则使用 Google Identity Services。这三种方式都会返回一个 ID token,由你在服务器端验证。
本指南逐步讲解 2026 年 10 月 Capacitor 8 的每个步骤,包括最容易出错的部分:SHA-1 指纹、Play App Signing 密钥以及 iOS URL scheme。
Google Sign-In 在 Capacitor 应用中的工作原理
| 平台 | 插件使用的原生 API | 传递给插件的 Client ID | 其他控制台设置 |
|---|---|---|---|
| Android | 凭据管理器 (androidx.credentials) |
Web client ID 填为 webClientId |
包含包名和 SHA-1 的 Android client |
| iOS | 使用 SDK 实现 Google Sign-In | iOS client ID 填为 iOSClientId |
反向客户端 ID URL scheme 位于 Info.plist |
| Web 端 | Google Identity Services | Web client ID 填为 webClientId |
已获授权的 JavaScript 来源 |
Google 会通过以下错误拦截嵌入式 WebView 中的 OAuth: disallowed_useragent 错误,所以在 Capacitor WebView 中加载 Google 登录页行不通。该插件改用原生账号选择器。
第 1 步:配置 Google Cloud
创建项目和 Google Auth Platform
- 打开 Google Cloud Console 并创建一个项目,或选择一个现有项目。所有客户端 ID 必须位于同一项目中。
- 打开 Google 身份验证平台 (即原“OAuth 同意屏幕”)。
- 在 品牌信息,设置用户可见的应用名称、支持邮箱,以及您的域名和隐私政策 URL。
- 在 受众,选择 外部 适用于面向消费者的应用。当应用处于 测试时,只有列在 测试用户 可以登录。
- 在 数据访问,保留默认
openid,email以及profile权限,除非需要更多。
基本权限无需发布到生产环境或通过验证。敏感权限(日历、Drive、Gmail)在公开发布前需要通过验证。
创建 Client ID
前往 Google Auth Platform > 客户端 (或 API 和服务 > 凭据) 并创建:
| 客户端类型 | 填写内容 | ID 填写位置 |
|---|---|---|
| Web 应用 | Web build 的已授权 JavaScript 来源(例如 https://app.example.com, http://localhost:5173) |
webClientId |
| iOS | 您的 Bundle ID,以及获取后的 App Store ID 和 Team ID | iOSClientId |
| Android(调试) | 包名及调试 SHA-1 | 仅限控制台 |
| Android(release) | 包名加上传密钥 SHA-1 | 仅限控制台 |
| Android (Play) | 包名加 Play 应用签名 SHA-1 | 仅限控制台 |
获取 SHA-1 值:
# Debug key and any signing config in build.gradle
cd android && ./gradlew signingReport
# From a signed APK you actually install
keytool -printcert -jarfile android/app/build/outputs/apk/release/app-release.apk
对于 Play Store 构建,从以下位置复制 SHA-1: Play Console > 测试和发布 > 应用完整性 > 应用签名密钥证书。如果你先需要一个 release keystore, Android keystore 生成器 会在浏览器中生成一个。我们的 Google client ID 指南 会更深入地讲解控制台界面。
第 2 步:安装插件
bun add @capgo/capacitor-social-login
bunx cap sync
禁用你不使用的 provider,让它们的 SDK 不会被打进 binary:
// capacitor.config.ts
import type { CapacitorConfig } from '@capacitor/cli';
const config: CapacitorConfig = {
appId: 'com.example.app',
appName: 'Example',
webDir: 'dist',
plugins: {
SocialLogin: {
providers: {
google: true,
apple: true,
facebook: false,
twitter: false,
},
},
},
};
export default config;
运行 bunx cap sync 更改 provider 后。
第 3 步:iOS 配置
添加反向 client ID 的 URL scheme
在 Google Cloud 中打开 iOS 客户端并复制 iOS URL scheme,格式类似 com.googleusercontent.apps.1234567890-abcdef。将其添加到 ios/App/App/Info.plist 在结束标签之前 </dict>:
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLSchemes</key>
<array>
<string>com.googleusercontent.apps.1234567890-abcdef</string>
</array>
</dict>
</array>
如果你已经有 CFBundleURLTypes 用于 deep links 的数组,请添加一个新 <dict> 条目,而不是创建第二个键。
让 Google SDK 处理回调 URL
在 ios/App/App/AppDelegate.swift,导入 SDK,并在 Capacitor 之前将 URL 路由给它:
import GoogleSignIn // add at the top of the file
// Replace the generated application(_:open:options:) method
func application(_ app: UIApplication, open url: URL,
options: [UIApplication.OpenURLOptionsKey: Any] = [:]) -> Bool {
if GIDSignIn.sharedInstance.handle(url) {
return true
}
return ApplicationDelegateProxy.shared.application(app, open: url, options: options)
}
保留这种 ApplicationDelegateProxy 调用,因此 @capacitor/app 仍会接收其他深度链接。
步骤 4:Android 配置
使用默认作用域的基础登录无需原生代码修改。如果你请求 额外权限范围 或使用 离线模式,插件需要接收 activity 结果,因此 MainActivity 必须实现该插件的标记接口:
package com.example.app;
import android.content.Intent;
import com.getcapacitor.BridgeActivity;
import com.getcapacitor.Plugin;
import com.getcapacitor.PluginHandle;
import ee.forgr.capacitor.social.login.GoogleProvider;
import ee.forgr.capacitor.social.login.ModifiedMainActivityForSocialLoginPlugin;
import ee.forgr.capacitor.social.login.SocialLoginPlugin;
public class MainActivity extends BridgeActivity implements ModifiedMainActivityForSocialLoginPlugin {
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode >= GoogleProvider.REQUEST_AUTHORIZE_GOOGLE_MIN
&& requestCode < GoogleProvider.REQUEST_AUTHORIZE_GOOGLE_MAX) {
PluginHandle handle = getBridge().getPlugin("SocialLogin");
if (handle == null) return;
Plugin plugin = handle.getInstance();
if (plugin instanceof SocialLoginPlugin) {
((SocialLoginPlugin) plugin).handleGoogleLoginIntent(requestCode, data);
}
}
}
@Override
public void IHaveModifiedTheMainActivityForTheUseWithSocialLoginPlugin() {}
}
如果没有它,带有 scopes 的调用将被拒绝,并提示“您无法在未修改主 activity 的情况下使用权限范围”。
对于模拟器,请使用包含 Google Play 标签的系统镜像,并在设备设置中登录 Google 账户。不包含 Play 服务的镜像将返回 NoCredentialException.
步骤 5:Web 配置
将提供 Web 构建的所有源添加到 Web 客户端的 已获授权的 JavaScript 来源,包括端口(http://localhost:5173)。调用 initialize 要尽早执行:该插件会注入 Google 的 script 标签,如果在脚本就绪前运行,登录将会失败。
步骤 6:初始化并登录
import { SocialLogin } from '@capgo/capacitor-social-login';
const WEB_CLIENT_ID = '1234567890-web.apps.googleusercontent.com';
const IOS_CLIENT_ID = '1234567890-ios.apps.googleusercontent.com';
export async function initAuth() {
await SocialLogin.initialize({
google: {
webClientId: WEB_CLIENT_ID, // Android + web
iOSClientId: IOS_CLIENT_ID, // iOS
iOSServerClientId: WEB_CLIENT_ID, // same as webClientId, required for offline mode on iOS
mode: 'online',
},
});
}
export async function signInWithGoogle() {
try {
const { result } = await SocialLogin.login({
provider: 'google',
options: {},
});
if (result.responseType !== 'online' || !result.idToken) {
throw new Error('Expected an ID token from Google');
}
const res = await fetch('https://api.example.com/auth/google', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ idToken: result.idToken }),
});
return res.json();
} catch (error: any) {
if (error?.code === 'USER_CANCELLED') return null;
throw error;
}
}
在线响应包含:
| 字段 | 备注 |
|---|---|
idToken |
OpenID Connect JWT。把它发送到你的服务器 |
accessToken |
用于从客户端调用 Google APIs。可以是 null 在 Android 上,当仅请求默认作用域时 |
profile |
email, name, givenName, familyName, imageUrl, id |
responseType |
'online' |
仅限 Android 的显示选项
本指南中介绍的 options 对象接受 style: 'bottom' 用于 bottom sheet UI,以及 filterByAuthorizedAccounts 以及 autoSelectEnabled 用于回访用户。请 filterByAuthorizedAccounts 在支持 Family Link 账号时保持关闭。 forceRefreshToken: true 向 Android 请求新的 access token,而不是缓存的 token。
请求额外的 scopes
const { result } = await SocialLogin.login({
provider: 'google',
options: {
scopes: ['https://www.googleapis.com/auth/calendar.readonly'],
},
});
记住 MainActivity 在 Android 上的更改,并在 数据访问 Google Cloud 中添加该 scope。
在线与离线模式
| 在线(默认) | 离线 | |
|---|---|---|
| 返回 | ID token、access token、profile | serverAuthCode 仅 |
| 需要后端 | 仅用于验证 token | 是,用于交换 code |
| Google 刷新令牌 | 保留在 Google SDK 的设备上 | 存储在你的服务器上 |
| 适用场景 | 你只需要知道用户是谁 | 用户离开时,你的服务器调用 Google API |
logout, isLoggedIn, refresh |
支持 | 暂不支持 |
iOS 上的离线模式需要 iOSServerClientId,而在 Android 上则需要 MainActivity 更改。
注销与会话检查
await SocialLogin.isLoggedIn({ provider: 'google' }); // { isLoggedIn: boolean }
await SocialLogin.logout({ provider: 'google' });
在 Android 上, logout 还会清除 Credential Manager 状态,因此下次会再次弹出账号选择器。
第 7 步:在您的服务器上验证 ID token
import { OAuth2Client } from 'google-auth-library';
const client = new OAuth2Client();
export async function verifyGoogleToken(idToken: string) {
const ticket = await client.verifyIdToken({
idToken,
audience: [
'1234567890-web.apps.googleusercontent.com',
'1234567890-ios.apps.googleusercontent.com',
],
});
const payload = ticket.getPayload();
if (!payload) throw new Error('Empty token payload');
return {
googleUserId: payload.sub,
email: payload.email,
emailVerified: payload.email_verified === true,
name: payload.name,
};
}
使用 sub 作为稳定的用户标识。仅当满足以下条件时,才通过电子邮件关联现有账号: email_verified 为 true。同时接受两个 client ID 作为 audience 可以确保来自所有平台的 token 均有效。然后签发您自己的 session。如果您使用托管后端,请遵循 使用 Capacitor Social Login 的 Supabase 或 Firebase Google 指南. Neon Auth 通过 OAuth 重定向处理 Google 登录, @capgo/capacitor-neon 原生运行。
故障排除
| 错误 | 原因 | 修复 |
|---|---|---|
[28444] Developer console is not set up correctly |
包名、SHA-1 或 webClientId 不匹配 |
使用 Web 客户端 ID,注册已安装 build 的 SHA-1,所有客户端保留在同一项目中 |
| debug 下正常,从 Play Store 安装后失败 | Play 会重新签名应用 | 添加使用 Play App Signing SHA-1 的 Android 客户端 |
[16] Account reauth failed |
缓存的账号状态已过期、账号不是测试用户,或用户已停用应用 | 插件会自动重试一次。请检查测试用户、外部受众和 Play signing SHA-1 |
NoCredentialException |
设备上没有 Google 账号,或模拟器没有 Play services | 使用 Google Play 系统镜像并登录 |
USER_CANCELLED 选择账号后立即执行 |
通常还是 SHA-1 或 client ID 不匹配 | 在把它当成真正的取消之前,先修复控制台配置 |
| iOS 崩溃:“缺少对以下 URL scheme 的支持” | 缺少反转后的 client ID Info.plist |
添加 com.googleusercontent.apps... scheme |
| Web:“指定的 origin 不允许用于指定的 client ID” | Web 客户端缺少 Origin | 添加准确的 origin,包括端口号 |
access_denied 提示“应用尚未完成 Google 验证流程” |
处于 Testing 模式时,账号不是测试用户 | 在 Audience > Test users 下添加 |
| iOS 上的 Google 登录界面被中断 | @capacitor/privacy-screen 覆盖了 SDK 视图 |
调用 PrivacyScreen.disable() 在……之前 login |
在 Android 上,通过 Logcat 过滤 GoogleProvider。该插件会记录包名、签名 SHA-1 以及脱敏后的 webClientId,稍后你可以拿它和控制台对比。
发布与维护
控制台更改可能需要几个小时才能生效,因此请勿在发布当天轮换客户端 ID。一旦原生配置已包含在商店构建中,诸如 scopes、错误处理或后端 URL 等客户端更改即可通过 Capgo 实时更新。如果你的团队没有用于 iOS 发布的 Mac, Capgo 构建 在云端构建并签名 iOS 二进制文件。
相关指南
- 如何使用 Capacitor 通过 Apple 登录,如果 Google 是你的主要登录方式,在 iOS 上就会需要它。
- 如何在 Capacitor 应用中添加身份验证 用于在社交登录、OIDC、passkeys 和 Better Auth 之间做选择。
- Social Login 插件页面 以及 Google Android 配置文档.