Firebase .listUsers() is not function - javascript

I have been looking for some time, but without answers, so I ask my question:
I work with firebase and I make a function 'getAllUsers' (which must return all registered user uid) :
function getAllusers(nextPageToken){
app.auth().listUsers(1000, nextPageToken)
.then(function(listUsersResult) {
listUsersResult.users.forEach(function(userRecord) {
console.log('user', userRecord.toJSON());
});
if (listUsersResult.pageToken) {
// List next batch of users.
listAllUsers(listUsersResult.pageToken);
}
})
.catch(function(error) {
console.log('Error listing users:', error);
});
}
(yes, this is the doc example)
but I get
Uncaught TypeError: app.auth is not a function
I tested :
auth().listUsers()
getAuth.listUsers()
I think this is my imports:
import { initializeApp } from "https://www.gstatic.com/firebasejs/9.6.7/firebase-app.js";
import { getAuth, signInWithPopup, createUserWithEmailAndPassword, signInWithEmailAndPassword, GoogleAuthProvider, signOut, getAdditionalUserInfo, reauthenticateWithCredential } from "https://www.gstatic.com/firebasejs/9.6.7/firebase-auth.js";
import { getDatabase, set, ref, update, child, onValue, get } from "https://www.gstatic.com/firebasejs/9.6.7/firebase-database.js";
import { getStorage, ref as sRef, uploadBytes, getDownloadURL, deleteObject } from "https://www.gstatic.com/firebasejs/9.6.7/firebase-storage.js";
const firebaseConfig = {
apiKey: "XX",
authDomain: "XX",
databaseURL: "XX",
projectId: "XX",
storageBucket: "XX",
messagingSenderId: "XX",
appId: "XX",
measurementId: "XX"
};
const app = initializeApp(firebaseConfig);
const database = getDatabase(app);
const auth = getAuth(app);
const storage = getStorage(app);
I am currently researching how to use 'admin' for this
Hoping someone can help me, I keep looking, thanks in advance

The Firebase Admin SDK run code with elevated/administrative permissions and thus can only be used in a trusted environment, such as your development machine, a server that you control, or Cloud Functions/Cloud Run. They cannot be used in client-side application code, as that would be a security concern.
The regular Firebase SDKs only allow a user access to their own profile data, as doing otherwise on an SDK level would be a security concern.
If the application needs to show information about other users, you will have to build (and secure) that yourself on top of Firebase. The two most common options:
Implement the functionality in a custom server-side API that uses the Admin SDK and that you can call from your client-side application code. The custom server-side code you write should then ensure that only data that the caller is authorized to see is returned.
Have each user write to a cloud-hosted database (such as Firestore or the Realtime Database or Firebase), and then have other users read it from there. In this scenario you'll want to use Firebase's security rules to ensure each user can only access the data they're authorized for.
This topic has been covered frequently before, so I recommend also checking out:
Firebase list all users
How do I return a list of users if I use the Firebase simple username & password authentication
Can't retrieve list of all users from firebase authetication
Retrieving a list of users who have registered using Firebase Auth

Related

Firebase Cloud Messaging - Cannot receive messages through PWA (Vue + Firebase 8.10.0)

