Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to authenticate a firebase user from server without client side auth?

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?

like image 851
Brian Avatar asked Oct 08 '17 01:10

Brian


People also ask

Is Firebase Auth client side?

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.

Can we use Firebase without authentication?

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.


2 Answers

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.

like image 133
Brian Avatar answered Sep 18 '22 13:09

Brian


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.

like image 42
samthecodingman Avatar answered Sep 20 '22 13:09

samthecodingman