Tuesday, 28 February, 2017 UTC


Summary

While React Native brings many efficiencies, it can also be complicated to work with when it comes to developing authentication and user management functions. (React Native is a Javascript framework designed to improve users’ ability to create cross-platform applications with native UI performance.) With React Native, everything needs to be built from scratch—from screen navigation and a responsive interface to creating and wiring up a user management backend. Enter Stormpath!
This tutorial will walk you through how to use Stormpath to add authentication and user management to your React Native application with ease. With Stormpath you’ll add library-free navigation, and create a responsive, networked user interface, all without needing to touch your own backend!
To complete this tutorial, sign up for a forever-free developer account with Stormpath. Stormpath is free to use, and can help your team write a secure, scalable application without worrying about the nitty-gritty details of authentication, authorization, and user security - or managing a backend user database. Sign up for an account today!
If you want to jump ahead, you can grab the source code from GitHub. Let’s get started!
Create Your Base Project
Start by installing the React Native command line interface (CLI) using npm and set up a skeleton project.
$ npm install -g react-native-cli
$ react-native init ReactNativeStormpath
After entering the created directory, install packages (with either npm install or yarn, which is faster) and run the project. This tutorial deploys to Android but iOS will work as well.
$ cd ReactNativeStormpath
$ yarn
$ react-native run-android
To ensure execution works set up Android on your system and have either a device attached or an emulator running. When successful you should see the stock welcome screen.
Add Easy Navigation with React Native
Navigation in React Native is quite an involved affair. Using either built-in or external libraries you define your aplication’s screens and the permissable routes between them using a Navigation Component, with each library sporting various design requirements and caveats.
It needn’t be so complicated. If you just need to switch between views you can simply use a single state variable and some callbacks (and no esoteric libraries or components).
Create two empty components, Login and Secured. Inside the main script (index.android.js) use a state variable to decide which of these components is returned by the main render, and inside each pass functions needed to switch the variable appropriately.
import React, { Component } from 'react';
import {
  AppRegistry
} from 'react-native';

import Login from './src/screens/Login';
import Secured from './src/screens/Secured';

class ReactNativeStormpath extends Component {

  state = {
    isLoggedIn: false
  }

  render() {

    if (this.state.isLoggedIn) 
      return <Secured 
          onLogoutPress={() => this.setState({isLoggedIn: false})}
        />;
    else 
      return <Login 
          onLoginPress={() => this.setState({isLoggedIn: true})}
        />;
  }

}

AppRegistry.registerComponent(ReactNativeStormpath , () => ReactNativeStormpath );
The secured page is passed a function to logout which switches the view back to the login page. Similarly the login page is passed a function which switches the view to the secured page.
To finish, all that’s needed is to fill out these pages and connect buttons inside them to the passed in functions.
Set Up Your Login Page
The login component just needs username and password text inputs and a button (and perhaps a title to make everything look professional).
import React, { Component } from 'react';
import {
    ScrollView,
    Text,
    TextInput,
    View,
    Button
} from 'react-native';

export default class Login extends Component {

    render() {
        return (
            <ScrollView style={{padding: 20}}>
                <Text 
                    style={{fontSize: 27}}>
                    Login
                </Text>
                <TextInput placeholder='Username' />
                <TextInput placeholder='Password' />
                <View style={{margin:7}} />
                <Button 
                        onPress={this.props.onLoginPress}
                        title="Submit"
                    />
                </ScrollView>
            )
    }
}
Note how when the button is pressed the switching function is called.
Set Up Your Secured Page
In the secured component put a welcome message and a logout button (which calls it’s own switch function).
import React, { Component } from 'react';
import {
    ScrollView,
    Text,
    View,
    Button
} from 'react-native';