I've run into a snag/gap in firebase's setup with web applications(PWA) which is not so clear in the documentation. I have an existing PWA built on Vue#^2.6.10 and am trying to plug Firebase's cloud messaging into it using firebase#8.10.0. It's easy enough to configure my application to receive messages from firebase when the app is active within a browser tab by using the following code in my App.vue in a created hook.
// Includes for the component
import firebase from 'firebase/app'
import 'firebase/app'
import 'firebase/messaging'
// Within the created hook
firebase.initializeApp({
apiKey: "XXXXXXXXXX_XXXXXXXXXXXXXXXXXXXXX",
authDomain: "xxxx.firebaseapp.com",
projectId: "xxxx",
storageBucket: "xxxxxx.appspot.com",
messagingSenderId: "xxxxxxxxxxxx",
appId: "x:xxxxxxxxx:web:xxxxxxxxxxx",
measurementId: "G-xxxxxxxxxxx"
})
const firebaseMessaging = firebase.messaging()
firebaseMessaging.getToken()
.then((token) => { console.log("Messaging Token: ", token) })
.catch((err) => { console.log("Messaging error: ", err) })
firebaseMessaging.onMessage((payload) => {
console.log("Message in app: ", payload)
})
While the PWA is active within a browser window/tab, I am able to successfully send a curl message to my application.
curl -X POST --header "Authorization: key=XXXXXXXXXXXX" --Header "Content-Type: application/json" https://fcm.googleapis.com/fcm/send -d '{"to":"XXXXXXXXXXXXX","notification":{"title":"Hello","body":"World","icon":"image/mstile-150x150.png"}}'
However, if I try to then configure the PWA to receive notifications via the firebase service worker, this is when the documentation seems to be missing context. Below is the recommended service worker configuration from the firebase docs which I am using.
// Give the service worker access to Firebase Messaging.
// Note that you can only use Firebase Messaging here. Other Firebase libraries
// are not available in the service worker.
importScripts('https://www.gstatic.com/firebasejs/8.10.0/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/8.10.0/firebase-messaging.js');
// Initialize the Firebase app in the service worker by passing in
// your app's Firebase config object.
// https://firebase.google.com/docs/web/setup#config-object
firebase.initializeApp({
apiKey: "xxxxx_xxxxxxxxxxxxxxx",
authDomain: "xxxx.firebaseapp.com",
projectId: "xxxx",
storageBucket: "xxxx.appspot.com",
messagingSenderId: "xxxxxxxxxxx",
appId: "x:xxxx:web:xxxxxxxxxx",
measurementId: "G-xxxxxxxxxxx"
});
// Retrieve an instance of Firebase Messaging so that it can handle background
// messages.
const messaging = firebase.messaging();
For a standard website without an existing service worker, it seems like this configuration should be enough, however, since I am tying into an existing PWA with an existing service worker, it seems I need to register firebase's configuration with the existing PWA configuration on my application. From what I've found thus far, the proper configuration of that tie-in is the following.
if ("serviceWorker" in navigator) {
wb = new Workbox(`${process.env.BASE_URL}service-worker.js`)
wb.addEventListener("controlling", () => { window.location.reload() })
wb.register()
wb.register("./firebase-messaging-sw.js")
.then(function(registration) {
console.log("Registration successful, scope is:", registration.scope);
})
.catch(function(err) {
console.log("Service worker registration failed, error:" , err );
})
} else {
wb = null
}
From the look of it, this does successfully register Firebase's configuration with my existing service worker.
However, while the registration looks successful from the onset it's not actually tying into the service worker. When clicking away from the PWA's active browser tab under this configuration, the service worker does not receive a notification when performing the same curl above. From everything I can tell thus far in the docs, the PWA should be receiving the notification and firing a default browser notification for the event, however, that's not the case. No notification is received even though the notification did send through Firebase's API successfully given the response from their API:
{"multicast_id":3069325822032476405,"success":1,"failure":0,"canonical_ids":0,"results":[{"message_id":"88f73357-6a0e-416d-8417-67608437f84d"}]}%
So, I am kind of at the end of the road in terms of what documentation and threads I can find on this topic thus far. It would seem like there's not a great example of how to do this configuration correctly when tying into an existing service worker. I very much appreciate anyone with experience on this topic providing their insight on configurations you've made work using firebase and service worker on PWAs.
Many thanks!
One way to initialize Firebase at App and Service Worker levels is to use both the Message API (postMessage) and SW registration life-cycle (ready).
Instead of creating a dedicated SW file for Firebase, edit the existing one.
service-worker.js
importScripts('https://www.gstatic.com/firebasejs/8.10.0/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/8.10.0/firebase-messaging.js');
/**
* Service Worker message listener.
*/
self.addEventListener("message", ({ data }) => {
if (data.action === "initializeFirebase") {
if (firebase.messaging.isSupported()) {
const { config } = data.payload;
firebase.initializeApp(config);
firebase.messaging();
}
}
});
It listens to an action called initializeFirebase, receives the configuration object, and initializes it.
--
Now we just need to send that message once the Service Worker is ready.
registerServiceWorker.js (Usually imported in src/main.js at Vue projects.)
import { register } from "register-service-worker";
import { FirebaseMessaging } from "./FirebaseMessaging.js";
register(`${process.env.BASE_URL}service-worker.js`, {
ready(registration) {
FirebaseMessaging.initServiceWorker(registration);
},
});
FirebaseMessaging.js
const FIREBASE_CONFIG = {
apiKey: "XXXXXXXXXX_XXXXXXXXXXXXXXXXXXXXX",
authDomain: "xxxx.firebaseapp.com",
projectId: "xxxx",
storageBucket: "xxxxxx.appspot.com",
messagingSenderId: "xxxxxxxxxxxx",
appId: "x:xxxxxxxxx:web:xxxxxxxxxxx",
measurementId: "G-xxxxxxxxxxx"
};
// Firebase Messaging instance
let messaging;
export const FirebaseMessaging = {
init() {
if (!messaging) {
firebase.initializeApp(FIREBASE_CONFIG);
messaging = firebase.messaging();
}
},
initServiceWorker(registration) {
this.init();
messaging.useServiceWorker(registration);
if (registration.active) {
registration.active.postMessage({
action: "initializeFirebase",
payload: { config: FIREBASE_CONFIG },
});
}
}
};
--
This way, when the registered SW is ready, Firebase is initialized at the App and Service Worker scopes.

