认证服务
配置 Better Auth、Google OAuth 和 Apple 原生登录
认证服务
EasyStarter 移动端使用 Better Auth 作为认证方案,当前已经内置:
- 邮箱 + 密码登录
- Google OAuth 登录
- Apple 原生登录(仅 iOS)
服务端配置位于 apps/server/src/lib/auth.ts。Apple 登录使用原生 ID Token 流程:App 调用系统级 Apple 登录弹窗,拿到 identityToken 后直接传给 Better Auth 验证,无需网页跳转。
所需环境变量
Server 端
BETTER_AUTH_SECRET=
GOOGLE_CLIENT_ID=
GOOGLE_CLIENT_SECRET=
APPLE_APP_BUNDLE_IDENTIFIER=获取 BETTER_AUTH_SECRET
BETTER_AUTH_SECRET 用于 Better Auth 签名和加密会话数据,必须是一个足够长的随机字符串。
openssl rand -base64 32复制生成结果,分别填到本地和生产环境:
BETTER_AUTH_SECRET=your-long-random-secretBETTER_AUTH_SECRET=your-long-random-secret创建 Google OAuth Client
Google Cloud 控制台:Google Cloud Console
- 登录 Google Cloud Console,选择或新建项目
- 进入
APIs & Services > Credentials - 点击
Create Credentials→ 选择OAuth client ID - 如需要,先完成
OAuth consent screen配置 - 应用类型选择
Web application - 填写回调地址
关键字段:
Authorized JavaScript origins:你的前端地址,例如https://yourdomain.comAuthorized redirect URIs:{SERVER_URL}/api/auth/callback/google
移动端 Google OAuth 需要 HTTPS 回调地址,推荐用 ngrok 将本地服务端映射为 HTTPS。
为什么移动端必须用 ngrok?
移动端的 Google 登录走的是 深链(Deep Link)回调流程,而不是浏览器页面跳转:
- App 调用
expo-web-browser打开 Google 登录页 - 用户完成登录后,Google 将请求重定向到服务端回调地址(
SERVER_URL/api/auth/callback/google) - 服务端处理完成后,将用户重定向回 App 的 Deep Link(例如
myapp://callback) - 操作系统拦截这个 Deep Link,唤起 App,完成登录
这个流程有两个限制:
- Google OAuth 强制要求 HTTPS,
http://localhost不被接受 - 真机和模拟器无法直接访问开发机的
localhost——服务端必须有一个从外部可达的地址
ngrok 解决了这两个问题:它将本地的 localhost:3001 暴露为一个公网可访问的 HTTPS 地址,Google 可以成功回调,服务端也能把用户导回 App 的 Deep Link。
安装 ngrok
前往 ngrok 官网 下载并安装,或使用 Homebrew:
brew install ngrok安装后注册账号并完成认证:
ngrok config add-authtoken YOUR_AUTH_TOKENAuth Token 在 ngrok Dashboard → Your Authtoken 中获取。
启动隧道
在启动本地服务端(pnpm dev:server)之后,再开一个终端运行:
ngrok http 3001ngrok 会输出一个 HTTPS 地址,类似:
Forwarding https://xxxx-xxxx.ngrok-free.app -> http://localhost:3001将这个地址作为 Google OAuth 回调填写:
https://xxxx-xxxx.ngrok-free.app/api/auth/callback/google同时将 .dev.vars 中的 SERVER_URL 也改为这个 ngrok 地址,确保 Better Auth 的 baseURL 和 OAuth 回调一致。
注意:免费版 ngrok 每次重启都会生成新地址,需要同步更新 Google Cloud Console 的回调 URI 和本地
.dev.vars。
创建完成后你会拿到:
Client ID→ 对应GOOGLE_CLIENT_IDClient Secret→ 对应GOOGLE_CLIENT_SECRET
配置 Apple 原生登录
移动端 Apple 登录走的是 iOS 系统级原生流程,App 调用 expo-apple-authentication 获取 Identity Token,服务端用 Bundle ID(即 APPLE_APP_BUNDLE_IDENTIFIER)作为 audience 验证 token。
为 App ID 启用 Sign In with Apple
在 配置 app.json 一章中已创建好 App ID,现在为它开启 Apple 登录能力:
- 登录 Apple Developer Portal → Identifiers
- 找到并点击你的 App ID
- 在 Capabilities 中勾选
Sign In with Apple - 点击 Continue → Save
创建并配置 Service ID
- 在
Identifiers中点击+,选择Service IDs→ Continue - 填写 Description 和 Identifier(例如
com.yourcompany.yourapp.si),这个值作为APPLE_CLIENT_ID - 点击 Register 完成创建
- 在列表中点击刚创建的 Service ID → 勾选
Sign In with Apple→ 点击Configure - 在 Primary App ID 中选择你的 App ID
- 配置 Domains and Subdomains 和 Return URLs:
| 环境 | Domains and Subdomains | Return URLs |
|---|---|---|
| 开发 | xxxx-xxxx.ngrok-free.app | https://xxxx-xxxx.ngrok-free.app/api/auth/callback/apple |
| 生产 | server.yourdomain.com | https://server.yourdomain.com/api/auth/callback/apple |
开发环境使用 ngrok 地址,每次 ngrok 重启后需要同步更新这里的 Domain 和 Return URL。生产环境填写你的实际服务端域名。
- 点击 Next → Done → Continue → Save
填入环境变量
本地开发统一放到 apps/server/.dev.vars:
BETTER_AUTH_SECRET=your-long-random-secret
GOOGLE_CLIENT_ID=your-google-client-id
GOOGLE_CLIENT_SECRET=your-google-client-secret
APPLE_APP_BUNDLE_IDENTIFIER=com.yourcompany.yourapp生产部署时,敏感值放到 apps/server/.env.production:
BETTER_AUTH_SECRET=your-long-random-secret
GOOGLE_CLIENT_SECRET=your-google-client-secret将非敏感的 ID 类变量填到 apps/server/wrangler.jsonc 的 vars 中:
"vars": {
"GOOGLE_CLIENT_ID": "your-google-client-id",
"APPLE_APP_BUNDLE_IDENTIFIER": "com.yourcompany.yourapp"
}Better Auth 在移动端的作用
移动端的 authClient 配置在 apps/native/lib/auth/auth.client.ts,通过 @better-auth/expo 适配器处理 deep link 回调和 cookie 存储。
当前已支持:
- 邮箱密码注册和登录
- Google OAuth(通过 deep link 回调)
- Apple 原生登录(通过 ID Token,仅 iOS)
- 基于 Cookie 的跨端会话管理
Apple 登录仅在真机和 TestFlight 环境中可用,模拟器不支持。