密码注册后 Firebase 云功能出现未经身份验证的错误

Posted

技术标签:

【中文标题】密码注册后 Firebase 云功能出现未经身份验证的错误【英文标题】:Firebase Cloud Function Unauthenticated Error After Password Sign-Up 【发布时间】:2021-12-05 17:51:44 【问题描述】:

触发此云功能时收到以下错误:“错误未验证”。

我不希望允许未经身份验证的调用此云功能。

工作流程如下:

    用户通过 Firebase 密码身份验证在应用中注册 Firebase 身份验证凭据已创建(Firebase 成功登录用户) 创建凭据后,会在 firebase 身份验证回调中触发云函数。

此时,调用应该经过身份验证,因为它是在 firebase 身份验证响应中触发的。

但是,它总是出错

错误:未经身份验证

此时用户已通过身份验证。

有什么建议吗? 客户代码 ->

const onRegisterPress = () => 
  if (password !== confirmPassword) 
    alert("Passwords don't match.")
    return
  
  setLoading(true);
  //CREATE'S USER'S AUTH CREDENTIALS
  firebase
    .auth()
    .createUserWithEmailAndPassword(email, password)
    .then((response) => 
      const data = 
        ...
      
      //console.log(response);
      return new Promise(async function(resolve, reject) 
        await firebase.functions().httpsCallable('writeAccountUser')(
          data
        ).then((response) => 
          console.log("Write Account User Response: ", response);
          resolve(setLoading(false));
        ).catch((error) => 
          console.error("Cloud Function Error: ", error);
          setLoading(false);
          reject(error)
        )
      );
    )
    .catch((error) => 
      alert(error)
    );

云功能->

const functions = require("firebase-functions");
const admin = require("firebase-admin");
admin.initializeApp();
const firestore = admin.firestore();

exports.writeAccountUser = functions.https.onCall((data, context) => 
    console.log("Incoming Data: ", data);
    console.log("Incoming Context: ", context);
    const clientData = data.data;
    console.log("Client Data: ", clientData);
    console.log("Account ID: ", clientData.accountID);
    return new Promise(async function (resolve, reject) 
        const accountsRef = firestore.collection('Accounts');
        const usersRef = firestore.collection('users');
        const now = new Date();
        if (clientData.accountExists === true) 
            console.log("Account Exists");
            await accountsRef
                .doc(clientData.accountID)
                .update(
                    users: admin.firestore.FieldValue.arrayUnion(clientData.uid)
                ).catch((error) =>  console.error(error); reject(false) );
        
        else 
            console.log("Account Does Not Exist!");
            const account_data = clientData.accountData;
            const product_lines = clientData.productLines;
            await accountsRef
                .doc(clientData.accountID)
                .set(
                    account_data,
                    product_lines,
                    users: [clientData.uid],
                    dateCreated: 
                        date: now,
                        timestamp: now.getTime()
                    
                ).catch((error) =>  console.error(error); reject(false));
        ;
        const email = clientData.email;
        const fullName = clientData.fullName;
        const acceptTerms = clientData.acceptTerms;
        const userData = 
            id: clientData.uid,
            email,
            fullName,
            accountID: clientData.accountID,
            dateCreated: 
                date: now,
                timestamp: now.getTime()
            ,
            lastUpdateFetch: 
                date: now,
                timestamp: now.getTime()
            ,
            termsConditionsAccepted: acceptTerms
        ;

        await usersRef
            .doc(clientData.uid)
            .set(userData)
            .catch((error) =>  console.error(error); reject(false) );
        resolve(true);
    );
);

错误-> [未处理的承诺拒绝:错误:未经身份验证] 在 node_modules/@firebase/firestore/dist/rn/prebuilt.rn-f9cd27ba.js:12199:33 中 在 http:///node_modules/expo/AppEntry.bundle?platform=ios&dev=true&hot=false&minify=false:169743:29 in _errorForResponse 在 yu 的 node_modules/@firebase/firestore/dist/rn/prebuilt.rn-f9cd27ba.js:12747:31 在 node_modules/tslib/tslib.js:77:12 中 在 http://REDACTED/node_modules/expo/AppEntry.bundle?platform=ios&dev=true&hot=false&minify=false:120748:21 中 在 http://REDACTED/node_modules/expo/AppEntry.bundle?platform=ios&dev=true&hot=false&minify=false:120702:31 完成

【问题讨论】:

【参考方案1】:

你可以尝试重构如下所示的函数:

const onRegisterPress = async () => 
  if (password !== confirmPassword) 
    alert("Passwords don't match.")
    return
  
  setLoading(true);

  const response = await firebase.auth().createUserWithEmailAndPassword(email, password)

  const data = ...
 
  const fnResponse = await firebase.functions().httpsCallable('writeAccountUser')(data)

  console.log("Write Account User Response: ", response);

您还可以在同一功能中使用 Admin SDK 创建帐户,并在响应后将用户登录到您的 Web 应用程序。这将确保 Cloud 函数的操作也已执行(以防用户出于任何原因注册后未调用该函数)。

【讨论】:

我喜欢这个,干净多了。它仍然显示 [未处理的承诺拒绝:错误:未经身份验证] 我正在尝试通过此云功能中的 Admin SDK 写入 Firestore 中的集合。我最初使用以下安全规则在客户端上向它写入安全规则:“允许读取,写入:如果 request.auth.token!=null”作为测试,直接在 firebase createUser 回调中调用它并且它有效。奇怪的是它没有对云功能进行身份验证。 @Arcade336 可以分享一下你的云功能代码吗?如果您是 Admin SDK,则不应出现任何身份验证错误。 我已更新线程以包含云功能代码。感谢您查看并回答我的问题。 @Arcade336 用户似乎在调用该函数之前已登录。您能否分享错误的屏幕截图及其错误堆栈,以便我们知道它来自哪里?函数是否首先被触发? @Arcade336 所以你正在进入竞争状态。我只需取消订阅 auth 观察者,将所有设备 ID 连同数据一起传递,然后从 Cloud 函数中添加所有内容。所以现在我们并不期望云功能在其他任何事情之前完成。

以上是关于密码注册后 Firebase 云功能出现未经身份验证的错误的主要内容,如果未能解决你的问题,请参考以下文章

Firebase 身份验证 UI - 登录与注册

Firebase休息验证 - 云功能

Firebase 电子邮件验证无法正常工作

为Firebase身份验证帐户实施密码的自定义规则

Firebase firestore 获取未经身份验证的用户文档

注册用户未显示在 Firebase Firestore 中