OAuth with Facebook and Google for ReactNative using Passport.js

Includes: definition, usage, flow, setup 3rd Parties, Server & client code

Lara Mo
8 min readFeb 23, 2022

What is OAuth? 🤔

  • It stands for Open Authorization.
  • It’s an approach to authenticate a user using 3rd party services like Facebook, Google, Github, LinkedIn…

When to use? 📈

  • We no longer need to validate a login or sign up form with information that can be given to us by a third party.
  • Use in order to modernize your app and not be limited to a simple username/password kind of login :)

Flow 🌊

I will use Google as the 3rd party in this case

  1. User presses Login with Google button on the client.
  2. Server listens to that request, and redirects the user to Google’s 3rd party authentication form to grant permission for our app to access their information.
  3. Once permission is granted, the server and the 3rd party exchange the user’s profile between them. The server now has access to their firstName,lastName, email and more.
  4. Upon successful exchange of info, the 3rd party will call a redirection URL thats pointing to the your server. It’s up to your server to decide what to do with the data.
    Ex: store in the database, send back to the client, save in session…

Step 1: Set up 3rd party

In this tutorial, I will be setting both Facebook and Google as my 3rd party authentications.
Assumptions:

  • For the purpose of the tutorial, I am going to be using localhost all along. But you should replace localhost to the address you will be hosting your server at.
  • As well, I assume you have setup a client project using ReactNative and a server project using Node.js and Express.

Facebook setup 👤📘

  • Select theFacebook Login product
  • Go to Settings , under Valid OAuth Redirect URI's you will have to enter your redirection URL that will get called as a callback when the information has been successfully exchanged between Facebook (3rd party) and our server. (Step 4 in Flow)

I made the URL as descriptive as possible:

http://localhost:5000/user/login/facebook/callback

  • Go to Settings (under Dashboard on the side menu)→ Basic
    Inside of App domains add localhost
  • Copy the App ID and the App secret , we will use them later.
  • Press Save changes in the bottom.

G⭕O⭕O⭕gle Setup

  • Search for Goolge+ API and enable it.
  • Go back to the Dashboard, click on Go to APIs overview → Credentials and press on ADD CREDENTIALSOAuth Client ID

Note: You have to complete a consent form.
Just fill up the App Name ,User support email and Developer contact information email on the bottom.

  • Now go back to the Credentials Tab, click again on Create Credentials and OAuth Client ID

Here is our redirection URL for Google:
http://localhost:5000/user/login/google/callback
- You may change the name to your own liking.

  • Press Create and copy Your Client ID and Your Client Secret , we will use them in the next step.

Step 2: Setup the Server

  • Install the needed dependencies
npm i --save express cookie-session passport passport-facebook passport-google-oauth20

Passport is an authentication middleware for Node.js.
It has over 500+ strategies including: Local Authentication, Google+, Facebook, Twitter, GitLab, LinkedIn

  • Create a .env file and store the copied values from Facebook and Google earlier.
  • Run npm i --D dotenv , its a dev dependency that allows to load all environment variables from a .env file into process.env
  • Create passportConfig.js to define the configuration for each strategy

Let’s go over this file:

‣ the env values are what we copied from Google’s and Facebook’s console when registering our project.

‣ The callbackURL is what each of this 3rd parties will call when user’s info was successfully exchanged with our server.

‣ If you want to see the email as well as the returned information, you must mention it in the profileFields for Facebook.

  • Create initPassport.js to initialize the strategies by passing it the facebook and google config we created earlier.

Let’s go over this file:

‣ Both strategies accept the config object frompassportConfig.js.

‣ Assume user has granted permission to share their profile. A callback returns:
accessToken: If we want to go back and access more info about the user we will be able to do that.
refreshToken: is used to refresh the accessToken as its expiring after certain amount of time
profile: the information the users allowed to be shared with our server.
done : calling this will redirect the user to the callback URL we defined earlier.