export default class Secured extends Component {
    render() {
        return (
            <ScrollView style={{padding: 20}}>
                <Text 
                    style={{fontSize: 27}}>
                    Welcome
                </Text>
                <View style={{margin:20}} />
                <Button
                            onPress={this.props.onLogoutPress}
                            title="Logout"
                     />
                </ScrollView>
                )
    }
}
Add Navigation Logic
As simple as that you have a login and secured page with navigation between the two!
Set Up Stormpath for Secure User Management
Stormpath is an API that helps developers manage users in their applications (without needing to create a backend). Follow these steps to set up Stormpath for the first time: Browse to: https://api.stormpath.com/register to register for an account.
You'll see a confirmation screen and you’ll receive an email at the address you put in to verify your account. Click the friendly green button in your email to verify your account.
Now, you can login to your newly created Stormpath account.
Next, Create an account in the default My Application Stormpath Application. You’ll use this account to login from the React Native app. Browse to: Applications -> My Application ->Accounts -> Create Account. Fill out the form and click the Create button.
The last step is to make note of your Client API DNS label. You can find this by clicking on Applications -> My Application -> Policies -> Client API. You’ll see DNS Label field. It will be something like: {DNS-LABEL}.apps.stormpath.io. You’ll need this address later when configuring your React Native app to connect to Stormpath.
Just like that you can now make authentication requests (defined in the Client API documentation) to https://{DNS-LABEL}.apps.stormpath.io/{endpoint}.
Modify Your Application UI to Make Requests
React Native uses the Fetch API for networking. To use it you need to modify the login component to respond to each request.
Put the following at the top of the component:
state = {
username: '',
    password: '',
    isLoggingIn: false,
    message: ''
}
username and password store the contents of the text inputs. To fill these variables you need to use the OnChangeText property. For example in the username component:
 this.setState({username})}
/>
isLoggingIn tracks whether logging in is in progress. When true an activity spinner can be shown by embedding a JSX expression. Put the following above the button component:
{this.state.isLoggingIn && <ActivityIndicator />}
The sign in button itself should be disabled both whilst logging in and if either the username or password fields aren’t set.
<Button 
disabled={this.state.isLoggingIn||!this.state.username||!this.state.password}
onPress={this._userLogin}
title="Submit"
/>
Note that on press is set to call this._userLogin. message stores any error message returned from logging in. It can be displayed by putting the following above the button as well:
{!!this.state.message && (
<Text
        style={{fontSize: 14, color: 'red', padding: 5}}>
        {this.state.message}
    </Text>
)}
Now for _userLogin. First reset the relevant states:
    _userLogin = () => { 

        this.setState({isLoggingIn: true, message:''});
Then create the data object to be sent to the API:
        var params = {
            username: this.state.username,
            password: this.state.password,
            grant_type: 'password'
        };
Next URL encode the parameters so they can be sent as application/x-www-form-urlencoded ([as required when getting an OAuth token from the Client API).
        var formBody = [];
        for (var property in params) {
          var encodedKey = encodeURIComponent(property);
          var encodedValue = encodeURIComponent(params[property]);
          formBody.push(encodedKey + "=" + encodedValue);
        }
        formBody = formBody.join("&");
Finally, call the Stormpath application URL using the Fetch API.
        var proceed = false;
        fetch("https://”+Environment.CLIENT_API+”/oauth/token", {
            method: "POST", 
            headers: {
              'Content-Type': 'application/x-www-form-urlencoded'
            },
            body: formBody
          })
          .then((response) => response.json())
          .then((response) => {
            if (response.error) this.setState({message: response.message});
            else proceed = true;
          })
          .then(() => {
            this.setState({isLoggingIn: false})
            if (proceed) this.props.onLoginPress();
          })
          .done();
Here Environment.CLIENT_API pulls in the DNS entry name you saved, which you need to put into Environment.js in the root folder. Javascript Promises handles the network call. Each then happens in sequence after the initial call:
  1. Get the initial JSON response
  2. Convert it to an object
  3. Set message if there was an error
  4. Run this.props.onLoginPress() if authentication successful, to switch the page
With this complete, your application should authenticate correctly and display any error messages the Stormpath servers send back.
Your New React Native Application with Auth and User Management
After some cosmetic changes such as clearing the text inputs when selected and securing the password field (see the source code for these) you should have the following login process:
Features like user registration and token-secured access control are easy to add on, once you have this initial application built. Check out these resources to learn more about how Stormpath supports these, and much more:
  • Token validation with Stormpath
  • Tutorial: Build a React.js Application with User Login & Authentication
  • Add Facebook Login to Your Existing React Application
  • Build an Android App with Secure User Authentication
  • Build vs. Buy, or, Why Rolling Your Own Might Not Be the Right Solution