OAuth2 with Firebase Admin Node.js SDK and Firebase Cloud Messaging - node.js

I’m building an app that will use Firebase Admin Node.js SDK (https://github.com/firebase/firebase-admin-node and https://firebase.google.com/docs/admin/setup ) to send push notifications to mobile devices. At the moment for development purposes I’m using the service account from my own Firebase project but intend to allow users to use their own Firebase projects.
To do this, I could get the user’s project id, client email and private key, store them and use them to initialize the Admin object whenever a user wants to send an email:
admin.initializeApp({
credential: admin.credential.cert({
projectId: "<PROJECT_ID>",
clientEmail: "foo#<PROJECT_ID>.iam.gserviceaccount.com",
privateKey:"-----BEGIN PRIVATE KEY-----\n<KEY>\n-----END PRIVATE KEY-----\n"
}),
databaseURL: "https://<DATABASE_NAME>.firebaseio.com"
});
But I’d prefer not to keep this data in my db as well as make it easier for the user to authenticate my app, so I’m exploring the possibility of initializing the admin object using a Google OAuth2 refresh token:
var refreshToken; // Get refresh token from OAuth2 flow
admin.initializeApp({
credential: admin.credential.refreshToken(refreshToken),
databaseURL: 'https://<DATABASE_NAME>.firebaseio.com'
});
My question is, using this way how would I configure the credential to use a specific Firebase project (like with the projectId: "PROJECT_ID" in the admin.credential.cert method above)?
I see in the reference docs for admin.credential (https://firebase.google.com/docs/reference/admin/node/admin.credential) it says that “The refresh token credential does not grant access to every admin API.”
Is it possible to use this flow for Firebase Cloud Messaging and if not, what would be the recommended way forward?

Related

Firebase admin on backend for verifyIdToken and use Firestore

I'm trying to use Firebase Admin on my backend for "faking" client authentication by verifying Id Token in order to use firestore from the backend.
The idea is to use my server as a middleware between my client and firestore.
I can initialize FirebaseAdmin on the backend and verifyIdToken() from client properly, but I don't have an idea for using firestore after that. Can you guys show me a way for doing it?
import * as firebaseAdmin from 'firebase-admin';
import firebaseServiceAccountKey from './firebaseServiceAccountKey.json';
if (!firebaseAdmin.apps.length) {
firebaseAdmin.initializeApp({
credential: firebaseAdmin.credential.cert(
firebaseServiceAccountKey
),
databaseURL: ##########################,
});
}
// This is working
function getUser(token) {
return firebaseAdmin
.auth()
.verifyIdToken(token)
.then((decodedToken) => {
return decodedToken;
})
.catch((error) => {
return error
});
}
/*
Now I want to use Firestore authenticated with this token, should I
import firebase from "firebase"
and then try auth() with token?
*/
Access to Firestore through the Admin SDK always happens with full administrative privileges. There is no way to access Firestore as the user whose token you verified.
If you want to use this middleware approach, you will have to ensure it only accesses data the user is authorized for in the code itself.
Also see:
Pass user auth to Firestore from Cloud functions
How to make Firebase Functions act as a user instead of being an admin?
If the goal is to have tighter control over who can sign in to your app, consider using custom authentication instead - where the server mints a custom token for each user, that the client-side SDK then uses to sign in.

Firebase Admin SDK to Log user in from Server

I have been using Firebase Admin SDK in my Node JS code for authenticating users from the server side.
The Admin SDK provides a method admin.auth().createUser() to create new users.
admin.auth().createUser({
email,
password,
displayName: name
})
.then(function(user) {
console.log("Successfully created new user:", user.uid)
return res.send(user)
})
.catch(function(err) {
console.log("Error creating new user:", err)
return res.send(err)
})
But now how to make a user login like there is a method auth.signInWithEmailAndPassword(email, pass) in the Firebase Client SDK.
There is a method on the firebase admin SDK to get the user info by Email admin.auth().getUserByEmail(email). This method returns all the user information including password but that password is hashed. So now is there any workaround to have a proper authenticate users from Server.
My comment is a bit late but one option would be to use the Firebase REST API directly but integrated into your own server-side API for authentication. And then use a combination of that and the Admin SDK to wrap it all up. REST API docs can be found here https://firebase.google.com/docs/reference/rest/auth/#section-sign-in-email-password. You could keep your client light weight and wrap up all Firebase auth stuff, custom claims, login, logout etc. all through your own API. You would just need to use both methods to do so. This would abstract you away from any dependencies in your app and API as you could put it all in a single service provider. Just food for thought.
There is no way to log a user in with the Admin SDK. The Admin SDK runs with administrative privileges and has no need to log in.
You'll want to use one of the Firebase client-side SDKs (e.g. for Android, iOS or web users) to sign your users in to Firebase directly from the client-side code.
If you want your server-side code to know what user is signed in, you send the token from the client to your server and then decode and validate it there. See the document on verifying an ID token and the sample of server-side authentication with Cloud Functions.
Hi you can use for example in typescript the client sdk in your server side code
import firebase from "firebase/compat/app";
const firebaseConfig = {
apiKey: "",
authDomain: "",
projectId: "",
storageBucket: "",
messagingSenderId: "",
appId: ""
};
firebase.initializeApp(firebaseConfig);
export const authSdk = firebase.auth()
// now you can do
authSdk.signInWithEmailAndPassword(userCredential.email, userCredential.password)
.then(loggedUser => {console.log(loggedUser.user?.uid)})

configuring firebase realtime database

Already i have initialized firebase with firebase functions and deployed. I am using fulfillment and i am not using separate server. i am using firebase only, ie. I have developed javascript code and deployed in firebase itself.
Now I want to configure firebase realtime database with this project.
Can I use below sample code?
var admin = require("firebase-admin");
// Fetch the service account key JSON file contents
var serviceAccount = require("path/to/serviceAccountKey.json");
// Initialize the app with a service account, granting admin privileges
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: "https://databaseName.firebaseio.com"
});
// As an admin, the app has access to read and write all data, regardless of Security Rules
var db = admin.database();
var ref = db.ref("restricted_access/secret_document");
ref.once("value", function(snapshot) {
console.log(snapshot.val());
});
I have few questions:
where to start configuring firebase realtime database?
How to get file "serviceAccountKey.json"? since,i am not using separate server.
How to get database URL?
Did OAuth configuration is required before database?
I believe since V1 you don't need to configure the admin since it takes the config form the server by itself checkout this link for more info https://firebase.google.com/docs/functions/beta-v1-diff#new_initialization_syntax_for_firebase_admin

