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
Related
I'm looking for a way to send user's email and password from the client to my Firebase Backend Functions and make the login from the backend, I find out info about Id tokens and stuff like that, but I need just simple function that receives email and password and make the request to Firebase Auth.
On firebase late versions you might have something like "signInWithEmailAndPassword(email, password)", So I'm looking the exact operation just for the SDK for node.js, and I dont seems to find one.
Thank you.
Firebase Auth only allows you to use signInWithEmailAndPassword on client side.
You should not authenticate users on backend (although it's possible), because it might have unintended consequences, but you can authenticate user with signInWithEmailAndPassword on the browser and then verify "ID Token" to your backend.
Frontend (using firebase):
const payload = {
uid: user.id,
idToken: await user.getIdToken()
}
//send payload to server
Backend (using firebase-admin):
const decodedToken = await getAuth(app).verifyIdToken(body.idToken)
//check decodedToken.uid equals body.uid
You can read more into "ID token verification" here:
https://firebase.google.com/docs/auth/admin/verify-id-tokens#web
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.
i am checking if the user is logged
const firebase = require('firebase-admin')
firebase.auth().onAuthStateChanged((user) =>{
console.log('message1', user)
if (user) {
console.log('exist')
} else {
console.log('not exist')
}
});
but i only get error: Error: FIREBASE_ERROR
You are using the Admin SDK, which has no concept of a signed-in user. All code in the Admin SDK runs under an administrative account, not under a Firebase Authentication user's credentials.
If you want to determine what user is logged in on a client, that is then communicating with the process that runs the Admin SDK, you can do so by getting the ID token for the user on the client, sending that to the server, and decoding and verifying the ID token on the server.
Also see:
Node.JS Firebase Auth - Is there a way to keep a user session like with client side Firebase Auth?
How to check if user is authenticated in Firebase and Express/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)})
How do i get currentUser in firebase admin SDK. In client SDK we can use
onAuthStateChanged() or firebase.auth().currentUser()
In NodeJs Server.js file firebase admin SDK onAuthStateChanged() Do not work, what should work here?
Basically i want only logged in users to access my innerPages so i am using express,nodejs app.get method to create routes.
app.get('/', authenticationRequired ,function(req,res){
res.sendFile(path.join(__dirname+'/index.html'));
});
And trying to write authenticationRequired method (returns false or true depending on if user is logged in).
The Firebase Admin SDK does not inherently know what user is using your Express web app. You will need to implement code for this. If you're already using Firebase Authentication in the web app, this takes these steps:
Retrieve the user's ID token on the client
You can get a user's ID token by using the firebase.auth().currentUser.getIdToken() method.
Pass this token from the client to the server
Verify the token on the server
The user ID token can be verified using the admin.auth().verifyIdToken(idToken) method. On success it will return a promise with the decodedToken, otherwise it will return a rejected promise.