Firebase Admin SDK to Log user in from Server - node.js

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

Related

Method Creating custom tokens will create uid if not exist in firebase

I using firebase. I using method: Creating custom tokens. When i look document in firebase https://cloud.google.com/identity-platform/docs/admin/create-custom-tokens .
const uid = 'some-uid';
admin
.auth()
.createCustomToken(uid)
.then((customToken) => {
// Send token back to client
})
.catch((error) => {
console.log('Error creating custom token:', error);
});
I have a question
If i don't have uid in firebase, it will create it ? If i have uid, i only create custom token and send back to client. I look document and i don't see document specific it. Thanks
There is no need to make an API call to create a user in Firebase when you're using custom authentication. Calling createCustomToken on the server, and then signing on the client with the resulting ID token, is all that is needed.
There is no separate step to create the UID for a custom provider. You create the custom token with the UID and other claims you want, send it to the client over a secure connection, and the client can then sign in to Firebase with that token.
For Firebase services the ID token, and the UID in it, are ephemeral - since it is your server (where you run the Admin SDK), and the client that maintain them. That's the reason a separate step to create the UID in Firebase is not necessary.

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 Token is being generated with invalid signature

I have created an App using the Parse server, and have now decided to implement some aspects of firebase into my app. Im trying to accomplish this by doing the signInWithCustomToken method in swift on ios. Im calling a rest service to generate a firebase token, and then signing in with that token returned upon valid sign in on my current auth system. However, the token being generated appears to have an invalid signature when pasting it into jwt.io. The environment that im using is node based (inside the parse server). It seems very simple and i have followed the firebase instrucutions/poured over questions on this over the last few days and im really not sure what im doing wrong! Heres my rest service on how i generate the token, i initialize the server with this method:
Parse.Cloud.define("initServer", function(request, response){
var admin = require('firebase-admin');
var serviceAccount = require('/home/bitnami/apps/parse/htdocs/firebase/serviceAccountKey.json');
console.log(serviceAccount);
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: 'https://urabo-acb7a.firebaseio.com'
});
response.success("Server Init OK");
});
this is the post method i call to generate the token from firebase-admin sdk:
Parse.Cloud.define("generateFirebaseToken", function(request, response) {
var admin = require('firebase-admin');
admin.auth().createCustomToken(request.params.uid)
.then(function(customToken) {
// Send token back to client
response.success(customToken);
})
.catch(function(error) {
console.log("Error creating custom token:", error);
});
});
And of course I went into the firebase console and generated the private key, and then scp'd it over to my server. Im not really sure why this is not working, it generates a token it just doesnt appear to be valid or linked to my account. Am i missing some weird encoding issue or something with the token? Does anyone have insight on this?? Thanks so much!
—The main question is are your users signing in to the REST service through your app and then you are also trying to re-authenticate them again with the token generated in your system?
—If they will be accessing further REST functions once authenticated, then why not authenticate them successfully when 'a' token is returned?
—Usually token usage or handling is restricted by the API providers. Another option is instead of involving user auth directly with the API service, have a separate auth system — the usual SignIn process and then make API calls based on the requested API feature. That way your app is interacting with the APIs and users remain at the front end.

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

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?

NodeJS authentication with Firebase

I would like to authenticate and keep sessions via NodeJS with Firebase. Client can't directly communicate with Firebase.
In short:
Client (browser) <----> NodeJs(firebase-admin) <----> Firebase
I created Firebase client in NodeJS, then I used login method:
var firebaseClient = require('firebase');
firebaseClient.initializeApp(config)
firebaseClient.auth().signInWithEmailAndPassword(req.body.email, req.body.password).catch(function(error){
console.log(error);
})
and then I created route to check authenticated user:
app.get('/check',function(req,res){
var user = firebaseClient.auth().currentUser
console.log(user)
})
This method only allows me keep 1 previously logged user.
I would like to use firebase-admin, but I don't know how to keep session and authenticate users
You can authenticate clients on their respective devices/browsers using the client SDK, and them get them to send an ID token to a backend service written using firebase-admin (the admin SDK). The admin SDK provides methods for validating ID tokens sent by clients: https://firebase.google.com/docs/auth/admin/verify-id-tokens

Resources