hyapp-server/docs/google-login-integration.md
2026-04-30 02:30:32 +08:00

8.6 KiB
Raw Blame History

Firebase Google 登录接入流程

本文档对应当前 Flutter Android 测试 App 和后端登录契约。Google 登录由 Firebase Auth 承接;后端不接收 Google account id不把 Google 资料字段当身份凭证,只接收 Firebase ID token。

当前目标包名:

com.org.laluparty

当前项目状态

已接入:

  • Android applicationId: com.org.laluparty
  • Android namespace: com.org.laluparty
  • Firebase Android App 配置文件:android/app/google-services.json
  • Firebase Authentication Google Sign-In
  • google_sign_in: 7.2.0
  • google_sign_in_android: 7.2.10
  • android/settings.gradle.kts 已声明 com.google.gms.google-services
  • android/app/build.gradle.kts 已应用 com.google.gms.google-services

当前 google-services.json 包含:

package_name: com.org.laluparty
web client_id: 821303287694-o0g9nugq6fglssugri1ls4auud549rll.apps.googleusercontent.com

Firebase 控制台配置

  1. 进入 Firebase Console选择项目。

  2. 添加 Android App。

    Android package name 填:

    com.org.laluparty
    
  3. 添加 debug 证书指纹。

    当前本机 debug keystore

    SHA1: C2:F0:20:54:81:57:F4:D1:55:1E:21:98:08:22:69:E1:F6:4A:92:CA
    SHA-256: F5:91:FC:90:F8:17:26:24:67:2E:FF:77:AA:AE:12:42:21:B4:A8:50:E2:E3:00:B8:BE:DE:B7:D3:1E:0A:D2:28
    

    重新查询命令:

    cd /Users/zuozuo/Desktop/HY/hyapp-flutter/android
    ./gradlew signingReport
    
  4. 启用 Google 登录。

    Firebase Console:

    Authentication -> Sign-in method -> Google -> Enable
    

    需要选择项目支持邮箱。

  5. 重新下载 google-services.json

    添加 SHA 指纹或启用 Google 登录后,都建议重新下载一次。

    放置路径:

    /Users/zuozuo/Desktop/HY/hyapp-flutter/android/app/google-services.json
    
  6. 确认 google-services.json 里有 Web OAuth Client。

    检查命令:

    jq -r '.client[] | .client_info.android_client_info.package_name as $pkg | [$pkg, (.oauth_client[]? | select(.client_type==3) | .client_id)] | @tsv' android/app/google-services.json
    

    必须能看到 client_type: 3 对应的 Web client id。google_sign_in_android 会用它做 Android 登录配置。

Google Cloud 侧配置

Firebase 通常会自动创建 OAuth 客户端。需要确认:

  • Android OAuth client 的包名是 com.org.laluparty
  • Android OAuth client 里有当前 debug SHA1
  • Web OAuth client 存在
  • OAuth consent screen 已配置

如果以后要调用 People API、Drive API 等 Google API再去 Google Cloud API Library 单独启用;当前只做登录不需要额外 API。

Flutter 代码接入

当前登录入口:

lib/src/pages/login_page.dart

Google 登录封装:

lib/src/google_auth_service.dart

当前初始化方式:

GoogleSignIn.instance.initialize(
  clientId: AppConfig.googleClientId,
  serverClientId: AppConfig.googleServerClientId,
);

Android 已接入 google-services.json 时,可以不传 GOOGLE_SERVER_CLIENT_ID。如果不使用 google-services.json,运行时必须传 Web client id

flutter run -d emulator-5554 \
  --dart-define=GOOGLE_SERVER_CLIENT_ID=你的Web客户端ID

后端登录请求

Flutter 侧必须先完成 Firebase Auth 登录,再从 Firebase 当前用户获取 ID token。后端登录只认 Firebase ID token

POST /api/v1/auth/third-party/login

请求字段:

{
  "provider": "firebase",
  "credential": "Firebase ID token",
  "username": "optional Firebase display name snapshot",
  "avatar": "optional Firebase photo url snapshot",
  "device_id": "local device id",
  "device": "flutter-android",
  "source": "hyapp-flutter",
  "platform": "android"
}

username/avatar 在这个接口里只允许作为 Firebase 当次返回的资料快照,不代表注册完成。注册页的权威提交入口仍然是:

POST /api/v1/users/me/onboarding/complete

