I have an API which uses the node admin sdk to connect and call to firebase. My clients hit my api for all the things they need. I do not want them to have to call out to firebase to authenticate directly because I want the client code decoupled from the api and backend.
How can the server authenticate them? Based on current docs even at minimum clients must provide their uid to the api (which assumes they authenticated on their own, right?).
Ideally, the clients would provide username and password in the body of a POST over ssl to my api and the api would log them in and send back their id token. What would be the recommended way to do this?
The Firebase service also offers a client-side based system for performing user authentication, or allowing users to “sign in” to your application and have particular information associated with them.
No Firebase Authentication…To use the Firebase Storage we need to authenticate a user via Firebase authentication. The default security rules require users to be authenticated. Firebase Storage is basically a powerful and simple object storage, in which you can store your files easily.
Just wanted to provide an update: an answer to this with undocumented REST API's can be found here: Firebase REST auth when creating token with node.js admin sdk
If I could I would mark this as the answer.
If you want to use Firebase for authentication, it is best handled on the client side by a client SDK. This is because authentication is rate-limited based on IP address and it also allows you to skip the process of coding in session management and persistence.
However, you can achieve what you want if you expect a low number of logins/users by hosting the client SDK on your server and hand-balling the request off to Firebase.
// app.js
const bodyParser = require('body-parser');
const cookieParser = require('cookie-parser');
const express = require('express');
const firebase = require('firebase'); // client SDK
firebase.initializeApp({
apiKey: "<API_KEY>",
authDomain: "<PROJECT_ID>.firebaseapp.com"
});
const app = express();
app.use(bodyParser.json());
app.use(cookieParser(['array', 'of', 'secrets']));
// on future requests, the UID can be found using `req.cookies['__session'].uid`
app.post('/login', function (req, res, next) {
if (!req.body.email) return res.status(400).json({error: 'missing email'});
if (!req.body.password) return res.status(400).json({error: 'missing password'});
firebase.auth().setPersistence(firebase.auth.Auth.Persistence.NONE) // don't persist auth session
.then(function() {
return firebase.auth().signInWithEmailAndPassword(req.body.email, req.body.password)
});
.then((user) => { // https://firebase.google.com/docs/reference/js/firebase.User
let uid = user.uid;
// set cookie with UID or some other form of persistence
// such as the Authorization header
res.cookie('__session', { uid: uid }, { signed: true, maxAge: 3600 });
res.set('cache-control', 'max-age=0, private') // may not be needed. Good to have if behind a CDN.
res.send('You have successfully logged in');
return firebase.auth().signOut(); //clears session from memory
})
.catch((err) => {
next(err);
});
});
module.exports = app;
Note: You may also consider co-locating your API using Cloud Functions. Depending on your use case, this may be the cost effective option.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With