Using Firebase and Auth0 together

24/10/2017

archer

Firebase has a decent drop in authentication solution, but it lacks many features that a dedicated identity service like Auth0 can provide. So lets join the two. A live demo is available here and the source is available on github.

Prerequisites

Create the token on Auth0

Firebase requires a JWT token for custom authentication, we’ll use an Auth0 rule to create the token and sign it.

Auth0 Rule:

function (user, context, callback) {
    const privateKey = 'FIREBASE_PRIVATE_KEY';
    const email = 'FIREBASE_SERVICE_EMAIL';
    const now = Math.floor(new Date().getTime() / 1000);
    const data = {
        iss: email,
        sub: email,
        aud: "https://identitytoolkit.googleapis.com/google.identity.identitytoolkit.v1.IdentityToolkit",
        iat: now,
        exp: now + 3600,
        uid: user.user_id
    };
    const firebaseToken = jwt.sign(data, privateKey, {expiresInMinutes: 60, algorithm: 'RS256'});
    context.idToken['http://foo/firebaseToken'] = firebaseToken;
    callback(null, user, context);
}

You can generate the key and email by following this guide

Use the token on the client

You should now see the Firebase token in the response to a user authentication. We’ll use the token to sign into firebase:

const ft = authResult.idTokenPayload["http://foo/firebaseToken"];
firebase.auth().signInWithCustomToken(ft).then((user: firebase.User) => {
    ...
    // do stuff
}).catch(function(e) {
    console.log(e);
});

In the demo we persist the token in local storage so that the user doesn’t have to log in while the token is still valid.

Now that you’re authenticated you can use other Firebase services like Firestore. In the demo we use Firestore to retrieve or create user details based on whether we’ve seen the user before. We restrict the user to only their own details by setting up a Firestore rule:

service cloud.firestore {
  match /databases/{database}/documents {
    match /users/{userId} {
      allow read, write: if request.auth.uid == userId;
    }
  }
}