Google 登录集成教程(Web + Expo 移动端)
本教程适用于 Next.js 后端 + Expo 移动端的 Google OAuth 登录集成。

一、Google Cloud Console 配置
1.1 创建项目
- 访问 Google Cloud Console
- 点击"新建项目",输入项目名称后创建
1.2 配置 OAuth 同意屏幕
⚠️ 重要:必须先配置同意屏幕,否则无法创建 OAuth 客户端 ID
- 进入 API 和服务 → OAuth 同意屏幕
- 点击 “Get started” 按钮
- 填写 App Information:
- App name:填写你的应用名称
- User support email:选择你的邮箱
- 点击 “Next”
- Audience 页面直接点击 “Next”
- Contact Information 填写你的邮箱,点击 “Next”
- Finish 页面点击 “Create”
- 创建完成后,点击左侧 “Audience”,添加测试用户(你的邮箱)
1.3 创建 OAuth 客户端 ID
⚠️ 关键:需要创建 4 个不同的客户端 ID,分别用于 Web、Android、iOS 和 Expo Go 调试
进入 API 和服务 → 凭据 → 创建凭据 → OAuth 客户端 ID
A. Web 应用(后端用)
-
应用类型:Web 应用
-
已获授权的重定向 URI:
http://localhost:3000/api/auth/callback/google https://你的域名/api/auth/callback/google -
记录生成的 Client ID 和 Client Secret,后续配置到后端环境变量
B. Android 客户端
⚠️ 最容易出错的地方:必须使用正确的 SHA-1 指纹,且必须开启自定义 URI scheme
-
应用类型:Android
-
包名:填写你的 Android 包名(如
com.yourcompany.yourapp) -
SHA-1 证书指纹:
- 从 Expo EAS Dashboard 获取 → 进入项目 → Credentials → Android → Upload keystore → 复制 SHA-1 Fingerprint
- 格式示例:
42:DA:B6:72:B1:F1:0C:69:BA:13:73:E8:6E:8B:0B:F8:C0:A4:4C:6C
⚠️ 注意:
- 不要使用 debug.keystore 的指纹
- 如果重新生成 keystore,必须更新这里的指纹
-
创建后必须执行:
- 点击刚创建的 Android 客户端
- 点击 Advanced settings
- 开启 Enable custom URI scheme
⚠️ 必须开启:否则会报错
Custom URI scheme is not enabled for your Android client -
记录生成的 Client ID
C. iOS 客户端(如需要)
- 应用类型:iOS
- Bundle ID:填写你的 iOS Bundle ID(如
com.yourcompany.yourapp) - 记录生成的 Client ID
D. Expo Web / Proxy(仅用于 Expo Go 调试)
-
应用类型:Web 应用
-
已获授权的重定向 URI:
https://auth.expo.io/@你的expo用户名/你的项目slug💡 提示:在
app.json中查看owner和slug字段 -
记录生成的 Client ID 和 Client Secret
二、后端配置
2.1 环境变量配置
在后端项目的 .env 文件中添加:
# Web 应用凭据
GOOGLE_CLIENT_ID=你的Web客户端ID
GOOGLE_CLIENT_SECRET=你的Web客户端Secret# 移动端客户端 ID(用于验证 token)
GOOGLE_ANDROID_CLIENT_ID=你的Android客户端ID
GOOGLE_IOS_CLIENT_ID=你的iOS客户端ID
GOOGLE_EXPO_CLIENT_ID=你的Expo客户端ID
2.2 生产环境配置
如果使用 Vercel 部署:
- 进入项目设置 → Environment Variables
- 添加上述所有环境变量
三、移动端配置
3.1 环境变量配置
在移动端项目的 .env 文件中添加:
EXPO_PUBLIC_API_URL=http://10.0.2.2:3000
EXPO_PUBLIC_GOOGLE_ANDROID_CLIENT_ID="你的Android客户端ID"
EXPO_PUBLIC_GOOGLE_IOS_CLIENT_ID="你的iOS客户端ID"
EXPO_PUBLIC_GOOGLE_EXPO_CLIENT_ID="你的Expo客户端ID"
EXPO_PUBLIC_GOOGLE_WEB_CLIENT_ID="你的Expo客户端ID"
💡 提示:
10.0.2.2是 Android 模拟器访问本机的地址
3.2 app.json 配置
⚠️ 关键配置:必须正确配置 intentFilters,否则 Google 回调无法返回 App
{"expo": {"scheme": "yourappscheme","android": {"package": "com.yourcompany.yourapp","intentFilters": [{"action": "VIEW","category": ["BROWSABLE", "DEFAULT"],"data": [{"scheme": "com.googleusercontent.apps.你的Android客户端ID的数字部分","path": "/oauth2redirect"}]}]}}
}
💡 提示:
scheme的格式为com.googleusercontent.apps.+ Android Client ID 的数字部分(去掉.apps.googleusercontent.com)
3.3 登录页面代码
在 app/(auth)/sign-in.tsx 中:
import * as Google from "expo-auth-session/providers/google";
import { makeRedirectUri, ResponseType } from "expo-auth-session";
import Constants from "expo-constants";// 判断是否在 Expo Go 环境
const isExpoGo = Constants.appOwnership === "expo";// 配置 redirectUri
const redirectUri = useMemo(() => {if (isExpoGo) {// Expo Go 环境使用代理return makeRedirectUri({ useProxy: true, path: "oauthredirect" });}// Development Build / 正式包使用自定义 schemeconst googleScheme = "com.googleusercontent.apps.你的Android客户端ID的数字部分";return makeRedirectUri({scheme: googleScheme,path: "oauth2redirect",native: `${googleScheme}:/oauth2redirect`});
}, [isExpoGo]);// 配置 Google 登录
const [googleRequest, googleResponse, promptGoogleSignIn] = Google.useAuthRequest({expoClientId: isExpoGo ? expoClientId ?? undefined : undefined,androidClientId: Platform.OS === "android" ? androidClientId ?? undefined : undefined,iosClientId: Platform.OS === "ios" ? iosClientId ?? undefined : undefined,webClientId: webClientId ?? undefined,responseType: ResponseType.Code,usePKCE: true,shouldAutoExchangeCode: false,redirectUri,scopes: ["openid", "email", "profile"]
});// 处理登录响应
useEffect(() => {if (googleResponse?.type === "success") {const { code, codeVerifier } = googleResponse.params;// 发送到后端验证// ...}
}, [googleResponse]);
3.4 创建回调路由
⚠️ 必须创建:否则回调会落在 Unmatched Route 页面
创建 app/oauth2redirect.tsx:
import { useEffect } from "react";
import * as WebBrowser from "expo-web-browser";export default function OAuthRedirectScreen() {useEffect(() => {WebBrowser.maybeCompleteAuthSession();}, []);return null;
}
四、构建与验证
⚠️ 重要:Expo Go 无法测试 Google 登录,必须使用 Development Build
4.1 为什么需要 Development Build?
Expo Go 的回调 URL(exp://...)会被 Google Console 拒绝,因此必须构建真实的 APK/IPA 才能测试。
4.2 构建流程
-
生成 Development Build
eas build --profile development --platform android⏱️ 构建时间约 20 分钟,请耐心等待
-
删除旧版本 App
⚠️ 必须删除:否则新的 intentFilters 不会生效
在手机上卸载旧版本的 App
-
安装新构建的 APK
从 EAS Dashboard 下载 APK 并安装到手机
-
启动开发服务器
npx expo start --dev-client
4.3 验证配置
验证回调是否注册成功
adb shell cmd package resolve-activity \-d "com.googleusercontent.apps.你的Android客户端ID的数字部分:/oauth2redirect" \-a android.intent.action.VIEW
预期输出:应包含你的包名和 .MainActivity,例如:
com.yourcompany.yourapp/.MainActivity
如果未找到:说明安装的仍是旧 APK,请重新卸载并安装新版本
验证 APK 签名(可选)
$ANDROID_HOME/build-tools/36.0.0/apksigner verify --print-certs dev-client.apk
检查:SHA-1 digest 应与 Google Console 中登记的一致
五、授权流程说明
- 客户端使用
expo-auth-session/providers/google发起授权请求(responseType=code,PKCE 自动开启) - 用户在浏览器中选择 Google 账号
- Google 重定向到自定义 scheme:
- Development Build:
com.googleusercontent.apps.xxx:/oauth2redirect - Expo Go:
https://auth.expo.io/...
- Development Build:
- 客户端获取
authorizationCode和codeVerifier - 客户端将 code 和 verifier 发送给后端
- 后端使用对应的 Client ID 向 Google 交换
id_token - 后端验证 token 并创建会话
💡 提示:授权完成后浏览器不会自动关闭,可手动返回 App。关键是确认终端日志打印
Google auth response success
六、常见问题排查
| 现象 | 原因 | 解决方案 |
|---|---|---|
400 错误:redirect_uri 为 exp://... | 仍在 Expo Go 环境 | 使用 Development Build |
400 错误:Custom URI scheme is not enabled | Android 客户端未开启自定义 URI | 在 Google Console 中开启 Enable custom URI scheme |
| 浏览器完成登录但无回调 | intentFilters 未注册 | 使用 adb resolve-activity 检查;重新安装 Dev Client |
| 后端交换 token 失败 | 环境变量缺失或错误 | 检查 GOOGLE_*_CLIENT_ID 是否齐全且正确 |
| SHA-1 指纹不匹配 | 使用了错误的 keystore | 从 EAS Dashboard 获取正确的 SHA-1 并更新到 Google Console |
七、重要提醒
- Keystore 管理:如果重新生成 keystore,必须同步更新 Google Console 中的 SHA-1 指纹
- 环境变量同步:后端和移动端的 Client ID 必须一一对应
- 测试用户:开发阶段记得在 OAuth 同意屏幕中添加测试用户
- 回调验证:每次重新构建后,务必使用
adb resolve-activity验证回调是否注册成功
八、调试技巧
- 查看终端日志:确认是否打印
Google auth response success - 检查 redirectUri:在代码中打印
redirectUri确认格式正确 - 验证 Client ID:确认传递给
useAuthRequest的 Client ID 与平台匹配 - 测试回调:使用
adb shell am start手动触发回调测试
完成以上配置后,即可实现 Web 端和移动端的 Google 登录功能。
