Melvin Koh

Software Engineer. Pythonista, JavaScripter. Find me on Twitter @melvinkcx2 😁

Firebase Auth using Facebook Log-In in Expo, React Native

Originally published on melvinkoh.me
If you are building a pure Expo app, without ejecting it, and are trying to integrate with Firebase Authentication using Facebook Log-In, you are at the right place. In this tutorial, I will be guiding you step by step to set up Firebase Authentication using Facebook OAuth Provider in a Expo project.

Motivation

You do not want to eject your Expo app, but you want to embrace the simplicity of Firebase Authentication using Facebook as OAuth provider.

Limitations

In order to use Firebase Auth without ejecting Expo, the only option, which is also the recommended way is to use the Firebase JavaScript/Web SDK.
Using Firebase JavaScript SDK on React Native means we lose the ability to use the pre-built UI and some other features.

Let’s Get Started!

Step 1: Configure Firebase Project and Facebook App

1. Create a Facebook app, if you haven’t already.
2. Get the App ID and App Secret of your Facebook App
> Facebook App ID and Secret
3. Paste them into your Firebase Console.
> Paste your Facebook App ID and App Secret into your Firebase Console
4. Copy the OAuth redirect URI of your Firebase project and paste it to your Facebook Dev Console.
> Paste your Firebase OAuth redirect URI into your Facebook Dev Console

Step 2: Set up Bundle ID for Facebook App

Add the following into your Facebook Dev Console:
  • iOS Bundle ID:
    host.exp.Exponent
  • Android Key Hashes:
    rRW++LUjmZZ+58EbN5DVhGAnkX4=
> Configure iOS Bundle ID and Android Key Hashes
Up to now, your Facebook app and Firebase project are ready. We can proceed to consume Firebase Auth.

Step 3: Installing and Initializing Firebase in Expo

First of all, install
firebase
:
npm install --save firebase
To initialize Firebase in Expo, I define my Firebase project attributes and Facebook App ID as an
extra
in
app.json
manifest file:
{
  "expo": {
    ...
    "extra": {
      "firebase": {
        "apiKey": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
        "authDomain": "xxxxxxxxxx.firebaseapp.com",
        "databaseURL": "xxxxxxxxxxxxxxxxxxxxxxxxxx",
        "projectId": "xxxxxxxxxx",
        "storageBucket": "xxxxxxxxxx.appspot.com",
        "messagingSenderId": "xxxxxxxxxxxx"
      },
      "facebook": {
        "appId": "xxxxxxxxxxxxxxx"
      },
    }
  }
}
Since Firebase App can only be initialized once, I create a new module
firebase.js
in my Expo project with:
// In /utils/firebase.js
// We should import firebase from this module instead of the default package.
import * as firebase from 'firebase'  // Should not be used elsewhere in the project

firebase.initializeApp(Expo.Constants.manifest.extra.firebase);

export default firebase;
Other parts of our project should no longer import firebase from the default
firebase
package but to import from
/utils/firebase
.

Step 4: Setting Up Your Code

> Flow of log in with Facebook
The logic of logging in with Facebook should be:
  1. User triggers log in
  2. Expo opens up the Facebook App or a pop-up Web View
  3. User authorizes your App
  4. Redirect and return Facebook credentials to your App
  5. Sign in Firebase with Facebook credentials
  6. Done! Your user is now logged in with Facebook.
The code should be:
// Say this is /utils/auth.js
import firebase from './firebase'

export async function signInWithFacebook() {
  const appId = Expo.Constants.manifest.extra.facebook.appId;
  const permissions = ['public_profile', 'email'];  // Permissions required, consult Facebook docs
  
  const {
    type,
    token,
  } = await Expo.Facebook.logInWithReadPermissionsAsync(
    appId,
    {permissions}
  );

  switch (type) {
    case 'success': {
      await firebase.auth().setPersistence(firebase.auth.Auth.Persistence.LOCAL);  // Set persistent auth state
      const credential = firebase.auth.FacebookAuthProvider.credential(token);
      const facebookProfileData = await firebase.auth().signInAndRetrieveDataWithCredential(credential);  // Sign in with Facebook credential

      // Do something with Facebook profile data
      // OR you have subscribed to auth state change, authStateChange handler will process the profile data
      
      return Promise.resolve({type: 'success'});
    }
    case 'cancel': {
      return Promise.reject({type: 'cancel'});
    }
  }
}

Voila!

Here we have our Firebase Auth set up to handle Facebook login in an Expo app.

About Token Refresh

There are 3 types of token involved in our scenario:
  • ID Token -> User’s Firebase auth token
  • Refresh Token -> User’s Firebase refresh token
  • Facebook Short-Lived Access Token -> This is only used once to identify user’s Firebase UID when user log in.
If you are using Firebase Firestore or Realtime Database, you don’t have to bother about refreshing token as they will be taken care of as a prerequisite of maintaining database connection.
If, however, you are using only Firebase Auth, you will need to refresh the token every hour. To refresh user’s auth token, simply run:
firebase.auth().currentUser.getIdToken(true);
If you find this useful, feel free to share it on Twitter!

Tags

More by Melvin Koh

Slack
Integrate Google Calendar
Git
Python
Nodejs
Memory Improvement
Bitbucket
Javascript
Python
Nodejs
Firebase
Postgres
Productivity
Programming
Python
Microservices
Facebook
Javascript
Django
Django
Firestore
Javascript
Vuejs
Jwt
Topics of interest