Javax.tech
Javax.tech

Reputation: 55

Firebase Cloud Function Unauthenticated Error After Password Sign-Up

I am receiving the following error when triggering this cloud function: "Error unauthenticated".

I do not wish to allow unauthenticated calls to this cloud function.

The workflow is as follows:

  1. User registers in app via firebase password authentication
  2. Firebase Auth Credentials are created (firebase signs in user upon success)
  3. Once the credentials have been created, the cloud function is triggered in the firebase auth callback.

At this point, the call should be authenticated, given it's being triggered in the firebase auth response.

However, it keeps erroring with

Error: unauthenticated

The user is authenticated at this point.

Any suggestions? CLIENT CODE ->

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)
    });
}

CLOUD FUNCTION ->

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);
    });
});

Error -> [Unhandled promise rejection: Error: unauthenticated] at node_modules/@firebase/firestore/dist/rn/prebuilt.rn-f9cd27ba.js:12199:33 in at http:///node_modules/expo/AppEntry.bundle?platform=ios&dev=true&hot=false&minify=false:169743:29 in _errorForResponse at node_modules/@firebase/firestore/dist/rn/prebuilt.rn-f9cd27ba.js:12747:31 in yu at node_modules/tslib/tslib.js:77:12 in at http://REDACTED/node_modules/expo/AppEntry.bundle?platform=ios&dev=true&hot=false&minify=false:120748:21 in at http://REDACTED/node_modules/expo/AppEntry.bundle?platform=ios&dev=true&hot=false&minify=false:120702:31 in fulfilled

Upvotes: 1

Views: 1246

Answers (1)

Dharmaraj
Dharmaraj

Reputation: 50840

You can try refactoring the function as shown below:

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);
}

You can also create the account using the Admin SDK in the same function and log the user on your web app after the response. That'll ensure the Cloud function's action has been executed as well (just in case the function is not called after user sign up for any reason).

Upvotes: 1

Related Questions