DEV Community

Clint Maruti
Clint Maruti

Posted on

Authenticate React App With Stormpath

React is an awesome Library that helps break down complex UI into simple and reusable components that can be composed together. I will show you how to build a react app from scratch, using the Stormpath React SDK to add sign up, login and view profile features.

Let's get started!

You'll first need to create a Stormpath account and application, which you can do here: https://api.stormpath.com/register

Stages we are going to cover:-

  • Install the React + Express.js Application Stack
  • Set up the React + Express.js Project
  • Master Page
  • Index Page
  • Login Page
  • Registration Page
  • Profile Page
  • Home Route
  • Logout
  • User State in Components
  • Import Components
  • Run The project
  • Wrapping Up

Install the React + Express.js Application Stack

In this tutorial, we will use ES6 and JSX to write as little code as possible as well as Stormpath React SDK for user features.

Here's a break down of what we will use:-

  • React - Allows us to compose simple yet powerful UIs.
  • ReactRouter - Organizes the URL navigation in our React application.
  • ES6 - The next version of JavaScript. Allows us to write real JavaScript classes.
  • JSX - Allows us to place HTML in JavaScript without concatenating strings.
  • Stormpath - Allows us to store and authenticate users without having to create our own backend for it.
  • Stormpath React SDK - Integrates Stormpath into our React application with very little effort.
  • Express - Allows us to serve our HTML and JavaScript files.
  • Express Stormpath - Allows us to serve Stormpath's API through Express.
  • Webpack - Allows us to pack all of our JavaScript files into one bundle.
  • Babel - Allows us to transpile our ES6 and JSX into ES5.
  • Bootstrap - Because we want things to be pretty.

Set up the React + Express.js Project

Create a directory where your project will sit

   $ mkdir my-react-app
   $ cd my-react-app
   $ npm init --yes
Enter fullscreen mode Exit fullscreen mode

Install Express and the Stormpath module for Express:

  $ npm install --save express express-stormpath body-paser
Enter fullscreen mode Exit fullscreen mode

Next, we will create a server to host our application. Create a new file server.js and paste the code below:

const express = require('express');
const stormpath = require('express-stormpath');

const app = express();

app.use(stormpath.init(app, {
   web: {
      produces: ['application/json']
   }
}));

app.on('stormpath.ready', function(){
   app.listen(3000, 'localhost', function(err){
      if(err){
         return console.error(err)
      }
      console.log('Listening at http://localhost:3000')
   });
});
Enter fullscreen mode Exit fullscreen mode

Okay, now we can go ahead and hook this up to a Stormpath Application by creating a new file stormpath.yml with the following code in it. Note, you do have to replace those values in it with your own.

   client:
      apikey:
         id: YOUR_API_KEY_ID
         secret: YOUR_API_KEY_SECRET
   application:
      href: https://api.stormpath.com/v1/applications/XXXX <-- YOUR APP HREF
Enter fullscreen mode Exit fullscreen mode

Try the server by running $ node server.js. If everything is set up correctly, you'll see:-

Listening at http://localhost:3000
Enter fullscreen mode Exit fullscreen mode

Great, give yourself a thumbs up for that. You've earned yourself a badge for successfully configured your server to communicate with Stormpath and expose a REST API for your React.

Configure Webpack

Moving on swiftly, terminate the server so that we can install the Webpack package. As we mentioned up there, Webpack is going to package all of our client-side scripts. We will need this organization soon!

$ npm install --save webpack
$ npm install --save-dev webpack-dev-middleware
Enter fullscreen mode Exit fullscreen mode

We will configure Webpack by creating a new file named webpack.config.jsby inserting the code below:

const path = require('path');
const path = require('webpack');

module.exports = {
   entry: [
      './src/app'
],
devtool: 'eval-source-map',
output: {
   path: __dirname,
   filename: 'app.js',
   publicPath: '/js/'
},
module: {
   loaders: []
 }
};
Enter fullscreen mode Exit fullscreen mode

So let's dissect this code:-
What this code does, is that it will look in our /src/ directory (we will create that) and package all of the scripts and their dependencies under that directory as one module. Then use the file /src/app.js and its exports as the export of that module. Then finally when it has generated that module package, it will serve that through Express under the /js/app.js endpoint.

