I've been trying to create a front-end app with Firebase Authentication (Google sign-in) and Firebase Cloud Function which stores the authenticated user data to Firestore.
- A user clicks a button to sign in with Google (Firebase Authentication).
- The front-end calls Cloud Function (
saveAuthUserData) after sign-in. - Cloud Function runs to store the authenticated user's profile in Firestore (collection:
users).
The expected Cloud Function (3) is to send an HTTP POST request to Firestore with the user's profile data.
I wrote this public/index.html and functions/index.js (below), but still looking for the way how it should interact with Firebase without any errors, specifically how to send an HTTP POST request from public/index.html to Cloud Function in functions/index.js. Both files are deployed on Firebase Hosting.
public/index.html
import { initializeApp } from "firebase/app";
import { getAuth, signInWithPopup,GoogleAuthProvider } from "firebase/auth";
import { getFirestore, collection, doc, setDoc } from "firebase/firestore";
import { getFunctions, httpsCallable } from "firebase/functions";
const config = {
apiKey: "xxxxxx",
authDomain: "yyyyy.web.app",
projectId: "zzzzzz"
};
const app = initializeApp(config);
const db = getFirestore(app);
const provider = new GoogleAuthProvider();
const auth = getAuth();
const functions = getFunctions();
var btn = document.getElementById("#sign-in-with-google");
btn.addEventListener("click", function() {
signInWithPopup(auth, provider).then((result) => {
var credential = GoogleAuthProvider.credentialFromResult(result);
var user = result.user;
if(user !== null) {
var profile = {
email: user.email,
name: user.displayName,
uid: user.uid
};
const setAuthUserData = httpsCallable(functions, "setAuthUserData");
setAuthUserData(profile).then((result) => {
console.log(result.data);
});
}
});
functions/index.js
const admin = require("firebase-admin");
const functions = require("firebase-functions");
admin.initializeApp();
const fireStore = admin.firestore();
const express = require("express");
const axios = require("axios");
const cors = require("cors");
const app = express();
app.use(cors({ origin: true }));
const setAuthUserData = async (profile) => {
var isAuthUserSet = false;
const db = fireStore.collection("users");
const email = profile.email;
if(email) {
const ref = await db.doc(email).set(profile).then(() => {
isUpdated = true;
});
}
}
return isUpdated;
}
app.post("/setAuthUserData/", (req, res) => {
setAuthUserData(req.params.profile).then((response) => res.send(response));
});
const api = functions.https.onRequest(app);
module.exports = { api };
Updated on 9/6/2022
I fixed my code as below by checking this answer, but I couldn't see any changes on Firestore and any success/error messages on both browser's console and GCP's Logs Explorer.
functions/index.js
- Cloud Function to save a user's profile data (being passed from
public/index.html) to Firestore (userscollection) if its email is valid.
const admin = require("firebase-admin");
const functions = require("firebase-functions");
admin.initializeApp();
const fireStore = admin.firestore();
const express = require("express");
const axios = require("axios");
const cors = require("cors");
const app = express();
app.use(cors({ origin: true }));
module.exports.setAuthUserData = functions.https.onCall(async (data, context) => {
var isUpdated = false;
try {
const db = fireStore.collection("users");
const email = data.email;
if(email) {
const ref = await db.doc(email).set(data).then(() => {
isUpdated = true;
});
}
return isUpdated;
} catch (err) {
return err;
}
});
Also, this terminal's screenshot shows how both functions and hosting are deployed.
Just in case, I tried to do the same thing without Cloud Function (as below) and it perfectly works as expected. When a user presses a button, he is asked to sign in with Google and his profile is properly stored in Firestore once authenticated.
public/index.html
import { initializeApp } from "firebase/app";
import { getAuth, signInWithPopup, GoogleAuthProvider } from "firebase/auth";
import { getFirestore, collection, doc, setDoc } from "firebase/firestore";
import { getFunctions, httpsCallable } from "firebase/functions";
const config = {
apiKey: "xxxxxx",
authDomain: "yyyyy.web.app",
projectId: "zzzzzz"
};
const app = initializeApp(config);
const db = getFirestore(app);
const provider = new GoogleAuthProvider();
const auth = getAuth();
const functions = getFunctions();
var btn = document.getElementById("#sign-in-with-google");
btn.addEventListener("click", function() {
signInWithPopup(auth, provider).then((result) => {
var credential = GoogleAuthProvider.credentialFromResult(result);
var user = result.user;
if(user !== null) {
var profile = {
email: user.email,
name: user.displayName,
uid: user.uid
};
(async() => {
try {
var profile = {
email: user.email,
name: user.displayName,
uid: user.uid
};
const ref = await setDoc(doc(db, "users", user.email), profile);
} catch (err) {
console.error(err);
}
})();
}
});
Updated on 9/7/2022
I fixed my code and finally it's working! The reason why it hadn't been working is a few syntax errors in mine, and there is no problem in what's suggested here.


