DEV Community

Clint Maruti
Clint Maruti

Posted on • Edited on

Authenticate React App With Stormpath - Part One

React is a Javascript 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

Next, we can go ahead and hook this up to our Stormpath Application by creating a new file stormpath.yml with the following code in it. Of course, you have to replace the values 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, you can give yourself a thumbs up for that. You've earned yourself a badge for successfully configuring 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 earlier, 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 (don't worry, 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 add a few lines on top of the scripts in server.js file:

   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 them 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 by creating a new file .babelrc and adding this code:-

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

Finally, we need to 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 serve 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 the HTML-5 Boilerplate extension to easily generate the HTML 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

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

A Little Bit on How React Works

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 , componentWllMount, componentWillUnmount etc. To give you a glimpse of this, let's create a simple React Component counter that starts counting immediately 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

So now let's try to understand this. 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 like this:

   <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. like this:

   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 that 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 (3)

Collapse
 
alexstaroselsky profile image
Alexander Staroselsky • Edited

This is a really great guide for Stormpath and React, but Stormpath no longer exists as a company as it has been purchased by Okta. In fact if you go to the Stormpath site, it indicates "Stormpath has joined forces with Okta. The Stormpath API shut down on August 17, 2017". The stormpath NPM module as well as stormpath-react haven't been published/updated in 3+ years. Iā€™d really recommend reviewing the Okta documentation instead. This is just a warning and not a reflection of the quality of this guide/post.

Collapse
 
clintdev profile image
Clint Maruti

Thanks Alexander,
I appreciate. Let me review

Collapse
 
chrisachard profile image
Chris Achard

Nice overview of starting a new React app!

I hadn't seen Stormpath before - thanks for pointing that out :)