In order for Express to serve webpack files, we have to open up server.js and add these lines to the top it:

   const webpack = require('webpack');
   const config = require('./webpack.config');
Enter fullscreen mode Exit fullscreen mode

Then immediately after the line const app = express(); add:

const compiler = webpack(config);

app.use(require('webpack-dev-middleware')(compiler, {
   noInfo: true,
   publicPath: config.output.publicPath
}));
Enter fullscreen mode Exit fullscreen mode

Again, this will allow Webpack to intercept requests and serve our packaged /js/app.js file.

Configuring Babel

Since we will be using ES6 and JSX, we need to transpile these files into ES5 (for backward compatibility with non-modern browsers). Babel does this. It takes ES6/JSX files as input, and convert those to ES5.

So, as usual we are going to install Babel package

   $ npm install --save babel-core babel-runtime babel-loader babel-plugin-react-transform \
  babel-preset-es2015 babel-preset-react babel-preset-stage-0
Enter fullscreen mode Exit fullscreen mode

Next, just as we did with Webpack, we are going to configure babel. Creating a new file .babelrc and add this code:-

{
   "presets": ["stage-0", "es2015", "react"]
}
Enter fullscreen mode Exit fullscreen mode

Finally, we will edit webpack.config.js in order to allow Babel to work with our Webpack. We will add an entry to the module.loaders array:

   module: {
      loaders: [{
         test: /<.js$/,
         loaders: ['babel'],
         include: path.join(__dirname, 'src')
}]
}
Enter fullscreen mode Exit fullscreen mode

Index.html and Bootstrap

Before deep-diving into React and getting ourselves wet, we'll set up the entry page for our app. This page will instruct the browser on what it must load before we initialize React and our application.

Start by creating a new directory build, inside it, create a file index.html. Our server will server all our static files from this folder.

   $ mkdir build
   $ cd build
   $ touch index.html
Enter fullscreen mode Exit fullscreen mode

Within index.html, insert this:

<!doctype html>
<!--[if lt IE 7]><html class="no-js lt-ie9 lt-ie8 lt-ie7"><![endif]-->
<!--[if IE 7]><html class="no-js lt-ie9 lt-ie8"><![endif]-->
<!--[if IE 8]><html class="no-js lt-ie9"><![endif]-->
<!--[if gt IE 8]><!-->
<html class="no-js"><!--<![endif]-->
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <base href="/">
    <title></title>
    <meta name="description" content="">
    <meta name="viewport" content="width=device-width">
    <link rel="stylesheet" href="/css/bootstrap.min.css" />
  </head>
  <body>
    <div id="app-container"></div>
    <script src="/js/app.js"></script>
  </body>
</html>
Enter fullscreen mode Exit fullscreen mode

If you are using Visual Studio Code as your editor, you can install HTML-5 Boilerplate extension to easily generate the script.

Moving on, in the build folder, create a new directory css and download bootstrap files to it.

$ mkdir css
$ cd css
$ curl -O https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css
$ cd ../.. # return to /my-react-app
Enter fullscreen mode Exit fullscreen mode

Alright, in order for our browser to access these files we need to configure them so that they are served through Express. Open up server.js and at the top of the file add:

const path = require('path');
Enter fullscreen mode Exit fullscreen mode

Under the line app.use(stormpath.init(app, ...)); add:

app.get('/css/bootstrap.min.css', function(req, res) {
   res.sendFile(path.join(__dirname, 'build/css/bootstrap.min.css'));
})

app.get('*', function(req,res) {
   res.sendFile(path.join(__dirname, 'build/index.html'));
});
Enter fullscreen mode Exit fullscreen mode

So, How Does React Work?

We now have a skeleton for our app done, next we will focus on building our React app. But before that, let's try to understand React.

Components

In React, everything is built upon components. Think of a component as an element on the DOM e.g. Navigation Bar, Header, Login Form ... etc. A component is basically something that renders a DOM node. A simple React component looks like this:-

class FirstComponent extends React.Component {
   render(){
      return <div>First Component</div>
   }
 }
Enter fullscreen mode Exit fullscreen mode

To render this component to the page, you need to import react and then call it:

ReactDOM.render(
   <FirstComponent />,
   document.getElementById('first-component')
);
Enter fullscreen mode Exit fullscreen mode