注册页只提交用户主动确认的 username/avatar/countrydevice_id/platform/device/source 是客户端自动上报的注册上下文,不需要用户填写。

后端校验规则

后端 user-service 必须使用 Firebase verifier 校验 ID token。StaticThirdPartyVerifier 只能用于单元测试或显式 mock provider不能用于 provider=firebase

Item Rule
provider 固定传 firebase,并出现在 user-service allowlist
credential Firebase Auth 当前用户的 ID token不能是 Google account id、email 或 access token
provider_subject 从校验后的 Firebase token sub/uid 提取,作为 third_party_identities(provider, provider_subject) 的绑定主键
iss 必须是 https://securetoken.google.com/<firebase_project_id>
aud 必须等于后端配置的 Firebase project id
signature 使用 Firebase Admin SDK 或 Firebase 公钥校验,不能跳过签名
firebase.sign_in_provider 首版 Google 登录必须等于 google.com;后续支持 Apple/phone 时改成配置 allowlist
email/name/picture 只作为资料快照辅助字段,不能作为登录绑定主键

Firebase ID token、Google access token、provider 原始 credential 都不能写入日志、审计表或数据库。gateway 只负责 HTTP JSON 到 gRPC 的转发和 request_id 透传,不保存 Firebase service account。

Android 运行验证

启动 Google 手机模拟器:

/Users/zuozuo/Library/Android/sdk/emulator/emulator -avd Pixel_8_API_35

确认设备在线:

adb devices -l

运行 App

cd /Users/zuozuo/Desktop/HY/hyapp-flutter
flutter run -d emulator-5554

Android 模拟器访问本机后端默认地址:

http://10.0.2.2:13000

如果要指定后端地址:

flutter run -d emulator-5554 \
  --dart-define=API_BASE_URL=http://10.0.2.2:13000

如果旧包名已经安装过,可以卸载旧包:

adb uninstall com.hyapp.hyapp_flutter
adb uninstall com.org.laluparty

然后重新运行:

flutter run -d emulator-5554

Release 前必须补充

当前 release 还临时使用 debug signing config。正式包必须

  1. 创建 release keystore。

  2. 配置 Android release signing。

  3. 用 release keystore 跑:

    cd /Users/zuozuo/Desktop/HY/hyapp-flutter/android
    ./gradlew signingReport
    
  4. 把 release SHA1 和 SHA-256 添加到 Firebase Android App。

  5. 重新下载并替换 android/app/google-services.json

  6. 如果上架 Google Play还要把 Play Console 的 App signing key SHA1/SHA-256 添加到 Firebase。

常见错误

选择账号后直接取消

常见原因:

  • Firebase 包名不是 com.org.laluparty
  • SHA1 没添加或添加错了
  • google-services.json 不是最新文件
  • google-services.json 没放在 android/app/
  • 没有 Web OAuth client

serverClientId must be provided on Android

说明 Android 没从 google-services.json 读到 Web client id。

处理:

  1. 确认 android/app/google-services.json 存在。

  2. 确认 Gradle 已应用 com.google.gms.google-services

  3. 确认 JSON 内有 client_type: 3 的 OAuth client。

  4. 重新下载 Firebase 配置文件。

  5. 或运行时传:

    --dart-define=GOOGLE_SERVER_CLIENT_ID=你的Web客户端ID
    

DEVELOPER_ERROR / clientConfigurationError

常见原因:

  • 包名不匹配
  • SHA 指纹不匹配
  • 使用了错误 Firebase 项目的 google-services.json
  • Android OAuth client 和 Web OAuth client 配置不完整

后端返回 AUTH_FAILED

后端要求:

  • provider 必须在允许列表里,当前 Firebase 登录应包含 firebase
  • credential 必须是未过期的 Firebase ID token
  • device_id 不能为空
  • Firebase project id 必须和 token 的 aud 一致
  • token issuer 必须匹配 https://securetoken.google.com/<firebase_project_id>
  • token 签名必须能通过 Firebase Admin SDK 或 Firebase 公钥校验
  • firebase.sign_in_provider 必须在后端 allowlist 中,首版 Google 登录为 google.com

如果 Firebase 登录成功但后端失败,优先用响应 request_id 查 gateway/user-service 日志。日志只能记录失败类型和 Firebase UID 摘要,不能记录原始 ID token。

参考