If I have two tenants in GCP Cloud Identity, tenant1 and tenant2, and I do this:
import {initializeApp} from 'firebase/app';
import {getAuth} from "firebase/auth";
export const firebaseApp = initializeApp(firebaseConfig);
export const firebaseAuth = getAuth()
firebaseAuth.tenantId = "tenant1"
firebaseAuth.onAuthStateChanged(user => {
console.log({user})
});
user.tenantId can be tenant2, if my previous login to the app was with tenant2.
In other words, it seems to me that onAuthStateChanged() is happy to accept state change from the previous tenant login.
Is this expected? If so, whats the recommended remedial approach?
Related
I have recently started learning Nuxt 3 by trying to implement basic user auth logic with firebase and now I would need to retrieve the cookie from the req to initialise the user auth state inside Pinia store but it seems like nuxtServerInit is not supported by Pinia. After realising this I proceeded to a different solution where I'm using server middleware to pass the req object to an action called nuxtServerInit() but then I ran into another problem which is that I cannot call the auth().verifyIdToken(token) from there because the firebase is initialised inside a plugin which runs afterwards.
After this I also tried to initialise firebase inside server middleware and pass auth object to nuxtServerInit() action and set it to the state but then I could not call an action from there I guess because Pinia has not initialised yet?
How could I overcome the original problem? What could be a better approach?
Heres the firebase init plugin:
import { initializeApp } from 'firebase/app'
import { getAuth } from "firebase/auth"
import { getFirestore } from 'firebase/firestore'
import { useStore } from '~/store/index.js'
export default defineNuxtPlugin(nuxtApp => {
const firebaseConfig = {
apiKey: "API_KEY",
authDomain: "AUTH_DOMAIN",
projectId: "PROJECT_ID",
storageBucket: "STORAGE_BUCKET",
messagingSenderId: "MESSAGING_SENDER_ID",
appId: "APP_ID"
};
const app = initializeApp(firebaseConfig);
const auth = getAuth(app)
const firestore = getFirestore(app)
nuxtApp.vueApp.provide('auth', auth)
nuxtApp.provide('auth', auth)
nuxtApp.vueApp.provide('firestore', firestore)
nuxtApp.provide('firestore', firestore)
const store = useStore()
console.log('AUTH', auth)
auth.onAuthStateChanged((user) => {
store.setAuth(user)
})
})
I have reinstalled firebase, expo, and refactored to be using V9 with no real progress. My signInWithEmailAndPassword works fine but I receive the same error with both popUp and Redirect.
TypeError: (0, \_auth.signInWithRedirect) is not a function. (In '(0, \_auth.signInWithRedirect)(auth, provider)', '(0, \_auth.signInWithRedirect)' is undefined)
I believe that it must not be importing correctly but I do not see how. I have authorized google auth in the firebase console and as stated tested the standard sign in and create user functions and they both have no error. My config and initialization both work for standard auth as well as firestore connections.
Import statements :
import {
getAuth,
onAuthStateChanged,
signInWithEmailAndPassword,
createUserWithEmailAndPassword,
signInWithRedirect,
GoogleAuthProvider,
} from "firebase/auth";
Handle Google sign in function :
const auth = getAuth();
const signInWithGoogle = () => {
const provider = new GoogleAuthProvider();
signInWithRedirect(auth, provider)
.then((*result*) => {
*// This gives you a Google Access Token. You can use it to access the Google API.*
const credential = GoogleAuthProvider.credentialFromResult(*result*);
const token = credential.accessToken;
*// The signed-in user info.*
const user = *result*.user;
*// ...*
})
.catch((*error*) => {
*// Handle Errors here.*
const errorCode = *error*.code;
const errorMessage = *error*.message;
*// The email of the user's account used.*
const email = *error*.email;
*// The AuthCredential type that was used.*
const credential = GoogleAuthProvider.credentialFromError(*error*);
*// ...*
});
};
Any guidance on what I am missing is greatly appreciated.
I need to run a Firebase function whenever my user updates their email address, except auth only has onCreate and onDelete. How can I react to email updates?
It's not possible today to directly react to an email address changing in Firebase Authentication. If you'd like to see that as a feature, please file a feature request.
You can react to it indirectly by having your app listen to authentication events (Android), take the User object delivered to your listener, and write the user's email address to a RealtimeDatabase location (or Firestore document) for that user's UID. Then, you can have a database trigger that tracks the location of your users in the database, and react to the change there.
My Workaround Use functions.https.onCall to create an HTTPS callable function.
Firebase Function
exports.onUpdateUserEmail = functions.https.onCall((data, context) => {
const uid = context.auth.uid;
const email = context.auth.token.email || null;
return admin.
firestore()
.collection("users")
.doc(uid)
.set({email});
});
Deploy
$ firebase deploy --only functions:addMessage
Call your Fonction in your app nodejs example firebase v9
import { initializeApp } from 'firebase/app';
import { getAuth, updateEmail } from "firebase/auth";
import { getFunctions, httpsCallable } from 'firebase/functions';
const app = initializeApp({
projectId: '### CLOUD FUNCTIONS PROJECT ID ###',
apiKey: '### FIREBASE API KEY ###',
authDomain: '### FIREBASE AUTH DOMAIN ###',
});
const functions = getFunctions(app);
const onUpdateEmail = httpsCallable(functions, 'onUpdateUserEmail');
const auth = getAuth();
updateEmail(auth.currentUser, "user#example.com").then(() => {
// Email updated!
onUpdateEmail();
}).catch((error) => {
// An error occurred
// ...
});
I made a service in my React Native Expo Snack app that handles the instantiation of different firebase services. Somehow, Snack isn't able to find firestore, as it says "_firebase.default.firestore is not a function". The code used is shows below:
import firebase, { firestore } from 'firebase';
const config = { ... // Deleted, assume the config is correct }
export const FirebaseApp = !firebase.apps.length ? firebase.initializeApp(config) : firebase.app();
export const Firestore = firebase.firestore();
export const Auth = firebase.auth();
Can somebody confirm this should work in Snack? Why doesn't it recognize firestore() as a function?
I have recently discovered the Firebase callable functions which allows me to call HTTPS trigger like function from the client side (and with auth() support).
I struggle to implement this new feature in my already existing Firebase web-client application.
I have some cloud functions running, among them are some HTTPS functions I would like to transform into an HTTPS callable function (with functions.https.onCall).
The documentation indicates:
Set up your client development environment
<script src="https://www.gstatic.com/firebasejs/4.12.0/firebase.js"></script>
<script src="https://www.gstatic.com/firebasejs/4.12.0/firebase-functions.js"></script>
And my code is:
import firebase from 'firebase';
import 'firebase/firestore';
const firebaseApp = firebase.initializeApp({
apiKey: '....',
authDomain: '....',
databaseURL: '....',
projectId: '....',
storageBucket: '....',
messagingSenderId: '....',
});
const db = firebaseApp.firestore();
const auth = firebaseApp.auth();
const functions = firebaseApp.functions();
export { db, auth, functions };
When I run my app, I got the following error:
Uncaught TypeError: firebaseApp.functions is not a function
I have tried yarn add firebase-functions and then import 'firebase-functions but then the app requires firebase-admin. I am affraid it is too much for a client-app so I might go in the wrong direction.
Can someone help me with this issue?
(!) This issue is NOT about the server-side Firebase SDK for Cloud Functions (Node JS). It is about calling Cloud functions directly from a Firebase web app.
Thank you!
UPDATE:
Thanks to #Andrew's post, this solves my issue:
My configuration
import firebase from 'firebase';
import 'firebase/firestore';
import '#firebase/functions';
import firestoreConfig from '#/config/firestore';
const firebaseApp = firebase.initializeApp(firestoreConfig /* The JSON configuration from my Firebase project */);
const db = firebaseApp.firestore();
const auth = firebaseApp.auth();
const functions = firebaseApp.functions();
export { db, auth, functions };
Using the configuration:
import { db, functions } from '#/database/firestoreInit';
export default {
addMessage(text) {
const addMessage = functions.httpsCallable('addMessage');
return addMessage({ text }).then(result => result);
},
}
I just ran into this same problem myself and solved it by installing and importing the #firebase/functions npm package. I found the solution on github here:
https://github.com/firebase/firebase-js-sdk/blob/master/packages/functions/README.md
From the README on github:
ES Modules
import firebase from '#firebase/app';
import '#firebase/functions'
// Do stuff w/ `firebase` and `firebase.functions`
CommonJS Modules
const firebase = require('#firebase/app').default;
require('#firebase/functions');
// Do stuff with `firebase` and `firebase.functions`
Hope that helps! The actual documentation is not very clear about having to do this in order to call the functions.
About #firebase/functions:
This package is not intended for direct usage, and should only be used via the officially supported firebase package.
This worked for me:
import * as firebase from 'firebase/app'; // Typescript
// import firebase from 'firebase/app'; // JS
import 'firebase/functions';
const myCallableFunc = firebase.functions().httpsCallable('myCallableFunc');
I don't know about importing firebase-functions with a CDN but if you're using npm then you don't need the firebase-functions package, just installing firebase will do.
Follow the steps mentioned here. Firebase cloud functions
I think there is nothing like firebaseApp.functions.