Firebase+TypeScript服务端报错:Auth类型无toJSON属性及Google登录问题
解决Firebase Admin + TypeScript中"Property 'toJSON' does not exist on type 'Auth'"错误及完整Google登录流程
错误原因
你代码里的firebase.auth()返回的是Firebase Auth服务实例,不是已登录用户的对象,所以不存在toJSON()方法。要获取登录用户数据,必须先让前端传递Google登录后的ID Token,后端通过Firebase Admin验证token后才能拿到用户真实信息。
完整流程实现步骤
1. 前端传递ID Token到后端
前端完成Google登录后,获取ID Token并在请求中传递:
// 前端示例(React/Vue等) import { getAuth, signInWithPopup, GoogleAuthProvider } from "firebase/auth"; const provider = new GoogleAuthProvider(); const auth = getAuth(); signInWithPopup(auth, provider) .then(async (result) => { const idToken = await result.user.getIdToken(); // 发送请求到后端,将token放在Authorization头 await fetch('/api/users/create', { method: 'POST', headers: { 'Authorization': `Bearer ${idToken}`, 'Content-Type': 'application/json' } }); }) .catch((error) => { console.error(error); });
2. 后端验证Token并处理用户数据
修正后的Firebase初始化代码
import admin from 'firebase-admin'; import appConfig from '@/AppConfig/app.config'; export const setupFirebase = () => { // 避免重复初始化 if (!admin.apps.length) { admin.initializeApp({ projectId: appConfig.firebaseProjectID, // 生产环境必须配置service account密钥 // credential: admin.credential.cert(require('./service-account-key.json')) }); } }; export const firebase = admin;
修正后的UserController代码
import { type Response, type NextFunction, type Request } from 'express'; import UserService from './users.service'; import Api from '@/lib/api'; import { firebase } from '@/lib/firebase'; export default class UserController extends Api { private readonly userService = new UserService(); public createUser = async ( req: Request, res: Response, next: NextFunction ) => { try { // 提取请求头中的ID Token const authHeader = req.headers.authorization; if (!authHeader || !authHeader.startsWith('Bearer ')) { return res.status(401).json({ message: '未提供有效Token' }); } const idToken = authHeader.split(' ')[1]; // 验证Token并解码用户信息 const decodedToken = await firebase.auth().verifyIdToken(idToken); const userData = { email: decodedToken.email, name: decodedToken.name, photoUrl: decodedToken.picture }; // 检查用户是否已存在 const existingUser = await this.userService.findUserByEmail(userData.email); if (existingUser) { return res.status(200).json({ message: '用户已存在', user: existingUser }); } // 创建新用户记录 const newUser = await this.userService.createUser( userData.name, userData.email, userData.photoUrl ); // 返回成功响应 res.status(201).json({ message: '用户创建成功', user: newUser }); } catch (e) { // 处理Token验证失败等特定错误 if (e instanceof Error && e.message.includes('invalid token')) { return res.status(401).json({ message: '无效的Token' }); } next(e); } }; }
3. Prisma UserService示例
确保你的UserService正确调用Prisma操作数据库:
import { PrismaClient } from '@prisma/client'; const prisma = new PrismaClient(); export default class UserService { async findUserByEmail(email: string) { return prisma.user.findUnique({ where: { email } }); } async createUser(name: string, email: string, photoUrl?: string) { return prisma.user.create({ data: { name, email, photoUrl } }); } }
关键注意事项
- 生产环境必须配置Firebase Admin的service account密钥,不能仅依赖projectId初始化。
- ID Token默认有效期1小时,前端需在过期前调用
getIdToken(true)刷新token。 - 处理响应时使用
return提前终止流程,避免重复发送响应导致错误。
内容的提问来源于stack exchange,提问作者Ammar Alesrawi
相关产品推荐
相关产品推荐