Firebase Cloud Firestore Admin SDK issue

I am trying to update a Firebase document by first logging in with the admin account using Firebase Auth SDK.
Next I use the Firestore SDK to pull down the different parts of data needed from that plan.
Then push them back up to the new plan. So it’s essentially duplicating the plan.
The way I used to do it was in a self invoking function at the bottom of a HTML and just load the SDKs from their CDN.
Instructions to setup and links to CDN: https://firebase.google.com/docs/web/setup
If you try doing the
const firebaseConfig = {
apiKey: 'api-key',
authDomain: 'project-id.firebaseapp.com',
projectId: 'project-id',
}
firebase.initializeApp(firebaseConfig);
var db = firebase.firestore();
db.collection("users").get().then((querySnapshot) => {
querySnapshot.forEach((doc) => {
// console.log(`${doc.othre} => ${doc.data()}`);
console.log(doc);
});
})
i get the follow error
Uncaught (in promise) FirebaseError: Missing or insufficient permissions.
If you want to use the Admin SDK from a server, please look at the doc for more details, in particular firebase.google.com/docs/admin/setup#prerequisites.

"Request is missing authentication credential" error when calling firebase.messaging.getToken()

I am following the tutorial to add push notifications to a web app, including calling firebase.messaging.usePublicVapidKey with the VAPID key. However, when I'm calling getToken I get the following error:
Request is missing required authentication credential. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project
I am already using VAPID key and nowhere in the tutorial did Google say that a Google OAuth login was required. How can I fix this?
var messaging = firebase.messaging();
messaging.usePublicVapidKey('redacted');
function obtenerToken() {
messaging.getToken().then(function (nuevoToken) {
if (nuevoToken) {
token = nuevoToken;
} else {
messaging.requestPermission().then(obtenerToken)
.catch(function (err) { console.log('La web no tiene permiso para recibir notificaciones ', err); });
}
}).catch(function (err) { console.log('Error al obtener token de Firebase ', err); });
}
obtenerToken();
Clear your site data!
After struggling with this for some time I cleared my site data and the auth error did not occur again. We use Firestore with custom auth tokens to retrieve realtime data in another part of the site and I suspect it caused the problem.
Did you initialize with a Firebase configuration object?
import firebase from "firebase/app";
import "firebase/messaging";
const firebaseConfig = {
apiKey: "api-key",
authDomain: "project-id.firebaseapp.com",
databaseURL: "https://project-id.firebaseio.com",
projectId: "project-id",
storageBucket: "project-id.appspot.com",
messagingSenderId: "sender-id",
};
if (!firebase.apps.length) {
firebase.initializeApp(firebaseConfig);
}
let messaging;
try {
messaging = firebase.messaging();
messaging.usePublicVapidKey("publicVapidKey");
} catch (e) {
messaging = null;
}
Have you set whitelist your production domain for browser API keys and client IDs in the Google Developer Console?
Did you setup firebase-messaging-sw.js file?
Like this.
// change your using firebase version
importScripts("https://www.gstatic.com/firebasejs/5.10.0/firebase-app.js");
importScripts("https://www.gstatic.com/firebasejs/5.10.0/firebase-messaging.js");
const messagingSenderId = "your sender id here";
firebase.initializeApp({ messagingSenderId });
try {
const messaging = firebase.messaging();
} catch (e) {}
See:
https://firebase.google.com/docs/web/setup
https://firebase.google.com/support/guides/launch-checklist
https://github.com/firebase/quickstart-js/tree/master/messaging
https://github.com/firebase/quickstart-js/blob/master/messaging/firebase-messaging-sw.js
If does not work then you should try quickstart.
Managed to fix the issue. It turns out I copied the config from one project and the VAAPI key from another project. D'oh!
I ran into the same issue, for a different reason. We are using two Firebase projects (one dev, one production). The two apps are configured in the same config file. I just learned that the firebase.messaging() function can accept one parameter: the initialized Firebase App. Without this parameter, const devMessaging was configuring with the default app settings, in my case production. Here is the fixed code:
export const app = firebase.initializeApp(config);
export const devApp = firebase.initializeApp(devConfig, "secondary");
const devMessaging = firebase.messaging(devApp);
devMessaging.usePublicVapidKey("this_is_private");
devMessaging.getToken().then(() => {
// continue with the rest of the code
});
resource: https://firebase.google.com/docs/reference/js/firebase.messaging

