Google 登录集成教程(Web + Expo 移动端)

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


一、Google Cloud Console 配置

1.1 创建项目

  1. 访问 Google Cloud Console
  2. 点击"新建项目",输入项目名称后创建

1.2 配置 OAuth 同意屏幕

⚠️ 重要:必须先配置同意屏幕,否则无法创建 OAuth 客户端 ID

  1. 进入 API 和服务OAuth 同意屏幕
  2. 点击 "Get started" 按钮
  3. 填写 App Information
    • App name:填写你的应用名称
    • User support email:选择你的邮箱
  4. 点击 "Next"
  5. Audience 页面直接点击 "Next"
  6. Contact Information 填写你的邮箱,点击 "Next"
  7. Finish 页面点击 "Create"
  8. 创建完成后,点击左侧 "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 IDClient Secret,后续配置到后端环境变量

B. Android 客户端

⚠️ 最容易出错的地方:必须使用正确的 SHA-1 指纹,且必须开启自定义 URI scheme

  • 应用类型:Android

  • 包名 :填写你的 Android 包名(如 com.yourcompany.yourapp

  • SHA-1 证书指纹

    • Expo EAS Dashboard 获取 → 进入项目 → CredentialsAndroidUpload 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,必须更新这里的指纹
  • 创建后必须执行

    1. 点击刚创建的 Android 客户端
    2. 点击 Advanced settings
    3. 开启 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 中查看 ownerslug 字段

  • 记录生成的 Client IDClient Secret


二、后端配置

2.1 环境变量配置

在后端项目的 .env 文件中添加:

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 部署:

  1. 进入项目设置 → Environment Variables
  2. 添加上述所有环境变量

三、移动端配置

3.1 环境变量配置

在移动端项目的 .env 文件中添加:

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

json 复制代码
{
  "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 中:

typescript 复制代码
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 / 正式包使用自定义 scheme
  const 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

typescript 复制代码
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 构建流程

  1. 生成 Development Build

    bash 复制代码
    eas build --profile development --platform android

    ⏱️ 构建时间约 20 分钟,请耐心等待

  2. 删除旧版本 App

    ⚠️ 必须删除:否则新的 intentFilters 不会生效

    在手机上卸载旧版本的 App

  3. 安装新构建的 APK

    从 EAS Dashboard 下载 APK 并安装到手机

  4. 启动开发服务器

    bash 复制代码
    npx expo start --dev-client

4.3 验证配置

验证回调是否注册成功
bash 复制代码
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 签名(可选)
bash 复制代码
$ANDROID_HOME/build-tools/36.0.0/apksigner verify --print-certs dev-client.apk

检查SHA-1 digest 应与 Google Console 中登记的一致


五、授权流程说明

  1. 客户端使用 expo-auth-session/providers/google 发起授权请求(responseType=code,PKCE 自动开启)
  2. 用户在浏览器中选择 Google 账号
  3. Google 重定向到自定义 scheme:
    • Development Build:com.googleusercontent.apps.xxx:/oauth2redirect
    • Expo Go:https://auth.expo.io/...
  4. 客户端获取 authorizationCodecodeVerifier
  5. 客户端将 code 和 verifier 发送给后端
  6. 后端使用对应的 Client ID 向 Google 交换 id_token
  7. 后端验证 token 并创建会话

💡 提示:授权完成后浏览器不会自动关闭,可手动返回 App。关键是确认终端日志打印 Google auth response success


六、常见问题排查

现象 原因 解决方案
400 错误:redirect_uriexp://... 仍在 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

七、重要提醒

  1. Keystore 管理:如果重新生成 keystore,必须同步更新 Google Console 中的 SHA-1 指纹
  2. 环境变量同步:后端和移动端的 Client ID 必须一一对应
  3. 测试用户:开发阶段记得在 OAuth 同意屏幕中添加测试用户
  4. 回调验证 :每次重新构建后,务必使用 adb resolve-activity 验证回调是否注册成功

八、调试技巧

  1. 查看终端日志 :确认是否打印 Google auth response success
  2. 检查 redirectUri :在代码中打印 redirectUri 确认格式正确
  3. 验证 Client ID :确认传递给 useAuthRequest 的 Client ID 与平台匹配
  4. 测试回调 :使用 adb shell am start 手动触发回调测试

完成以上配置后,即可实现 Web 端和移动端的 Google 登录功能。

相关推荐
雨落秋垣3 分钟前
在前端把图片自动转换为 WebP 格式
前端
羽沢315 分钟前
一些css属性学习
前端·css·学习
二狗哈19 分钟前
Cesium快速入门22:fabric自定义着色器
运维·开发语言·前端·webgl·fabric·cesium·着色器
计算衎20 分钟前
FastAPI后端和VUE前端的数据交互原理详解
前端·vue.js·fastapi
黑岚樱梦21 分钟前
Linux系统编程
java·开发语言·前端
xrl201222 分钟前
ruoyi-vue2前端集成DMN规则引擎
前端·规则引擎·工作流·dmn
转转技术团队22 分钟前
前端工程化实践:打包工具的选择与思考
前端·javascript·webpack
前端郭德纲30 分钟前
React 19.2 已发布,现已上线 npm!
前端·react.js·npm
知其然亦知其所以然34 分钟前
JavaScript 变量的江湖恩怨:一篇文章彻底讲清楚
前端·javascript·面试
小番茄夫斯基36 分钟前
使用 pnpm + Workspaces 构建 Monorepo 的完整指南
前端·javascript·vue.js