August 6, 2020

React Native Authentication with Auth0

React Native Authentication with Auth0

Most sophisticated mobile applications need some sort of authentication to not only secure your application but maybe also other services communicating with the client. I was looking for the most simple way to add some sort of authentication that allows the user to create an account via email and password or with a google account.

After investigating Auth0, I choose their service since I found a React Native guide on how to integrate a simple authentication to your app. I made use of Google Firebase before for authentication but find it a bit cumbersome to set up signing up with Google, also it is relatively expensive compared to Auth0.

So let's start to integrate Auth0 into our freshly installed RN Application.

To generate a new RN application (including typescript) run in your terminal. You can replace "auth0Example" with your own project name.

npx react-native init auth0Example --template react-native-template-typescript

Before running the application ensure all packages are installed correctly by running cd ios && pod install and npm i.

The freshly generated project comes with all kinds of clutter code to display the generic view, we can remove everything in App.tsx and just return a simple view and text component with some placeholder text. Also I like to move my App.tsx into a src folder and change the import in the index.ts.

It should look like this now:

import React from "react"
import { View, Text } from "react-native"

const App = (): JSX.Element => {
    return (
        <View>
            <Text>Auth0 Example</Text>
        </View>
    )
}

export default App

Once we have this, we can now install the dependencies needed for Auth0. To do so, run npm install react-native-auth0 --save and don't forget to update your pods for iOS.

At the Auth0 dashboard we create a new application and make sure the type is set to Native. In the application settings you see a domain field which looks something like this ***.eu.auth0.com. We need the domain for later as well as the ClientID.

Let's now configure Auth0 for iOS, to do so add the following import statement on top of your ios/<project-name>/AppDelegate.m file.

#import <React/RCTLinkingManager.h>

Right above the @end add the following lines:

- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url
            options:(NSDictionary<UIApplicationOpenURLOptionsKey, id> *)options
{
  return [RCTLinkingManager application:app openURL:url options:options];
}

Open now your Info.plist and search for those lines:

<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>

Below those lines you add the following:

<key>CFBundleURLTypes</key>
<array>
    <dict>
        <key>CFBundleTypeRole</key>
        <string>None</string>
        <key>CFBundleURLName</key>
        <string>auth0</string>
        <key>CFBundleURLSchemes</key>
        <array>
            <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
        </array>
    </dict>
</array>

After saving we just need to define our callback and logout url, to do so use the following format {PRODUCT_BUNDLE_IDENTIFIER}://YOUR_DOMAIN/ios/{PRODUCT_BUNDLE_IDENTIFIER}/callback

The {PRODUCT_BUNDLE_IDENTIFIER} should be replaced with your project specific product bundle identifier, you can find it when you open your iOS project file and look under Build Settings/Bundle Identifier. The domain you take from your Auth0 application settings. Then you add this URL to the callback and logout url settings in your application settings.

All you have to do now is add Auth0 to your RN project, like so:

    import Auth0 from 'react-native-auth0';
    
    const auth0 = new Auth0({ domain: 'YOUR_DOMAIN', clientId: 'YOUR_CLIENT_ID' });

To start the login procedure you add the following as onPress handler or in a useEffect hook once your screen is mounted:


auth0
    .webAuth
    .authorize({scope: 'openid profile email'})
    .then(credentials =>
      // Successfully authenticated
      // Store the accessToken
      this.setState({ accessToken: credentials.accessToken })
    )
    .catch(error => console.log(error));

To logout you simple use:


auth0.webAuth
    .clearSession({})
    .then(success => {
        Alert.alert(
            'Logged out!'
        );
        this.setState({ accessToken: null });
    })
    .catch(error => {
        console.log('Log out cancelled');
    });