formatFB & formatGoogle are helper methods that I created to format the return object to be the same for every strategy. I personally chose to only use the firstName , lastName and email.

serializeUser is used after successful authentication to persist the user in the session.deserializeUser is used to retrieve user data from session.

  • Lastly, we create our index.js which is the start point to the server app.

Let’s go over this file:

‣ We initialize passport by calling initPassport and passing app to it.
‣ We then define 4 routes:
user/login/facebook & user/login/google will call the passport strategies that will ask the user for permission to share data.

user/login/facebook/callback & user/login/google/callback are the routes that will be called upon successful profile exchange by the 3rd party service and our server.
We will redirect the user back to the client app using a URL. To allow that URL to open our app, we must configure it both on IOS and Android.

‣ add email to both facebook and google scope to have access to the user’s email.

Step 3: Setup Deep Linking

Deep links take users to the correct destination in your app from any online and offline channel including email, social media, referrals, QR codes, and more.
In this case, we use the deep linking mechanism to open our app on the login page. The URL will contain some information about the user that we will use on the client side to login.

Just a little break down of the URL:

memcaps://login?/firstName=${req.user.firstName}/lastName=${req.user.lastName}

memcaps → is the name I chose to refer to my app.
login → is the route I chose to redirect the user to.
firstName,lastName and email are the parameters I chose to return from the user’s profile.

Note: I assume you have routing already setup on the client similar to this:

IOS

  • Open the project in XCode → Info → scroll until URL Types
  • Change urlSchemes to the name you desire, I chose memcaps and will be able to call the deep link like so: memcaps://…
  • Open AppDelegate.m and add #import <React/RCTLinkingManager.h> on the top
  • Add this function to the bottom of the file:

‣ the return part is what enables the deep linking on ios.

Android

  • Add this code to AndroidManifest.xml

android:host="app" and android:scheme="memcaps" with the help of the intent is what allows us to reference our app from an outside source.

‣ Don’t forget to change android:name to your own app name.

App

  • Both platforms are setup. We must let our app know that we want to use deep linking.
    Create a file called linking.js and define your config

Notice how I reference the app with memcaps://app which is what our ios and android are also configured to do.
In this particular config, I decided to only define the Login path that parses the incoming params after the /.

You can define a lot more screen if you need and you can call them by any name.

  • Lastly, reference the linking file in the main Navigator of your app like so:

Step 4: Setup the Client

  • Install this library on the client
npm install --save react-native-safari-view react-native-webview

Just some background:
For deep linking, we usually theLinking.openURL() method.
Apple considers this as bad UX as this doesn't guarantee the user will use the default Safari browser on IOS. Hence why I use this library.
Otherwise, for android we will use react-native-webview.

  • Add 2 buttons like this in your login component

openUrl is a method we will define soon that will call our backend which will trigger the 3rd party authorization form that will look something like this:
Google in this example:

  • In the same Login component, add a useEffect function that listens to “incoming URL’s”.

Let’s go over this file:

useEffect called when the component is about to load, we would want to check if this page was opened from a URL.
That is, we called memcaps://login... to get here.

‣ we use WebView for android but SafariView for ios.
SafariView.dismiss() will get called when info is exchanged successfully and we want to close the browser to go back to the app.
The Webview component doesn't have this kind of method, so we control it with simple useState . That is, we set the URL to '' when we want to close the browser and go back to the app.
Note that openURL is the method that opens the browser in the first place.

handleOpenURL is a method that will accept the URL that looks somewhat like this:

memcaps://login?/firstName=Lara/lastName=Mo/email=laramo@gmail.com

this method will check if those params are defined.
If they are, we use the redux action login to redirect the user to the home page.

And thats it!
Until next time,
Lara

--

--

Lara Mo

Student @Concordia University | Front-end developer @Plusgrade Passionate about React, JS, CSS, HTML and coffee :) | Coding & coffee is my moto ☕👩‍💻