user logged globally in Firebase/Node.js

I am having a problem with Firebase.
I am trying to use the Node.js (Client), meaning that I am initializing the SDK on Express, and not on the client:
// initializing Firebase Node.js (Client)
const configFb = {
apiKey: "key",
authDomain: "xxx.firebaseapp.com",
databaseURL: "https://xxxx.firebaseio.com",
storageBucket: "xxxx.appspot.com"
};
firebase.initializeApp(configFb);
And I am also using the SDK Admin.
The problem is: Once someone logs in, this user will be the only one logged. If I open the app here, I will be logged with his account. If I sign out, this user will be signed out as well.
What I am doing wrong?
Thanks!
Node.js client SDK was not designed for this. It currently persists the session in memory. Once the user is signed in, you will have to issue your own token and return it to the client or set it in some cookie. You will then sign out that user. Future requests will check the cookie or the token you created. This is a simplistic answer as the sessions could be invalidated and you would lose that capability here. Ideally i would recommend using the client SDK on the browser or the app instead of doing it from a server.

FIREBASE WARNING: Provided authentication credentials are invalid

I am trying to use Firebase in node.js but every time I restart the server I am getting following error:
FIREBASE WARNING: Provided authentication credentials are invalid. This usually indicates your FirebaseApp instance was not initialized correctly. Make sure your apiKey and databaseURL match the values provided for your app at https://console.firebase.google.com/, or if you're using a service account, make sure it's authorized to access the specified databaseURL and is from the correct project.
Following is my index.js:_
var express = require('express');
var router = express.Router();
var mongoose=require('mongoose');
var admin=mongoose.model('admin');
var firebase = require("firebase");
// Initialize the app with no authentication
firebase.initializeApp({
serviceAccount: {
projectId: "...",
clientEmail: "...",
privateKey: "-----BEGIN PRIVATE KEY-----...",
},
databaseURL: "..."
});
console.log("sfsaf")
// The app only has access to public data as defined in the Security Rules
var db = firebase.database();
var ref = db.ref("unitalk-b9145");
var messagesRef = ref.child("messages");
messagesRef.push({
name:"Rupali",
post:"Demo test of firebase"
});
Although I have checked the path of service-account and databaseURl..
Please help..
You can not log in with the service account using the "firabase" package. You need to use the "firabase-admin" package for this. You can find detailed information here (https://firebase.google.com/docs/database/admin/start).
UPDATED: 8 Nov 2016
go to : https://console.firebase.google.com
To use the Firebase Admin SDKs, you'll need a Firebase project, a service account to communicate with the Firebase service, and a configuration file with your service account's credentials.
Navigate to the Service Accounts tab in your project's settings
page.
Select your Firebase project. If you don't already have one, click
the Create New Project button. If you already have an existing
Google project associated with your app, click Import Google Project
instead.
Click the Generate New Private Key button at the bottom of the
Firebase Admin SDK section of the Service Accounts tab.
After you click the button, a JSON file containing your service
account's credentials will be downloaded. You'll need this to
initialize the SDK in the next step.
Sample code;
var admin = require("firebase-admin");
var serviceAccount = require("path/to/serviceAccountKey.json");
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: "https://<DATABASE_NAME>.firebaseio.com"
});
Another method to solve the issue link
for those who still facing this issue, you may try on this method, this is related to the project roles management according to the description inside
For anyone looking at this recently. I had the problem with Firebase function, after changing project. It went away when i removed the keys from admin.initializeApp()
Apparently firebase functions now know to use the project credentials. So just this;
admin.initializeApp();
You are using require('firebase') module so u need the following things:
var config = {
apiKey: " [your api key]",
authDomain: "[projectname].firebaseapp.com",
databaseURL: "https://[projectname].firebaseio.com/",
storageBucket: "[projectname].appspot.com",
messagingSenderId: "[message id]",
};
firebase.initializeApp(config);
If you want to use require("firebase-admin") then you have to configure
serviceAccountKey.json(downloaded file) file ...
I am able to connect with firebase successfully.

Resources