And React would render the component to that element.

Of course, there are more things to a React component, such as state. Here is an example of a counter component that starts counting when added to the DOM and stops when removed.

class Counter extends React.Component {
   state = {
      current: 0
   }

   constructor(){
      super();
      this.intervalId = null;
   }

   updateCounter(){
      this.setState({current: this.state.current + 1})
   }

   componentWillMount(){
      this.setState({ counter: this.props.from || 0 });
      this.intervalId = 
      setInterval(this.updateCounter.bind(this), 1000);
   }
   componentWillUnmount(){
      clearInterval(this.intervalId);
   }
   render(){
      return <span>{ this.state.current }</span>
   }
}
Enter fullscreen mode Exit fullscreen mode

The methods componentWillMount() and componentWillUnmount() are life-cycle methods that will be executed at various points of a component's life-cycle (in this case, mount and unmount). The methods are usually used for setting up and tearing down a component and is necessary to use because React will error if you try to set the state of a component when it hasn't been mounted yet.

The member this.props is a collection of all the properties (inputs) passed to a component. Properties of a component can be set as shown below:

   <Counter from="50" />
   <Counter from={ myVariable } />
Enter fullscreen mode Exit fullscreen mode

JSX Variables

Variables can easily be interpolated into your JSX DOM using { nameOfVariable }, e.g. as shown below:

   render(){
      let myVariable = 123;
      return <span>{ myVariable }</span>
   }
Enter fullscreen mode Exit fullscreen mode

JSX and Reserved JavaScript Identifiers

Since JSX is JavaScript, there are some caveats that you need to know when working with React. i.e when setting properties of a React DOM component you cannot use neither for nor class
since those are considered reserved JavaScript identifiers. To get around this problem, React has come with htmlFor and className that you should use instead.

To illustrate the issue, this won't work:

   <label for="my-input" class="my-label">My Input</label>
Enter fullscreen mode Exit fullscreen mode

But this will:

   <label htmlFor="my-input" className="my-label">My Input</label>
Enter fullscreen mode Exit fullscreen mode

Virtual DOM

Instead of working directly against the DOM, in React all components are kept in their own virtual DOM. You can think of the virtual DOM as a DOM implementation in JavaScript (because it actually is). This virtual DOM is then mapped to a real DOM element. So when you render your React component, React will look at the DOM output from the component, compare it to its representation in the virtual DOM, and then generate a patch for the real DOM.

What this means is that you never have to think of manually manipulating DOM elements again. All you have to do is tell React how you want your component to look like, and it will take care of transforming the DOM the ways necessary (with minimal effort).

Installing React Dependencies

Now when we are acquainted with React, we'll kick things off by installing some React dependencies:

   $ npm install --save react react-dom react-router react-stormpath react-document-title history
Enter fullscreen mode Exit fullscreen mode

Before we start coding, we need a place to put our React files, so create a new directory named src, and then use that as your working directory.

   $ mkdir src
   $ cd src
Enter fullscreen mode Exit fullscreen mode

Now, let's start with the entry point of our app. This will be the place where we will set up our React application and its routing. So create a new file named app.js and enter this code:

import React from 'react';
import ReactDOM from 'react-dom';
import { Router, IndexRoute, Route, browserHistory } from 'react-router';

ReactDOM.render(
  <Router history={browserHistory}>
  </Router>,
  document.getElementById('app-container')
);
Enter fullscreen mode Exit fullscreen mode

So now we have a foundation for our application. Let's go ahead and import the Stormpath SDK and some things we'll need in it. At the top of your app.js file, add the import statement:

   import ReactStormpath, { Router, HomeRoute, LoginRoute, AuthenticatedRoute } from 'react-stormpath';
Enter fullscreen mode Exit fullscreen mode

As you can see in app.js there's now two conflicting Router imports. Since ReactStormpath.Router extends from ReactRouter.Router we won't be needing that anymore. So go ahead and remove the Router import from react-router. Important: Leave the other ReactRouter imports, we'll be needing those later.

Now, we'll initialize the Stormpath SDK. Add the following line right above ReactDOM.render().

   ReactStormpath.init()
Enter fullscreen mode Exit fullscreen mode

That was easy! We're now ready to start building our pages on Part Two of this tutorial.

Top comments (0)