Trying to authenticate with signInWithCustomToken with strange errors

I am trying to authenticate admin to enable write access to Firebase DB.
I wanted to create a custom UID, which would only be passed to admin account which would then verify itself as write access account with the DB rules set to:
"rules": {
".read": true,
".write": "auth.uid === 'some_uid'"
}
I tried the recomended way of first intializing app with:
this.config = {
apiKey: api_key
authDomain: auth_domain
databaseURL: db_url
messagingSenderId: ...
projectId: ...
storageBucket: ...
token: ...
}
firebase.initializeApp(this.config)
And then passing the token returned previously from server to the createCustomToken() function to create an UID and log-in the user with it.
firebase
.auth()
.createCustomToken(this.config.token)
.then((token) => {
firebase.auth().signInWithCustomToken(token)
.then(() => {
...some logic
})
.catch(function(error) {
console.log(error)
})
})
I get TypeError: firebase.auth(...).createCustomToken is not a function
I know I am initializing the app correctly, because if I delete the steps with tokens, ie: createCustomToken and signInWithCustomToken and just run my logic, which fetches data from firebaseDB, then everything works.
So the question is, how am I initializing it wrong, if the firebase.auth(...) doesnt have function createCustomToken on it, but the docs say it does.
You are mixing the Admin and client SDKs. createCustomToken is in the Admin SDK. The signInWithCustomToken is in the client SDK.
You would typically mint the custom token with the admin SDK on the server and then send it back to the client to complete sign in using client SDK.

Firebase credentials don't work when authenticated

I'm trying to implement an authentication for firebase in my react app. I do that with github but it's not relevant.
So I have some credentials and they work just fine. I can fetch my data from db and manilpulate it.
Until I login...
After successfully executing this: firebase.auth().signInWithPopup(githubProvider).then ...
I start constantly receiving warnings of that kind:
FIREBASE WARNING: Provided authentication credentials for the app named "[DEFAULT]" are invalid. This usually indicates your app was not initialized correctly. Make sure the "apiKey" and "databaseURL" properties provided to initializeApp() match the values provided for your app at https://console.firebase.google.com/.
I can't do anything to my DB.
And this continues until I log out with firebase.auth().signOut().then ... then everything works fine again.
inb4: I am 100% confident that my credentials are correct. I have copied and pasted them several times.
Can someone give me insight on what is going on in that case?
And here's how I initialize the App
import firebase from 'firebase';
try {
const config = {
apiKey: process.env.REACT_APP_FIREBASE_API_KEY,
authDomain: process.env.REACT_APP_FIREBASE_AUTH_DOMAIN,
databaseURL: process.env.REACT_APP_FIREBASE_DATABASE_URL,
projectId: process.env.REACT_APP_FIREBASE_PROJECT_ID,
storageBucket: process.env.REACT_APP_FIREBASE_STORAGE_BUCKET,
messagingSenderId: process.env.REACT_APP_FIREBASE_MESSAGING_SENDER_ID,
};
firebase.initializeApp(config);
} catch (e) {}
export const githubProvider = new firebase.auth.GithubAuthProvider();
export const firebaseRef = firebase.database().ref();
export default firebase;

Categories

Resources