Firebase 接入流程
身份验证使用 Google Firebase 的 Authentication 服务。其优点是安全、支持众多身份验证提供商,缺点是和其他 Firebase 服务集成度高,单接时注意一些配置的坑。
Firebase 提供两种不同的定价方案:免费的 Spark 方案和随用随付的 Blaze 方案。开发时可以先选用 Spark,后续再升级为 Blaze。各服务有相应免费限额( 定价方案 ),超出按使用情况收费( Identity Platform 价格 ),当前需求只需 Authentication 服务中的 Identity Platform,其免费限额是“月活跃用户数不超过 50000”。
一、创建应用
1、登录 Firebase 控制台 https://console.firebase.google.com/。
2、创建项目,填写项目相关信息。
3、添加应用,当前需求是网站,创建应用时选 Web 应用,复制生成的配置信息,为接入做准备,参考官方文档将 Firebase 添加到您的 JavaScript 项目 。
4、点 Authentication 菜单,进 Authentication 服务页。
-
点 “登录方法” 开启相应登录方式,支持:
- 电子邮箱、电话、匿名
- Google 账号、Facebook 账号、 Play 游戏账号、Game Center 账号、Apple 账号、GitHub 账号、Microsoft 账号、Twitter 账号、Yahoo 账号
- 点“设置” > “网域” > “已获授权的网域” > “添加网域”,添加需求网站的详细域名,完成网站授权。默认已获授权网域有:localhost、xx.firebaseapp.com、xx.web.app。
二、接入- npm 方式
1、初始化 Firebase SDK,
import { initializeApp } from "firebase/app"
// 创建应用时的配置信息
const firebaseConfig = {
apiKey: "...",
// 如果自定义域名,填需求网站对应域名
authDomain: "...",
projectId: "...",
storageBucket: "...",
messagingSenderId: "...",
appId: "1:...:web:..."
}
const app = initializeApp(firebaseConfig)
选择自定义域名时,还需服务端做下反代理
location /__/auth {
proxy_pass https://<project>.firebaseapp.com;
}
2、初始化 Authentication SDK
import { getAuth } from "firebase/auth"
...
const auth = getAuth(app)
3、登录方式
根据在 Firebase 控制台开启的登录方式对接,当前需求只开启下面几种:
-
Google 账号
import { GoogleAuthProvider } from 'firebase/auth' ... const provider = new GoogleAuthProvider() -
Facebook 账号
import { FacebookAuthProvider } from 'firebase/auth' ... const provider = new FacebookAuthProvider()- 登录 Facebook 开发者平台 创建应用,“use case” 选择 “Authenticate and request data from users with Facebook Login”
- 完善 “App settings” 各项信息
- 在 Firebase 平台 Facebook 登录项填入 Facebook 开发者平台 “App settings” 里的应用 ID、密钥。
- 自定义“use case”,选择增加 "email","Valid OAuth redirect URIs" 填入 Firebase 平台 Facebook 登录项里的 OAuth 重定向 URI。
- 发布,注意发布时会强制要求做 Business 商家验证
-
电子邮件
链接方式需要配置 Firebase Hosting 服务,改用密码方式,需额外实现密码强度校验
4、选择登录交互方式
-
重定向登录交互方式,signInWithRedirect,缺点是配置复杂,需预先关联 Google Cloud Billing 账号,本地 localhost 还需要配置 https,参考文章在阻止第三方访问存储空间的浏览器上使用 signInWithRedirect 的最佳实践
import { signInWithRedirect, getRedirectResult } from "firebase/auth" ... signInWithRedirect(auth, provider) ... // 登录后页面重定向返回 const userCred = await getRedirectResult(auth) -
弹窗登录交互方式,signInWithPopup,缺点是弹窗容易被浏览器误拦截。
import { signInWithPopup } from "firebase/auth" ... const userCred = await signInWithPopup(auth, provider)
本地开发时,可以先用弹窗登录交互方式
5、实现内部用户登录
根据登录后返回的用户信息 userCred.user.providerData,请求内部登录接口,获取关联用户 token,完成登录流程。
三、其他
调试跳转登录方式时,返回用户信息始终是 null,定位原因,因为身份验证相关代码托管到 Firebase,还需在 Google Cloud 更新 OAuth 2.0 Client ID Credential,这又涉及到注册 Google Cloud Billing 账号,开通支付功能,注意大陆地区开通不了,参考 stackoverflow onAuthStateChanged and getRedirectResult returning null user after successful google login redirect 。
auth/account-exists-with-different-credential 错误,原因 Google 和 Facebook 使用了同一邮箱注册。
auth/popup-closed-by-user 错误,复现场景是 Andriod Chrome 浏览器,Facebook 账号登录时。网上反馈原因很多:未正确设置 Authorized domains;浏览器阻止了弹窗(解决办法是 nginx 设置 add_header Cross-Origin-Opener-Policy 为 "same-origin-allow-popups",或者 provider.setCustomParameters({ display: 'popup' });但根据 Firebase 开源社区,这个问题根源是 Android 环境下,Facebook 发生了多次重定向,导致 Firebase 错误认为弹窗被关闭了,目前无解,官方建议是换成 signInWithRedirect,但 signInWithRedirect 社区也反馈有 bug,最后评估改用 Facebook 原生登录。