Quantcast
Channel: Blog – Stormpath User Identity API
Viewing all 278 articles
Browse latest View live

Tutorial: Build a React.js Application with User Authentication

$
0
0

React (sometimes referred to as React.js) is an awesome way to build web UIs. Our new React SDK extends React and React Router with routes and components that allow you to solve common user management tasks using Stormpath, such as authentication and authorization.

Lately React has picked up quite some attention, and it’s easy to understand why. React allows you to turn complex UIs into simple and reusable components that can be composed easily together.

This post will show you how to build a React application from scratch, using the Stormpath React SDK to add features that allow people to sign up, login, and even view their own user profile.

Let’s get started!

The React + Express.js Application Stack

Since we’re building our application from scratch, we’ll use ES6 and JSX to write as little code as possible, as well as the Stormpath React SDK for user features.

To give you a good overview of what we’ll be using:

  • 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.

Setting up Our React + Express.js Project

Start by creating a new project directory and a package.json file for it.

1
2
3
$ mkdir my-react-app
$ cd my-react-app
$ npm init --yes

Now install Express and the Stormpath module for Express:

1
$ npm install --save express express-stormpath

We need a server to host our application, so create a new file named server.js and put the code below in it:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var express = require('express');
var stormpath = require('express-stormpath');

var app = express();

stormpath.init(app, {
  website: true
});

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

Awesome. Now we can hook that up to a Stormpath Application by creating a new file named stormpath.yml with the following code in it. And yeah, you do have to replace those values in it with your own.

1
2
3
4
5
6
client:
  apiKey:
    id: YOUR_API_KEY_ID
    secret: YOUR_API_KEY_SECRET
application:
  href: https://api.stormpath.com/v1/applications/XXXX <-- YOUR APP HREF

So far so good. Now try the server by running $ node server.js. If everything is set up correctly then you should see:

1
Listening at http://localhost:3000

If you saw that message, you’ve successfully configured your server to talk with Stormpath and expose a REST API for our React application to use.

Configuring Webpack

Before you get too excited, kill the server and install Webpack so that we can package all of our client-side scripts (we’ll need this organization soon).

1
2
$ npm install --save webpack
$ npm install --save-dev webpack-dev-middleware

Configure Webpack by creating a new file named webpack.config.js and put the code below in it:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var path = require('path');
var webpack = require('webpack');

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

What this will do is look in our /src/ directory (that we’ll create shortly) 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.

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

1
2
var webpack = require('webpack');
var config = require('./webpack.config');

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

1
2
3
4
5
6
var compiler = webpack(config);

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

As I mentioned before, this will allow Webpack to intercept requests and serve our packaged /js/app.js file.

Configuring Babel

Since we’ll be using ES6 and JSX, we need to transpile these files into ES5 (for backwards compatibility with non-modern browsers). This is where Babel comes in. Babel can take our ES6/JSX files as input, and convert those to ES5.

To use Babel, start by installing some dependencies:

1
2
$ npm install --save babel-core babel-runtime babel-loader babel-plugin-react-transform \
  babel-preset-es2015 babel-preset-react babel-preset-stage-0

Now we’ll instruct Babel on how to compile our files, so create a new file named .babelrc and add this code it:

1
2
3
{
  "presets": ["stage-0", "es2015", "react"]
}

Finally, in order to get Babel to work with Webpack, we need to edit webpack.config.js and add an entry to the module.loaders array, as shown below:

1
2
3
4
5
6
7
module: {
  loaders: [{
    test: /\.js$/,
    loaders: ['babel'],
    include: path.join(__dirname, 'src')
  }]
}

Index.html and Bootstrap

Now, before getting our hands dirty with React, we’ll prepare the entry page for our app. This page will tell the browser what it must load before we initialize React and our application. So create a new directory named build, then within that, put a file named index.html. Our server will serve all of our static files from this folder.

1
2
3
$ mkdir build
$ cd build
$ touch index.html

Then within index.html, put the following:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<!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>

Also, under the build directory, create a new directory named css and download Bootstrap to it. Name the file bootstrap.min.css.

1
2
3
4
$ mkdir css
$ cd css
$ curl -O https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css
$ cd ../.. # return to /my-react-app

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

1
var path = require('path');

Then under the line stormpath.init(app, { website: true }); add:

1
2
3
4
5
6
7
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'));
});

How Does React Work?

Now that we have the skeleton for our app done, we can focus on building our React app. But before we write any code, let’s take a look at what React is and what it does for us.

Components

In React, everything is built upon components. You can think of a component as something that renders a DOM node. A simple React component looks like this:

1
2
3
4
5
class HelloWorld extends React.Component {
  render() {
    return <span>Hello World!</span>;
  }
}

That was simple. Now, if you wanted to render this component to a page, then all you’d have to do is import React and then call:

1
2
3
4
ReactDOM.render(
  <HelloWorld />,
  document.getElementById('hello-world-element')
);

And React would render the component to that element.

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class Counter extends React.Component {
  state = {
    current: 0
  }

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

  updateCounter() {
    this.setState({ counter: 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>;
  }
}

Notice the methods componentWillMount() and componentWillUnmount(). These are component life-cycle methods that will be executed at various points of a component’s life-cycle (in this case, mount and unmount). These 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.

Also notice this.props.from. 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:

1
2
<Counter from="50" />
<Counter from={ myVariable } />

JSX Variables

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

1
2
3
4
render() {
  var myVariable = 123;
  return <span>{ myVariable }</span>;
}

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 or class since those are considered reserved JavaScript identifiers. To get around this problem, React has come up with htmlFor and className that you should use instead.

To illustrate the issue, this won’t work:

1
<label for="my-input" class="my-label">My Input</label>

But this will:

1
<label htmlFor="my-input" className="my-label">My Input</label>

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:

1
$ npm install --save react react-dom react-router@1.0.2 react-stormpath react-document-title history@1.13.1

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.

1
2
$ mkdir src
$ cd src

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:

1
2
3
4
5
6
7
8
9
10
import React from 'react';
import ReactDOM from 'react-dom';
import { Router, IndexRoute, Route } from 'react-router';
import createHashHistory from 'history/lib/createHashHistory';

ReactDOM.render(
  <Router history={createHashHistory({ queryKey: false })}>
  </Router>,
  document.getElementById('app-container')
);

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:

1
import ReactStormpath, { Router, LoginRoute, LogoutRoute, AuthenticatedRoute } from 'react-stormpath';

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().

1
ReactStormpath.init();

That was easy! We’re now ready to start building our pages.

Master Page

Before we create our pages, we have to set up our router. The router is what determines how we’ll be able to navigate around in our application. We’ll start by creating a shared root route. This will act as our “master page”. I.e. all routes under this route will all share the same master component (header). So place the codebelow inside the <Router> tag in your app.js so that it looks like:

1
2
3
4
<Router history={createBrowserHistory()}>
  <Route path='/' component={MasterPage}>
  </Route>
</Router>

As you can see, we have referenced MasterPage. Something that doesn’t exist yet. So let’s go ahead and create that in a new directory that we’ll name pages, in our src folder.

1
2
$ mkdir pages
$ cd pages

Now create a new file named MasterPage.js and add this code to it:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import React from 'react';
import { Link } from 'react-router';
import { LoginLink } from 'react-stormpath';
import DocumentTitle from 'react-document-title';

import Header from './Header';

export default class is extends React.Component {
  render() {
    return (
      <DocumentTitle title='My React App'>
        <div className='MasterPage'>
          <Header />
          { this.props.children }
        </div>
      </DocumentTitle>
    );
  }
}

As you can see, we don’t have a Header component yet, so let’s go and create a new file named Header.js in the same directory with the following content:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import React from 'react';
import { Link } from 'react-router';
import { LoginLink, LogoutLink, Authenticated, NotAuthenticated } from 'react-stormpath';

export default class Header extends React.Component {
  render() {
    return (
      <nav className="navbar navbar-default navbar-static-top">
        <div className="container">
          <div id="navbar-collapse" className="collapse navbar-collapse">
            <ul className="nav navbar-nav">
              <li><Link to="/">Home</Link></li>
            </ul>
            <ul className="nav navbar-nav navbar-right">
            </ul>
          </div>
        </div>
      </nav>
    );
  }
}

Index Page

In our MasterPage notice the property this.props.children. This will contain the components of the child routes that our router match. So if we had a route that looked like:

1
2
3
<Route path='/' component={MasterPage}>
  <Route path='/hello' component={HelloPage} />
</Route>

And we tried to access /hello. The this.props.children array would be populated with a HelloPage component and for that reason that component would be rendered in our master page.

Now imagine the scenario where you try to access /. Without any this.props.children, this would only render your master page but with empty content. This is where IndexRoute comes into play. With an IndexRoute you can specify the component that should be rendered when you hit the path of the master page route (in our case /).

But before we add our IndexRoute to our router, let’s create a new file in our pages directory named IndexPage.js and add the following to it:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import { Link } from 'react-router';
import React, { PropTypes } from 'react';
import { LoginLink } from 'react-stormpath';

export default class IndexPage extends React.Component {
  render() {
    return (
      <div className="container">
        <h2 className="text-center">Welcome!</h2>
        <hr />
        <div className="jumbotron">
          <p>
            <strong>To my React application!</strong>
          </p>
          <p>Ready to begin? Try these Stormpath features that are included in this example:</p>
          <ol className="lead">
            <li><Link to="/register">Registration</Link></li>
            <li><LoginLink /></li>
            <li><Link to="/profile">Custom Profile Data</Link></li>
          </ol>
        </div>
      </div>
    );
  }
}

Now let’s add our IndexRoute. Open up app.js and inside the tag <Route path='/' component={MasterPage}> add your IndexRoute so that it looks like the following:

1
2
3
<Route path='/' component={MasterPage}>
  <IndexRoute component={IndexPage} />
</Route>

Login Page

We now have an application that shows a header with a default page. But we don’t have any place to login yet. So let’s create a new file named LoginPage.js and add some content to it:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import React from 'react';
import DocumentTitle from 'react-document-title';
import { LoginForm } from 'react-stormpath';

export default class LoginPage extends React.Component {
  render() {
    return (
      <DocumentTitle title={`Login`}>
        <div className="container">
          <div className="row">
            <div className="col-xs-12">
              <h3>Login</h3>
              <hr />
            </div>
          </div>
          <LoginForm redirectTo="/profile" />
        </div>
      </DocumentTitle>
    );
  }
}

Notice the LoginForm component. This is all we have to add in order for us to have a fully working form in which people can sign up from.

But before we can use it, we need to open up app.js and add a route for the page in our router. So inside the tag <Route path='/' component={MasterPage}> add the following:

1
<LoginRoute path='/login' component={LoginPage} />

In order to be able to access the login page, we need to add this to our menu. So go ahead and open up Header.js and inside the element <ul className="nav navbar-nav navbar-right"> add the following:

1
2
3
4
5
<NotAuthenticated>
  <li>
    <LoginLink />
  </li>
</NotAuthenticated>

As you can see we’re using the NotAuthenticated component. With this we’ll only show a LoginLink when the user isn’t logged in yet.

Registration Page

Now, let’s add a page where people can sign up. We’ll call it RegistrationPage. So create a new file named RegistrationPage.js and put the following content in it:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import React from 'react';
import DocumentTitle from 'react-document-title';
import { RegistrationForm } from 'react-stormpath';

export default class RegistrationPage extends React.Component {
  render() {
    return (
      <DocumentTitle title={`Registration`}>
        <div className="container">
          <div className="row">
            <div className="col-xs-12">
              <h3>Registration</h3>
              <hr />
            </div>
          </div>
          <RegistrationForm />
        </div>
      </DocumentTitle>
    );
  }
}

Notice that we used the RegistrationForm component. As you might have guessed, this will render a Stormpath registration form. And once you’ve signed up it will point users to the login page where they’ll be able to login.

In order to access this page. We need to add a route. So go ahead and open up app.js and inside the tag <Route path='/' component={MasterPage}> add:

1
<Route path='/register' component={RegistrationPage} />

We now have a route, but people won’t be able to find the page unless we link to it, so open up Header.js and add the following right before the closing tag (</ul>) of <ul className="nav navbar-nav navbar-right">:

1
2
3
4
5
<NotAuthenticated>
  <li>
    <Link to="/register">Create Account</Link>
  </li>
</NotAuthenticated>

Notice the use of the NotAuthenticated component. With this we’ll only show the /register link when the user isn’t logged in.

Profile Page

Once a user is logged in, we want to be able to show them some personalized content (their user data). So create a new file named ProfilePage.js and put the following code in it:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import React from 'react';
import DocumentTitle from 'react-document-title';
import { UserComponent } from 'react-stormpath';

export default class ProfilePage extends UserComponent {
  render() {
    return (
      <DocumentTitle title={`My Profile`}>
        <div className="container">
          <div className="row">
            <div className="col-xs-12">
              <h3>My Profile</h3>
              <hr />
            </div>
          </div>
          <div className="row">
            <ul className="list-group">
              <li className="list-group-item">
                <strong>First Name</strong>
                <span className="pull-right">{ this.state.user.givenName }</span>
              </li>
              <li className="list-group-item">
                <strong>Last Name</strong>
                <span className="pull-right">{ this.state.user.surname }</span>
              </li>
            </ul>
          </div>
        </div>
      </DocumentTitle>
    );
  }
}

Notice that we extend from UserComponent. Doing so allows us to access the whole user profile from this.state.user. If there is no user data, then the user state will just be empty.

In order for us to access this page from the menu, open up Header.js and right below <li><Link to="/">Home</Link></li> add:

1
2
3
4
5
<Authenticated>
  <li>
    <Link to="/profile">Profile</Link>
  </li>
</Authenticated>

With this, using the Authenticated component, when we have a user session we’ll render a link to the /profile page and allow our users to view their user profile.

In order for us to be able to access the page, we must as with the other pages add it to the router. Open up app.js and inside the tag <Route path='/' component={MasterPage}> add:

1
<AuthenticatedRoute path='/profile' component={ProfilePage} />

Notice that we’re using AuthenticatedRoute. This is a route that can only be accessed if there is an authenticated user session. If there’s no session, then the user will automatically be redirected to the path of the LoginLink.

Logout

Finally, once our users have signed up and logged in. We want to give them the option to logout. Fortunately, adding this is really simple.

Start by opening up app.js and inside the tag <Route path='/' component={MasterPage}> let’s add a LogoutRoute, as shown below:

1
<LogoutRoute path='/logout' />

In order for our users to be able to logout, they need to be able to access it from somewhere. So go ahead and add it to our menu by opening up Header.js and inside <ul className="nav navbar-nav navbar-right"> add this code to the end:

1
2
3
4
5
<Authenticated>
  <li>
    <LogoutLink />
  </li>
</Authenticated>

Notice the LogoutLink component. This will automatically create a link to the path that you’ve specified for your LogoutRoute.

Importing Components

To be able to reference our pages we need to import them. And in order to make importing easy, we’ll put them all together in an index.js file so we only have to import it once. So let’s create a new file named index.js in our pages directory and export all of our pages from it, as shown below:

1
2
3
4
5
export MasterPage from './MasterPage'
export IndexPage from './IndexPage'
export LoginPage from './LoginPage'
export RegistrationPage from './RegistrationPage'
export ProfilePage from './ProfilePage'

With this, we’ll only have to do one import in order to have access to all of our pages.

So let’s do that. Open up app.js file and at the top of the file, add the following import statement:

1
import { MasterPage, IndexPage, LoginPage, RegistrationPage, ProfilePage } from './pages';

Running The Project

Now we have an application where our users can sign up, login, and show their user data. So let’s try it out!

As before, start our server by running the following:

1
$ node server.js

And if everything is running successfully you should be able to see this message:

1
Listening at http://localhost:3000

So, open up http://localhost:3000 in your browser and try it out!

Summary

As you have seen in this article, React is a really powerful tool and when used together with ES6, JSX and Stormpath, building apps suddenly becomes fun again.

If there are any parts that you feel unsure of, feel free to check out the example project and use that as a reference implementation. I also enjoyed this post on React’s design – it explains in beautiful detail why React is awesome.

And if you have questions regarding the Stormpath React SDK, be sure to check out its API documentation.


Write Once Multi Tenancy with Subdomains and Spring Boot

$
0
0

Java introduced the idea of “Write Once, Run Anywhere”. In this post, you will learn how to “Write Once, Run Any Tenant”. With a single application and some configuration in Stormpath’s Admin Console, your application will be able to support multiple Organizations of users. This is great for SaaS applications who need to securely partition their Customer organizations; each Organization will have no knowledge of or access to the others.

What Is Multi-Tenancy?

Imagine a self-storage company. There’s a large building. Inside the building, there are multiple storage units, each with a lock on the door that only the renter of that unit has access to.

One of the reasons self-storage works so well is that it is easy repeat. Each storage unit is basically the same as the others. Adding a new tenant does not require a whole new large building. It simply requires that a storage unit be allocated to that tenant. It also ensures that each tenant has a protected storage unit, unique to them, and that only they can access.

It’s the same idea for a multi-tenant application. You have one application that can support distinct collections of users. Setting up a new tenant is reduced to a little configuration in an admin console. There’s no need to deploy your application to a new server.

A Multi-Tenant Sample for Spring Boot

Building all this multi-tenant infrastructure yourself from scratch is a royal pain, but multi-tenancy is native to and easily configurable in the Stormpath user model. In this post, we’ll show you how to use it in a Spring Boot app.

We’re going to follow along with a made-up company in this post to demonstrate multi-tenancy. It’s called the Imperial Xchange – your one-stop shop for all your evil apparel needs! In this scenario, we want to keep the Sith Lords separate from the Stormtroopers.

The goal is to deploy the Application once, to allow both Sith Lords and Stormtroopers to login to their respective tenants while also ensuring that they can’t login to each other’s tenants. Finally, we will add another Organization into the mix without any code changes or even the need to restart the application.

Getting Ready for A Multi-Tenant User Store

The first step to multi-tenant bliss is to get Stormpath setup. While there are few steps along the way, you’ll see that it’s pretty easy.

There are a number of ways to accomplish authentication in a multi-tenant enabled Application:

  1. Add a field to the login form for users to type in their Tenant name
  2. Select Tenant after login
  3. Automatically set Tenant by subdomain

The most advanced version of this – and the easiest on users – is the subdomain approach. That is the approach we will be configuring in the examples that follow.

For more information on the various approaches, check out our Multi-Tenancy Guide

Create a Stormpath Account

Point your browser over to https://api.stormpath.com and signup for a Stormpath account. Fill out the form, verify your account, create an API key pair and you’re good to go.

For more detailed information on setting up your free Stormpath account, refer to the Product Guide.

Setup the Organizations

Organizations are the key to our subdomain-based configuration. A Stormpath Organization is a type of Account Store. That is, a container for Accounts. The important part here is that you specify an Organization Name Key that matches your subdomain.

In this case, we will use sith and stormtrooper Organization names to match the subdomains we setup below.

Follow these steps:

Setup the Organizations

  1. Browse to your Stormpath Admin Console
  2. Click the Organizations tab at the top of the page
  3. Click the Create Organization button

    create_org

  4. Enter Sith for the Name and sith for Name Key and click the Create Organization button

  5. Repeat steps 2 – 4 using Stormtrooper for the Name stormtrooper for the Name Key

    orgs

Setup the Directories

Stormpath Directories contain the Accounts that we will use for a particular Tenant.

  1. Click the Directories tab at the top of the page
  2. Click the Create Directory button

    create_directory

  3. Enter Sith Directory for the Name and click the Create Directory button

  4. Repeat steps 2 – 3 usting Stormtrooper Directory for the Name

Setup the Accounts

We’re going to create two Accounts – one in each Directory.

First, a Sith Account:

  1. Click Accounts tab at the top of the page
  2. Click the Create Account button

    create_account

  3. Choose the Sith Directory option for Account Location

  4. Enter dvader for Username
  5. Enter Darth for First Name
  6. Enter Vader for Last Name
  7. Enter dvader@empire.biz for Email
  8. Enter a password of your choosing for Password and re-enter it for Confirm Password
  9. Click the Create button

Next, a Stormtrooper Account:

  1. Click Accounts tab at the top of the page
  2. Click the Create Account button

    create_account

  3. Choose the Stormtrooper Directory option for Account Location

  4. Enter tk421 for Username
  5. Enter TK for First Name
  6. Enter 421 for Last Name
  7. Enter tk421@empire.biz for Email
  8. Enter a password of your choosing for Password and re-enter it for Confirm Password
  9. Click the Create button

Setup the Application

The Stormpath Application is where we point the Spring Boot application to for authentication and authorization.

Follow these steps to create an Application:

  1. Click the Applications tab at the top of the page
  2. Click the Create Application button
  3. Enter Imperial Xchange for the Name
  4. Uncheck the Create new Directory checkbox (we will associate the Organizations we created with the Application below)
  5. Click the Create button

    create_application

Tying it all Together

The last steps in this section are to add the Directories we’ve created as Account Store Mappings in the Organizations and to associate the Organizations with the Application

Account Store Mappings:

  1. Click the Organizations tab again
  2. Click the Sith link
  3. Click the Account Stores link
  4. Click the Add Account Stores link
  5. On the Directories tab, click the checkbox next to Sith Directory
  6. Click the Create Mappings button

    sith_mapping

  7. Click the Organizations tab again

  8. Click the Stormtrooper link
  9. Click the Account Stores link
  10. Click the Add Account Stores link
  11. On the Directories tab, click the checkbox next to Stormtrooper Directory
  12. Click the Create Mappings button

    stormtrooper_mapping

Application Account Stores:

  1. Click the Applications tab again
  2. Click the Imperial Xchange link
  3. Click the Account Stores link

    application_account_stores_before

  4. Click the Add Account Store button

  5. Choose the Organizations tab and select the Sith and Stormtrooper checkboxes

    org_mappings

  6. Click the Create Mappings button

    application_account_stores

Phew! Your Application is now completely setup for multi-tenancy. Hooray!

Configure ID Site

ID Site is Stormpath’s hosted and pre-built user interface screens that take care of the most common authentication workflows, including the login and register functions (among others) of your Application.

We’re using it here as it automatically supports the subdomain approach to multi-tenancy.

For more information on ID Site, check out the product guide here.

When you authenticate to an Application backed by ID Site, you will be automatically redirected to the hosted login page and then redirected back to your Application. For security purposes, you must specify the allowed origin and redirect urls.

For the purposes of our example app, we are going to use a locally defined domain: ix.localhost.

Specifically, we’ll be using sith.ix.localhost and stormtrooper.ix.localhost.

ID Site supports the notion of wildcard domains. This means that you don’t have to specify every subdomain you want to support for a given domain. You use the wildcard character * as you’ll see below.

Follow these steps for configure ID Site:

  1. Click the ID Site tab at the top of the page
  2. Scroll down to the Authorized Javascript Origin URLs section and enter http://*.ix.localhost:8080
  3. Click into the Authorized Redirect URLs section and enter http://*.ix.localhost:8080/ and http://*.ix.localhost:8080/idSiteResult

    create_application

  4. Scroll to the bottom of the page and click the Save button.

/idSiteResult is the default callback URI used in Spring Boot applications.

Configure Your Local Environment

Rounding out our configuration journey is setting up your local environment to support the local domains we are using for this example.

On Macs and Linux machines, you edit the /etc/hosts file. On Windows machines, you edit the %SystemRoot%\System32\drivers\etc\hosts file. Update the following line:

1
127.0.0.1    localhost stormtrooper.ix.localhost sith.ix.localhost

When we run the Spring Boot application below on the standard port, 8080, this configuration allows you to browse to http://sith.ix.localhost:8080 and http://stormtrooper.ix.localhost:8080

Spring Boot Application

The code for the example application can be found here.

This application simply demonstrates the subdomain based multi-tenant capability that we configured in the previous section.

So, how do we go about enabling ID Site for our application? What about displaying the Organization field on the login form? This is done as a configuration in the application.properties file:

1
2
stormpath.web.idSite.enabled = true
stormpath.web.idSite.showOrganizationField = true

That’s it!

The application consists of two controllers and a couple of templates. The HomeController shows the home template. The homepage / is completely unprotected. The RestrictedController shows the restricted template. You must be logged in to go to /restricted.

You can fire up the app as follows:

1
2
3
4
5
mvn clean package

STORMPATH_API_KEY_FILE=<full path to your API Key file> \
STORMPATH_APPLICATION_HREF=<href to your application> \
mvn spring-boot:run

Let’s see the multi-tenancy partitioning in action:

  1. Browse to: http://sith.ix.localhost:8080/

    sith_localhost

  2. Click the green button

  3. Enter in the Darth Vader account information we created earlier

    sith_localhost_login

    Notice that the tenant, extracted from the subdomain, is shown in the read-only Organization field on the page. This is a result of the application.properties configuration we did above. We could choose to not show the Organization field at all since it is taken from the subdomain automatically.

  4. Click the Login button and you will be redirected back to the /restricted page

    sith_localhost_login

So, what? What’s the big deal? Here it is: Logout and then try to login again using the Stormtrooper account we setup earlier:

stormtrooper_bad_login

Stormtroopers are not allowed to log into the sith Tenant.

Now, try to login with the Stormtrooper Account using the correct URL: http://stormtrooper.ix.localhost:8080/

stormtrooper_localhost_login

stormtrooper_localhost_auth

There it is! Remember, we have a single instance of our Spring Boot application running. We’ve achieved the goal of partitioning the Sith Lord’s from the Stormtroopers. This was accomplished mainly through the Organizations and the ID Site configurations in the Admin Console.

Wanna add another tenant to your Application? All you need to do is create another Organization with mapped Directory and then add that Organization to the Account Store Mappings of your Application. You can then immediately browse to the new subdomain – no need to even restart the application! If you added an Organization with name key officer, you could immediately browse to: http://officer.ix.localhost:8080 (you’d still ned to add officer.ix.localhost to your /etc/hosts file).

I hope you’re as excited as I am about how powerful and useful the automatic multi-tenant by subdomain feature of Stormpath is.

Feel free to drop a line over to email anytime.

Like what you see? to keep up with the latest releases.

A Simple Web App With Node.js, Express, Bootstrap & Stormpath

$
0
0

Here at Stormpath we <heart> Node.js – it’s so much fun to build with! We’ve built several libraries to help node developers achieve user management nirvana in your applications.

If you’ve built a web app before, you know that all the “user stuff” is a royal pain. Stormpath gives developers all that “user stuff” out-of-the-box so you can get on with what you really care about – your app! By the time you’re done with this tutorial (less than 15 minutes, I promise), you’ll have a fully-working Express app.

We will focus on our Express-Stormpath library to roll out a simple Express.js web application, with a complete user registration and login system, with these features:

  • Login and Registration pages
  • Password reset workflows
  • A profile page for your logged in users
  • A customizable home page
  • The ability to add other Stormpath features in our Express-Stormpath library (API authentication, SSO, social login, and more)

In this demo we will be using Express 4.0, we’ll discuss some of the great features of Express 4.0 as we go along. I will be using my Mac, the Terminal app, and Sublime Text for a text editor.

What is Stormpath?

Stormpath is an API service that allows developers to create, edit, and securely store user accounts and user account data, and connect them with one or multiple applications. Our API enables you to:

In short: we make user account management a lot easier, more secure, and more scalable than what you’re probably used to.

Ready to get started? Register for a free developer account!

Start your project

Got your Stormpath developer account? Great! Let’s get started.. vroom vroom

If you don’t already have Node.js on your system you should head over to Node.org and install it on your computer. In our examples we will be using a Mac, all commands you see should be entered in your Terminal (without the $ in front – that’s a symbol to let you know that these are terminal commands)

Step one is to create a folder for this project and change into that directory:

$ mkdir my-webapp
$ cd my-webapp

Now that we are in the folder we will want to create a package.json file for this project. This file is used by Node.js to keep track of what libraries (aka modules) your project depends on. To create the file:

$ npm init

You will be asked a series of questions, for most of them you can just press enter to allow the default value to be used. Here is what I chose, I decided to call my main file server.js, I set my own description and set the license to MIT – everything else I just pressed enter on:

Press ^C at any time to quit.
name: (my-webapp)
version: (0.0.0)
description: Website for my new app
entry point: (index.js) server.js
test command:
git repository:
keywords:
author:
license: (ISC) MIT
About to write to /private/tmp/my-webapp/package.json:

{
  "name": "my-webapp",
  "version": "0.0.0",
  "description": "Website for my new app",
  "main": "server.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "MIT"
}


Is this ok? (yes) yes

With that I will now have a package.json file in my folder. I can take a look at what’s in it:

$ cat package.json

{
  "name": "my-webapp",
  "version": "0.0.0",
  "description": "Website for my new app",
  "main": "server.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "MIT"
}

Looks good! Now let’s install the libraries we want to use. You can install them all with this command:

$ npm i --save express express-stormpath cookie-parser csurf jade forms xtend

The save option will add this module to your dependencies in package.json. Here is what each module does:

  • Express.js is the web framework that everything else is built on.
  • Express-stormpath provides convenience features that can be tied in to the Express app, making it very easy to use Stormpath’s features in Express.
  • Csurf adds CSRF protection to our forms.
  • Cookie-Parser is used to read the cookies that are created by the Csurf library.
  • Forms is a module that will take the pain out of validating HTML forms.
  • Jade is a templating engine for writing HTML pages.

  • Xtend is a utility library that makes it easy to copy properties from one JavaScript object to another.

Gather your API Credentials and Application Href

The connection between your app and Stormpath is secured with “API Key Pair”. You will provide these keys to your web app and it will use them when it communicates with Stormpath. You can download your API key pair in our Admin Console. After you login you can download your API key pair from the home page, it will download the apiKey.properties file.

While you are in the Admin Console you want to get the href for your default Stormpath Application. In Stormpath, an Application object is used to link your web app to your user stores inside Stormpath. All new developer accounts have an app called “My Application”. Click on “Applications” in the Admin Console, then click on “My Application”.

For this demonstration we will export these settings to your environment, so please run these commands in your terminal:

Unix/Linux/Mac:

export STORMPATH_CLIENT_APIKEY_ID=xxxx
export STORMPATH_CLIENT_APIKEY_SECRET=xxxx
export STORMPATH_APPLICATION_HREF=xxxx

Windows:

set STORMPATH_CLIENT_APIKEY_ID=xxxx
set STORMPATH_CLIENT_APIKEY_SECRET=xxxx
set STORMPATH_APPLICATION_HREF=xxxx

Now these settings will be automatically available to our server.

Writing the application entry (server.js)

It’s time to create server.js, this will be the entry point for your server application. You can do that from Sublime Text or you can do this in the terminal:

$ touch server.js

Now open that file in Sublime Text and put the following block of code in it:

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

var app = express();

app.set('views', './views');
app.set('view engine', 'jade');

app.use(stormpath.init(app, {
  website: true,
  expand: {
    customData: true
  }
}));

app.get('/', function(req, res) {
  res.render('home', {
    title: 'Welcome'
  });
});

app.on('stormpath.ready',function(){
  console.log('Stormpath Ready');
  app.listen(3000);
});

In this example we’ve enabled auto-expansion of custom data – this will come in handy later when we build the profile page.

There are many more options that can be passed, and we won’t cover all of them in this demo. Please seee the Express-Stormpath Documentation for a full list

Create your home page

Let’s get the easy stuff out of the way: your home page. Create a views directory and then create a Jade file for the home page:

$ mkdir views
$ touch views/home.jade

Now open that file in Sublime Text and put the following in it:

html
  head
    title=title
    link(href='//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css', rel='stylesheet')
  body
    div.container
      div.jumbotron
        h1 Hello!

        if user
          p Welcome, #{user.fullName}
          p
            a.small(href="profile") Edit my profile
          a.btn.btn-primary(href="/logout") Logout
        else
          p Welcome to my app, ready to get started?
          p
            a.btn.btn-primary(href="/login") Login now
          p
            span.small Don't have an account?
            span &nbsp;
            a.small(href="/register") Register now

This is a simple view that will prompt a new visitor to log in, or greet a registered user if they have already logged in.

With that… we’ve got something we can look at!

Run the server – It’s Aliiiive!

I kid you not: your application is ready to be used. Just run this command to start the server:

$ node server.js

This will start your app which is now running as a web server on your computer. You can now open this link in your browser:

http://localhost:3000

You should see your home page now:

Node App Home

Go ahead, try it out! Create an account, you will be redirected back to the home page and shown your name. Then logout and login again, same thing! Pretty amazing, right??

Pro tip: use a file watcher

As we move forward we will be editing your server files. You will need to restart the server each time. You can kill the server by typing Ctrl + C in your Terminal. But I suggest using a “watcher” that will do this for you.

I really like the Nodemon tool. You can install it globally (it will always be ready for you!) with this command:

$ npm install -g nodemon

After installation, you can then run this command:

$ nodemon server.js

This will start your server and watch for any file changes. Nodemon will automatically restart your server if you change any files – sweet!

Create the profile page

A common feature of most sites is a “Dashboard” or “profile” page – a place where your visitor provide some essential information.

For example purposes, we’re going to build a profile page that allows you to collect a shipping address from your visitors. We will leverage Custom Data, one of the most powerful features of stormpath

To begin, let’s create a new view for this dashboard:

$ touch views/profile.jade

And a JavaScript file where the route handler will live:

$ touch profile.js

Now we’ve got some copy-and-paste work to do. These two files are pretty big, so we’ll explain them after the paste.

Paste this into profile.js:

var cookieParser = require('cookie-parser');
var csurf = require('csurf');
var express = require('express');
var extend = require('xtend');
var forms = require('forms');

var collectFormErrors = require('express-stormpath/lib/helpers').collectFormErrors;

// Declare the schema of our form:

var profileForm = forms.create({
  givenName: forms.fields.string({
    required: true
  }),
  surname: forms.fields.string({ required: true }),
  streetAddress: forms.fields.string(),
  city: forms.fields.string(),
  state: forms.fields.string(),
  zip: forms.fields.string()
});

// A render function that will render our form and
// provide the values of the fields, as well
// as any situation-specific locals

function renderForm(req,res,locals){
  res.render('profile', extend({
    title: 'My Profile',
    csrfToken: req.csrfToken(),
    givenName: req.user.givenName,
    surname: req.user.surname,
    streetAddress: req.user.customData.streetAddress,
    city: req.user.customData.city,
    state: req.user.customData.state,
    zip: req.user.customData.zip
  },locals||{}));
}

// Export a function which will create the
// router and return it

module.exports = function profile(){

  var router = express.Router();

  router.use(cookieParser());

  router.use(csurf({ cookie: true }));

  // Capture all requests, the form library will negotiate
  // between GET and POST requests

  router.all('/', function(req, res) {
    profileForm.handle(req,{
      success: function(form){
        // The form library calls this success method if the
        // form is being POSTED and does not have errors

        // The express-stormpath library will populate req.user,
        // all we have to do is set the properties that we care
        // about and then cal save() on the user object:
        req.user.givenName = form.data.givenName;
        req.user.surname = form.data.surname;
        req.user.customData.streetAddress = form.data.streetAddress;
        req.user.customData.city = form.data.city;
        req.user.customData.state = form.data.state;
        req.user.customData.zip = form.data.zip;
        req.user.customData.save();
        req.user.save(function(err){
          if(err){
            if(err.developerMessage){
              console.error(err);
            }
            renderForm(req,res,{
              errors: [{
                error: err.userMessage ||
                err.message || String(err)
              }]
            });
          }else{
            renderForm(req,res,{
              saved:true
            });
          }
        });
      },
      error: function(form){
        // The form library calls this method if the form
        // has validation errors.  We will collect the errors
        // and render the form again, showing the errors
        // to the user
        renderForm(req,res,{
          errors: collectFormErrors(form)
        });
      },
      empty: function(){
        // The form library calls this method if the
        // method is GET - thus we just need to render
        // the form
        renderForm(req,res);
      }
    });
  });

  // This is an error handler for this router

  router.use(function (err, req, res, next) {
    // This handler catches errors for this router
    if (err.code === 'EBADCSRFTOKEN'){
      // The csurf library is telling us that it can't
      // find a valid token on the form
      if(req.user){
        // session token is invalid or expired.
        // render the form anyways, but tell them what happened
        renderForm(req,res,{
          errors:[{error:'Your form has expired.  Please try again.'}]
        });
      }else{
        // the user's cookies have been deleted, we dont know
        // their intention is - send them back to the home page
        res.redirect('/');
      }
    }else{
      // Let the parent app handle the error
      return next(err);
    }
  });

  return router;
};

Paste this into profile.jade:

html
  head
    title=title
    link(
      href='https://stormpath.com//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css',
      rel='stylesheet'
    )
  body
    div.container

      div.page-header
        h1 My Profile

      if errors
        each error in errors
          div.alert.alert-danger
            span #{error.error}
      if saved
        div.alert.alert-success
          span Your profile has been saved
      form.login-form.form-horizontal(method='post', role='form')
        input(name='_csrf', type='hidden', value=csrfToken)

        div.form-group
          label.col-sm-4 First Name
          div.col-sm-8
            input.form-control(
              placeholder='Your first name',
              required=true,
              name='givenName',
              type='text',
              value=givenName)
        div.form-group
          label.col-sm-4 Last Name
          div.col-sm-8
            input.form-control(placeholder='Your last name',
              required=true,
              name='surname',
              type='text',
              value=surname)
        div.form-group
          label.col-sm-4 Street address
          div.col-sm-8
            input.form-control(placeholder='e.g. 123 Sunny Ave',
              required=true,
              name='streetAddress',
              type='text',
              value=streetAddress)
        div.form-group
          label.col-sm-4 City
          div.col-sm-8
            input.form-control(placeholder='e.g. City',
              required=true,
              name='city',
              type='text',
              value=city)
        div.form-group
          label.col-sm-4 State
          div.col-sm-8
            input.form-control(placeholder='e.g. CA',
              required=true,
              name='state',
              type='text',
              value=state)
        div.form-group
          label.col-sm-4 ZIP
          div.col-sm-8
            input.form-control(placeholder='e.g. 94116',
              required=true,
              name='zip',
              type='text',
              value=zip)
        div.form-group
          div.col-sm-offset-4.col-sm-8
            button.login.btn.btn-primary(type='submit') Save
        div.pull-right
          a(href="/") Return to home page

Breaking it down

You’ve just created an Express Router. Saywha? I really like how the Express maintainers have described this:

A router is an isolated instance of middleware and routes.
Routers can be thought of as "mini" applications, capable only
of performing middleware and routing functions. Every express
application has a built-in app router.

… saywha?

In my words: Express 4.0 encourages you to break up your app into “mini apps”. This makes everything much easier to understand and maintain. This is what we’ve done with the profile.js file — we’ve created a “mini app” which handles JUST the details associated with the profile page.

Don’t believe me? Read on.

Plug in your profile page

Because we followed the Router pattern, it’s now this simple to add the profile page to your existing server.js file (put it right above the call to app.on('stormpath.ready'):

app.use('/profile',stormpath.loginRequired,require('./profile')());

Omg. Yes. YES. You’ve just decoupled the implentation of a route from it’s addressing. Holy grail? Almost. Awesome? Most Def. (By the way, you’ve also forced authentication on this route, using Stormpath, nice!)

Restart your sever and visit /profile, you should see the form now:

Node App Home

Breaking it down – for real

Okay, there’s a LOT more to talk about here. So let me cover the important points:

  • The profile.js file is a builder or constructor, so to speak. You have to invoke it as a method in order to get the router out of it. That’s why we have that empty () after the require('./profile') statement. Why bother? Because with this pattern you can pass in any options that may be required for this router. At the moment we don’t have any, but who knows what the future holds? Doing this give you room to use this router in multiple web apps and factor out any app-specific config.

  • We are using the forms library to create a schema for the profile form. This is a good practice because it separates the way in which we validate from the form from the way in which the form is displayed.

  • We have a renderForm function which is responsible for creating the view model of the form — this model is passed down to the Jade layer, so that profile.jade has all the properties it needs for rendering the form. This render function ensures that our template layer doesn’t blow up with missing values

  • We are using the Csurf library to add CSRF tokens to the form as a security measure. This is done automaticaly for the default forms (login, registration, password reset), but because this is a new, custom router, we have to setup those details manually

  • We reach into the Express-Stormpath library to grab our collectFormErrors function, a handy utility for pulling validation errors out of the response we get from the forms library. Note to self: PR that in to forms library!

  • We make use of the loginRequired middleware to ensure that users are logged in before they can use this profile page

Wrapping it up

Alas, we’ve reached the end of this tutorial. You now have a web app that can reigster new users and allow them to provide you with a shipping address, pretty sweet right?

Following the profile example you now have everything you need to start building other pages in your application. As you build those pages, I’m sure you’ll want to take advantage of some other great features, such as:

Those are just a few of my favorites, but there is so much more!

Please read the Express-Stormpath Product Guide for details on how to implement all these amazing features — and don’t hesitate to reach out to us!

WE LOVE WEB APPS and we want your user management experience to be 10x better than you ever imagined.

-robert out

Like what you see? to keep up with the latest releases.

Complete User Authentication for Laravel Applications

$
0
0

A few months ago, we released an Authentication Driver for Laravel that allows you to use the Auth Facade. Recently, we updated this to a full integration with views already set up for you in our Laravel Authentication package. This makes it very easy to start a project with Stormpath authentication built in from the beginning. This isn’t just basic authentication, we are using tokens to do the authentication and following the OAuth standards for it!

With this package, we have enabled the basic user workflows for you. Login, Logout, Forgot Password, and Change Password workflows are pre-built and easy to turn on and off. These are all powered by the Stormpath PHP SDK and fully configurable from the configuration file.

What is Stormpath?

Stormpath is a complete identity API with powerful authentication, authorization, and user management for any application. Stormpath makes it easy to do stuff like:

  • User registration and login.
  • Account verification via email.
  • Password reset via email.
  • And a bunch of other cool stuff you probably don’t like coding!

Why Use Stormpath’s Laravel Authentication Package?

Well, quite simply, we make managing user accounts, roles, and permissions a lot easier, more secure, and more scalable than what you’re probably used to. We also automate a lot of advanced user features like customer-organizations for multi-tenant applications, single sign-on, and social login. Plus, you never have to build or maintain a user database.

Using Stormpath not only allows you to easily build your application out, but it also allows you to scale your site to support millions of users without changing your code, or even needing a database!

So, let’s dive in.

If you don’t already have a Stormpath account and application, you’ll need to create one now — you can do so here: https://api.stormpath.com/register

The rest of this article assumes you have a Stormpath account and API key pair.

Build Your Laravel Application

To help you understand how this package works and integrates with Laravel, let’s build a simple application. This application will have a Login, Logout, and Register functionalities. After we get all of the basics installed, we will enable the Forgot Password workflows and work with middleware.

Install the Tools You Need

The first step is to install all the tools needed to start this project. The following tools will be required:

  • Composer
  • Laravel
  • Stormpath-Laravel

Install Composer

Composer is a dependency manager for PHP. It is how Stormpath distributes all PHP Packages. Visit http://getcomposer.org and follow the instructions here to fully install composer. Once you have this installed, you should be able to type composer in terminal and see the output:

1
2
3
4
5
6
7
8
> composer
   ______
  / ____/___  ____ ___  ____  ____  ________  _____
 / /   / __ \/ __ `__ \/ __ \/ __ \/ ___/ _ \/ ___/
/ /___/ /_/ / / / / / / /_/ / /_/ (__  )  __/ /
\____/\____/_/ /_/ /_/ .___/\____/____/\___/_/
                    /_/
Composer version 1.0-dev (dc0627617935da9208124e580b9f0e39dd214ae5) 2015-12-01 14:57:35

The following message may appear. You can ignore it as this is just a notice about performance if you are using xdebug.

You are running composer with xdebug enabled. This has a major impact on runtime performance. See https://getcomposer.org/xdebug

Install Your Laravel Project

In this example, I use a tool called the Laravel Installer. It is a simple command line tool that lets you quickly install a new project. There are a few other ways you can install Laravel but they all require composer. Install the Laravel Installer by running composer global require "laravel/installer" Next, run the following to install the project.

1
laravel new my-stormpath-project

If you don’t want to use the installer, another option to install Laravel is with composer. Visit https://laravel.com/docs/5.2/#installing-laravel

You can now cd into my-stormpath-project and run php artisan. If everything installed correctly, you should see something like the following:

1
2
3
4
5
~/Sites/my-stormpath-project>  php artisan
Laravel Framework version 5.2.6

Usage:
  command [options] [arguments]

Require the Stormpath Laravel Package

Requiring the Stormpath Laravel package is very simple with Composer. Open your composer.json file and add the following line to the require block:

1
"stormpath/laravel": "0.1.*"

At the time of writing this post, The package version is 0.1.0.

There are a few more settings that have to be configured to enable this package before you can run it. The first step is to take your API keys from Stormpath and put them into your .env file of your project. From the root of your project, open up .env and place the following at the end of the file replacing the necessary values.

1
2
3
STORMPATH_CLIENT_APIKEY_ID=
STORMPATH_CLIENT_APIKEY_SECRET=
STORMPATH_APPLICATION_HREF=

After saving this file, We have to initialize the package. Open config/app.php and add the following to your providers section.

1
2
3
4
5
"providers" => [
    ...
    Stormpath\Laravel\Support\StormpathLaravelServiceProvider::class,
    ...
]

You should now be able to start up the server using php artisan serve from the command line and visit http://localhost:8000/login. You should see the following login screen

Forgot Password

Congratulations, you have installed stormpath/laravel! You now have basic login and registration capabilities without needing to build any logic or views at all.

Protect a Route with Stormpath

Out of the box, we provide you with a few different middleware options to protect your routes. We have stormpath.guest and stormpath.auth

stormpath.guest is set up so only un-authenticated users can see the route. This is useful for registration pages and pricing/upgrade pages. These are pages that registered users may not need to see.

stormpath.auth is the inverse of stormpath.guest. This middleware requires a user to be logged into the system to be able to view the route.

To set up a route, all you need to do is add the middleware to the route.

1
2
3
4
5
6
7
8
9
// This route is only accessible by a logged in user 
Route::get('protected', ['middleware' => ['stormpath.auth'], function() {
    return 'These are all the secrets!';
}]);

// This route is only accessible by a guest
Route::get('guests', ['middleware' => ['stormpath.guest'], function() {
    return 'You are a guest!';
}]);

By default. stormpath.guest middleware is enabled for login, register, forgot-password, and change-password routes.

Configure Your Laravel Integration

So far, we have touched on the basics of what this integration is able to do. We have built in many more features that can be enabled and configured within the Stormpath Configuration of the Package. In order to access and modify these, you will need to publish the vendor files. In Laravel, there is an artisan command to do this for us. From the root of your project in terminal, run php artisan vendor:publish and this will create a new file located at config/stormpath.php with all the configuration options that are available.

Enable Forgot/Reset Password Workflows

When building an application, a lot of people will either forget or incorrectly set up the forgot password and reset password workflows. If a developer does not want to manually reset user passwords all the time, they will want to offer a way for the user to do so. This can be a very insecure part of an application if it is not correctly set up.

We have made this easier for you and integrated it as part of the core package. By default, these workflows are turned off, but it is just a configuration option in the config/stormpath.php file that you need to enable. Find the forgotPassword key in the array and set enabled to true. You now have access to the Forgot password workflow by going to /forgot in your browser.

Forgot Password

This will begin the email flow for the forgot password workflow. The user will receive an email if the account is found. The email will include a link for them to reset their password. No crazy code is needed for you to set this up correctly and it is secure.

Pre-Built Workflows with ID Site

If you know about Stormpath, you may already know about ID Site. If you are unaware of what ID Site is, it is a set of hosted and pre-built user interface screens that take care of common identity functions for your applications — login, registration, and password reset. ID Site can be accessed via your own custom domain like id.mydomain.com and shared across multiple applications to create centralized authentication as needed.

We wanted to make an easy way for you to use ID Site in Laravel. There are a couple of things that need to be done to enabled ID Site. Steps for setting up ID Site can be found in the Stormpath docs.

To enable the package to use ID site for all your requests, open up the file config/stormpath.php and you will see a full list of available options. The one we are looking for can be found towards the bottom of the file in the web->idsite setting. We want to mark it as enabled for ID Site to work. Now, any of the features that are enabled will use ID site by default.

Finish up Your Secure Laravel Application

With the above, you should now be able to create a secure application quickly without much work to do. We would love to hear your thoughts on this and hope you are as excited as we are about this.

Feel free to drop a line over to email anytime.

Like what you see? to keep up with the latest releases.

Where to Store your JWTs - Cookies vs HTML5 Web Storage

$
0
0

Stormpath has recently worked on token authentication features using JSON Web Tokens (JWT), and we have had many conversations about the security of these tokens and where to store them.

If you are curious about your options, this post is for you. We will cover the basics of JSON Web Tokens (JWT), cookies, HTML5 web storage (localStorage/sessionStorage), and basic information about cross-site scripting (XSS) and cross site request forgery (CSRF).

Let’s get started…

JSON Web Tokens (JWT): A Crash Course

The most implemented solutions for API authentication and authorization are the OAuth 2.0 and JWT specifications, which are fairly dense. Cliff’s Notes Time! Here’s what you need to know:

  • JWTs are a great authentication mechanism. They give you a structured and stateless way to declare a user and what they can access. They can be cryptographically signed and encrypted to prevent tampering on the client side.
  • JWTs are a great way to declare information about the token and authentication. You have a ton of freedom to decide what makes sense for your application because you are working with JSON.
  • The concept behind scopes is powerful yet incredibly simple: you have the freedom to design your own access control language because, again, you are working with JSON.

If you encounter a token in the wild, it looks like this:

"dBjftJeZ4CVP.mB92K27uhbUJU1p1r.wW1gFWFOEjXk..."

This is a Base64 encoded string. If you break it apart you’ll actually find three separate sections:

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9
.
eyJpc3MiOiJodHRwOi8vZ2FsYXhpZXMuY29tIiwiZXhwIjoxMzAwODE5MzgwLCJzY29wZXMiOlsiZXhwbG9yZXIiLCJzb2xhci1oYXJ2ZXN0ZXIiXSwic3ViIjoic3RhbmxleUBhbmRyb21lZGEuY29tIn0
.
edK9cpfKKlGtT6BqaVy4bHnk5QUsbnbYCWjBEE7wcuY

The first section is a header that describes the token. The second section is a payload which contains the juicy bits, and the third section is a signature hash that can be used to verify the integrity of the token (if you have the secret key that was used to sign it).

When we magically decode the second section, the payload, we get this nice JSON object:

{
  "iss": "http://galaxies.com",
  "exp": 1300819380,
  "scopes": ["explorer", "solar-harvester", "seller"],
  "sub": "tom@andromeda.com"
}

This is the payload of your token. It allows you to know the following:

  • Who this person is (sub, short for subject)
  • What this person can access with this token (scope)
  • When the token expires (exp)
  • Who issued the token (iss, short for issuer)

These declarations are called ‘claims’ because the token creator claims a set of assertions that can be used to ‘know’ things about the subject. Because the token is signed with a secret key, you can verify its signature and implicitly trust what is claimed.

Tokens are given to your users after they present some credentials, typically a username and password, but they can also provide API keys, or even tokens from another service. This is important because it is better to pass a token (that can expire, and have limited scope) to your API than a username and password. If the username and password are compromised in a man-in-the-middle attack, it is like giving an attacker keys to the castle.

Stormpath’s API Key Authentication Feature is an example of this. The idea is that you present your hard credentials once, and then get a token to use in place of the hard credentials.

The JSON Web Token (JWT) specification is quickly gaining traction. Recommended highly by Stormpath, it provides structure and security, but with the flexibility to modify it for your application. Here is a longer article on it: Use JWT the Right Way!

Where to Store Your JWTs

So now that you have a good understanding of what a JWT is, the next step is to figure out how to store them. If you are building a web application, you have a couple options:

  • HTML5 Web Storage (localStorage/sessionStorage)
  • Cookies

To compare these two, let’s say we have a fictitious AngularJS or single page app (SPA) called galaxies.com with a login route (/token) to authenticate users to return a JWT. To access the other APIs endpoints that serve your SPA, the client needs to pass an valid JWT.

The request that the single page app makes would resemble:

HTTP/1.1

POST /token
Host: galaxies.com
Content-Type: application/x-www-form-urlencoded

username=tom@galaxies.com&password=andromedaisheadingstraightforusomg&grant_type=password

Your server’s response will vary based on whether you are using cookies or Web Storage. For comparison, let’s take a look at how you would do both.

Web Storage

Exchanging a username and password for a JWT to store it in browser storage (sessionStorage or localStorage) is rather simple. The response body would contain the JWT as an access token:

HTTP/1.1 200 OK

  {
  "access_token": "eyJhbGciOiJIUzI1NiIsI.eyJpc3MiOiJodHRwczotcGxlL.mFrs3Zo8eaSNcxiNfvRh9dqKP4F1cB",
       "expires_in":3600
   }

On the client side, you would store the token in HTML5 Web Storage (assuming that we have a success callback):

function tokenSuccess(err, response) {
    if(err){
        throw err;
    }
    $window.sessionStorage.accessToken = response.body.access_token;
}

To pass the access token back to your protected APIs, you would use the HTTP Authorization Header and the Bearer scheme. The request that your SPA would make would resemble:

HTTP/1.1

GET /stars/pollux
Host: galaxies.com
Authorization: Bearer eyJhbGciOiJIUzI1NiIsI.eyJpc3MiOiJodHRwczotcGxlL.mFrs3Zo8eaSNcxiNfvRh9dqKP4F1cB

Cookies

Exchanging a username and password for a JWT to store it in a cookie is simple as well. The response would use the Set-Cookie HTTP header:

HTTP/1.1 200 OK

Set-Cookie: access_token=eyJhbGciOiJIUzI1NiIsI.eyJpc3MiOiJodHRwczotcGxlL.mFrs3Zo8eaSNcxiNfvRh9dqKP4F1cB; Secure; HttpOnly;

To pass the access token back to your protected APIs on the same domain, the browser would automatically include the cookie value. The request to your protected API would resemble:

GET /stars/pollux
Host: galaxies.com

Cookie: access_token=eyJhbGciOiJIUzI1NiIsI.eyJpc3MiOiJodHRwczotcGxlL.mFrs3Zo8eaSNcxiNfvRh9dqKP4F1cB;

So, What’s the difference?

If you compare these approaches, both receive a JWT down to the browser. Both are stateless because all the information your API needs is in the JWT. Both are simple to pass back up to your protected APIs. The difference is in the medium.

Web Storage

Web Storage (localStorage/sessionStorage) is accessible through JavaScript on the same domain. This means that any JavaScript running on your site will have access to web storage, and because of this can be vulnerable to cross-site scripting (XSS) attacks. XSS in a nutshell is a type of vulnerability where an attacker can inject JavaScript that will run on your page. Basic XSS attacks attempt to inject JavaScript through form inputs, where the attacker puts <script>alert('You are Hacked');</script> into a form to see if it is run by the browser and can be viewed by other users.

To prevent XSS, the common response is to escape and encode all untrusted data. But this is far from the full story. In 2015, modern web apps use JavaScript hosted on CDNs or outside infrastructure. Modern web apps include 3rd party JavaScript libraries for A/B testing, funnel/market analysis, and ads. We use package managers like Bower to import other peoples’ code into our apps.

What if only one of the scripts you use is compromised? Malicious JavaScript can be embedded on the page, and Web Storage is compromised. These types of XSS attacks can get everyone’s Web Storage that visits your site, without their knowledge. This is probably why a bunch of organizations advise not to store anything of value or trust any information in web storage. This includes session identifiers and tokens.

As a storage mechanism, Web Storage does not enforce any secure standards during transfer. Whoever reads Web Storage and uses it must do their due diligence to ensure they always send the JWT over HTTPS and never HTTP.

Cookies

Cookies, when used with the HttpOnly cookie flag, are not accessible through JavaScript, and are immune to XSS. You can also set the Secure cookie flag to guarantee the cookie is only sent over HTTPS. This is one of the main reasons that cookies have been leveraged in the past to store tokens or session data. Modern developers are hesitant to use cookies because they traditionally required state to be stored on the server, thus breaking RESTful best practices. Cookies as a storage mechanism do not require state to be stored on the server if you are storing a JWT in the cookie. This is because the JWT encapsulates everything the server needs to serve the request.

However, cookies are vulnerable to a different type of attack: cross-site request forgery (CSRF). A CSRF attack is a type of attack that occurs when a malicious web site, email, or blog causes a user’s web browser to perform an unwanted action on a trusted site on which the user is currently authenticated. This is an exploit of how the browser handles cookies. A cookie can only be sent to the domains in which it is allowed. By default, this is the domain that originally set the cookie. The cookie will be sent for a request regardless of whether you are on galaxies.com or hahagonnahackyou.com.

CSRF works by attempting to lure you to hahagonnahackyou.com. That site will have either an img tag or JavaScript to emulate a form post to galaxies.com and attempt to hijack your session, if it is still valid, and modify your account.

For example:

<body>

  <!-- CSRF with an img tag -->

  <img href="http://galaxies.com/stars/pollux?transferTo=tom@stealingstars.com" />

  <!-- or with a hidden form post -->

  <script type="text/javascript">
  $(document).ready(function() {
    window.document.forms[0].submit();
  });
  </script>

  <div style="display:none;">
    <form action="http://galaxies.com/stars/pollux" method="POST">
      <input name="transferTo" value="tom@stealingstars.com" />
    <form>
  </div>
</body>

Both would send the cookie for galaxies.com and could potentially cause an unauthorized state change. CSRF can be prevented by using synchronized token patterns. This sounds complicated, but all modern web frameworks have support for this.

For example, AngularJS has a solution to validate that the cookie is accessible by only your domain. Straight from AngularJS docs:

When performing XHR requests, the $http service reads a token from a cookie (by default, XSRF-TOKEN) and sets it as an HTTP header (X-XSRF-TOKEN). Since only JavaScript that runs on your domain can read the cookie, your server can be assured that the XHR came from JavaScript running on your domain.

You can make this CSRF protection stateless by including a xsrfToken JWT claim:

{
  "iss": "http://galaxies.com",
  "exp": 1300819380,
  "scopes": ["explorer", "solar-harvester", "seller"],
  "sub": "tom@andromeda.com",
  "xsrfToken": "d9b9714c-7ac0-42e0-8696-2dae95dbc33e"
}

If you are using the Stormpath SDK for AngularJS, you get stateless CSRF protection with no development effort.

Leveraging your web app framework’s CSRF protection makes cookies rock solid for storing a JWT. CSRF can also be partially prevented by checking the HTTP Referer and Origin header from your API. CSRF attacks will have Referer and Origin headers that are unrelated to your application.

Even though they are more secure to store your JWT, cookies can cause some developer headaches, depending on if your applications require cross-domain access to work. Just be aware that cookies have additional properties (Domain/Path) that can be modified to allow you to specify where the cookie is allowed to be sent. Using AJAX, your server side can also notify browsers whether credentials (including Cookies) should be sent with requests with CORS.

Conclusion

JWTs are a awesome authentication mechanism. They give you a structured way to declare users and what they can access. They can be encrypted and signed for to prevent tampering on the client side, but the devil is in the details and where you store them. Stormpath recommends that you store your JWT in cookies for web applications, because of the additional security they provide, and the simplicity of protecting against CSRF with modern web frameworks. HTML5 Web Storage is vulnerable to XSS, has a larger attack surface area, and can impact all application users on a successful attack.

Questions or comments? We would love to hear them! Let me know if you have any questions in the discussion below or at tom@stormpath.com / @omgitstom.

Like what you see? to keep up with the latest releases.

OAuth with JSON Web Tokens In .NET

$
0
0

With a new year comes another exciting release of the Stormpath .NET SDK. In this release, we’ve knocked down another big milestone: full support for token-based authentication. But that’s not all! This release also includes support for JSON Web Tokens (JWTs), and contains plenty of improvements along the way.

Why OAuth and Token-Based Authentication Is Awesome For .NET Apps

OAuth and token-based authentication are a common point of confusion and frustration for web developers. OAuth is not Single Sign-On, but it’s often confused with SSO because many login providers (such as Google and Facebook) use a flavor of OAuth to handle external login. At the most basic level, OAuth means generating access and refresh tokens when users log into your application. And tokens are awesome!

Let me explain why.

Think of an access token as representing the identity of a user who is logged into your application. The access token is sent to the server with every request. On the server, the token is examined and verified to ensure the request is valid and authorized. After a period of time, the token expires and is no longer valid.

When an access token expires, the refresh token is used to generate a fresh access token. Typically, access tokens are short-lived and refresh tokens are long-lived. If the access token is compromised, it can be revoked, which forces the generation of a new access token via the user’s refresh token. Likewise, if a refresh token is compromised, it can be revoked so it cannot be used to generate new access tokens.

Why are tokens awesome? In short: scalability and security.

HTTP is stateless, so there’s no built-in way to store session or user information between requests. In the past, .NET developers had to rely on cookies and session variables to maintain state on the server, but this can be insecure. And if you’re planning on hosting your application on multiple servers behind a load balancer, making sure sessions are correctly shared between your machines can be a huge pain.

Token-based authentication is stateless, just like HTTP. Access and refresh tokens (in the form of JSON Web Tokens) are stored client-side and represent the user’s identity and authorization claims. Nothing is stored on the server to represent the session, so it’s easier to scale horizontally on multiple machines.

A cryptographic signature is used to ensure that the token isn’t compromised. An ID claim can be included in each token to prevent replay attacks. Additionally, if you know a user or token has been compromised, you can revoke their tokens immediately and prevent any future requests. This improves the security of the application.

In this release of the Stormpath .NET SDK, we’ve added rich support for the token management features already available in the Stormpath REST API.

Install the .NET SDK

Installing the SDK in a new project is as simple as:

install-package Stormpath.SDK

If you’re already using the SDK, this release should be a drop-in upgrade without any breaking changes:

update-package Stormpath.SDK

For a full list of changes, see the changelog on Github.

How Stormpath Makes Token Management In .NET Easy

With the Stormpath .NET SDK, it’s easy to:

  • Set policies for access and refresh token expiry
  • Generate access tokens and refresh tokens when users log into your application
  • Verify that an access token hasn’t been revoked or tampered with
  • Use a refresh token to generate a new access token
  • List tokens for an account and application
  • Revoke access and refresh tokens

Configure Access and Refresh Token Policies

Each Application has an OAuth Policy, which can be retrieved by calling GetOauthPolicyAsync:

1
2
3
4
IOauthPolicy policy = await myApp.GetOauthPolicyAsync();
// Default values:
// policy.AccessTokenTimeToLive = TimeSpan.FromHours(1);
// policy.RefreshTokenTimeToLive = TimeSpan.FromDays(60);

These values can be updated by the appropriate Set methods, and then calling SaveAsync:

1
2
3
policy.SetAccessTokenTimeToLive(TimeSpan.FromDays(1));
policy.SetRefreshTokenTimeToLive(TimeSpan.FromDays(180));
await policy.SaveAsync();

The maximum duration for access and refresh tokens is 180 days. Refresh tokens are optional; to disable refresh token generation, set the Refresh Token TTL to TimeSpan.Zero.

Generate OAuth Tokens for a User

Token generation should happen when a user logs into your application. In OAuth parlance, your application will issue a Password Grant request to Stormpath containing the user’s credentials. If the credentials are valid, Stormpath will generate access and refresh tokens for the user.Given a set of user credentials, you can generate tokens with a few lines of code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// Build the Password Grant request
var passwordGrantRequest = OauthRequests.NewPasswordGrantRequest()
    .SetLogin("lskywalker@tattooine.rim")
    .SetPassword("whataPieceofjunk$1138")
    .Build();

// Send the request to Stormpath
var grantResult = await myApp.NewPasswordGrantAuthenticator()
    .AuthenticateAsync(passwordGrantRequest);

// grantResult.AccessTokenHref is the location of the created Access Token resource in Stormpath
// grantResult.ExpiresIn is the number of seconds the access token is valid
// grantResult.AccessTokenString is the access token JWT
// grantResult.RefreshTokenString is the refresh token JWT
// grantResult.GetAccessTokenAsync() will retrieve the resource as an IAccessToken

In a web application, you can use the Set-Cookie HTTP header to pass the access and refresh token JWTs back to the user’s browser.

Verify Access Tokens

When a user makes a request to your application with an access token, it must be validated. The Stormpath .NET SDK supports two validation modes: local and remote.Local validation can be performed without making a network request, and ensures the following:

  • Token hasn’t been tampered with
  • Token hasn’t expired
  • Issuer is Stormpath

Remote validation makes a request to the Stormpath API, and ensures all of the above plus:

  • Token hasn’t been revoked
  • Account hasn’t been disabled, and hasn’t been deleted
  • Issuing application is still enabled, and hasn’t been deleted
  • Account is still in an account store for the issuing application

The choice of using local or remote validation depends on the needs of your application.

Remote validation looks like this:

1
2
3
4
5
6
7
8
9
10
// Build the validation request
var jwtAuthenticationRequest = OauthRequests.NewJwtAuthenticationRequest()
    .SetJwt(accessTokenJwtString)
    .Build();

// If the request is successful, an IAccessToken is returned.
// If the token is invalid, expired, revoked, or tampered with,
// a ResourceException is thrown.
IAccessToken validAccessToken = await myApp.NewJwtAuthenticator()
    .AuthenticateAsync(jwtAuthenticationRequest);

Local validation is identical, except for a call to WithLocalValidation:

1
2
3
4
5
6
// If the request is successful, an IAccessToken is returned.
// If the token is invalid, expired, revoked, or tampered with,
// the appropriate exception derived from InvalidJwtException is thrown.
IAccessToken validAccessToken = await myApp.NewJwtAuthenticator()
    .WithLocalValidation()
    .AuthenticateAsync(jwtAuthenticationRequest);

Refresh Access Tokens

When an access token expires, it’s straightforward to issue a Refresh Grant request to obtain a fresh token:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// Build the Refresh Grant request
var refreshGrantRequest = OauthRequests.NewRefreshGrantRequest()
    .SetRefreshToken(refreshTokenJwtString) // the refresh token JWT
    .Build();

// Send the request to Stormpath
var refreshGrantResult = await myApp.NewRefreshGrantAuthenticator()
    .AuthenticateAsync(refreshGrantRequest);

// grantResult.AccessTokenHref is the location of the created Access Token resource in Stormpath
// grantResult.ExpiresIn is the number of seconds the access token is valid
// grantResult.AccessTokenString is the new access token JWT
// grantResult.RefreshTokenString is the refresh token JWT
// grantResult.GetAccessTokenAsync() will retrieve the resource as an IAccessToken

Generating a new access token does not modify the expiration time of the refresh token. Once the refresh token expires, the user must authenticate again to get new access and refresh tokens.

List Tokens for an Account

You can query or list an account’s access and refresh tokens via the appropriate collection resource:

1
2
var accessTokens = await account.GetAccessTokens().ToListAsync();
var refreshTokens = await account.GetRefreshTokens().ToListAsync();

It’s also possible to restrict the query to a particular Application, given the Application’s href:

1
2
3
4
var accessTokenForApplication = await account
    .GetAccessTokens()
    .Where(x => x.ApplicationHref == myApp.Href)
    .SingleOrDefaultAsync();

Revoke Access and Refresh Tokens

Revoking the access and refresh tokens for an account is necessary in some situations, such as:

  • The user has explicitly logged out
  • The user’s device or client has been compromised, and you need to force them to re-authenticate

Revoking tokens is a simple manner of deleting the appropriate resource:

1
2
3
4
// Get a reference to an IAccessToken or IRefreshToken by looking it up by href,
// or by querying the GetAccessTokens() or GetRefreshTokens() collections.

await token.DeleteAsync();

Create and Parse JSON Web Tokens (JWTs) in .NET

At the heart of token authentication is the JSON Web Token, which is a standard and compact way of storing identity and claims as a string, with an optional cryptographic signature to prevent tampering. Access and refresh token strings are JWTs that have been Base64-encoded to make them URL-safe.

This SDK release includes built-in support for constructing, signing, parsing, and validating JWTs that use the HMAC SHA-256 (HS256) algorithm.

Construct and Sign JWTs

The IClient interface exposes a builder that can construct JWTs:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
IJwtBuilder builder = client.NewJwtBuilder();

// IJwtBuilder supports setting any standard JWT claim,
// plus arbitrary claims that you define:
builder
    // Set the Audience (aud) claim
    .SetAudience("Darth Vader")
    // Set the Expiration (exp) claim
    .SetExpiration(DateTimeOffset.Now.AddDays(10))
    // Set the JWT ID (jti) claim
    .SetId($"jwt-id-{Guid.NewGuid()}")
    // Set the Issued-At (iat) claim
    .SetIssuedAt(DateTimeOffset.Now)
    // Set the Issuer (iss) claim
    .SetIssuer("Lord Sidious")
    // Set the Subject (sub) claim:
    .SetSubject("Secret Plans")
    // SetClaim() can be used to add any claim as a key-value pair:
    .SetClaim("title", "Death Star")
    // SignWith() is used to sign the JWT with a secret key:
    .SignWith("my_secret_key_123", Encoding.UTF8);

// Build the JWT
IJwt jwt = builder.Build();

The IJwt interface represents a constructed or parsed JWT, and includes a deserialized body (payload):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// jwt.Base64Header, jwt.Base64Payload, and jwt.Base64Digest
// contain the original base64 parts of the JWT
string base64Digest = jwt.Base64Digest;

// The header is represented as a dictionary
var alg = jwt.Header["alg"];

// The deserialized body is available via Body
string aud = jwt.Body.Audience;
DateTimeOffset exp = jwt.Body.Expiration.Value;

// IJwtClaims includes some helper methods for working with claims
bool containsTitle = jwt.Body.ContainsClaim("title"); // true
string title = jwt.Body.GetClaim("title").ToString();

// Get a string representation of the entire JWT
string token = jwt.ToString();

The result of IJwt.ToString() is Base64-encoded and guaranteed to be URL-safe.

Parse and Validate JWTs

Likewise, IClient also exposes a JWT parser and validator:

1
2
3
4
5
6
7
8
IJwtParser parser = client.NewJwtParser();

// Parse and validate a JWT
IJwt parsedJwt = parser
    // Sets the secret key used to sign the JWT
    .SetSigningKey("my_secret_key_123", Encoding.UTF8)
    // Verifies and deserializes the JWT
    .Parse(token);

If validation fails, the appropriate exception derived from InvalidJwtException will be thrown. By default, the signature and lifetime (Expiration and Not-Before claims) are validated when parsing any JWT. You can add additional validation requirements with the Require methods:

1
2
3
4
5
6
7
8
9
IJwt parsedJwt = parser
    // If these claims do not exist, a MissingClaimException is thrown
    // If the claim exists but the value does not match, a MismatchedClaimException is thrown
    .RequireAudience("Darth Vader")
    .RequireIssuer("Lord Sidious")
    .RequireClaim("title", "Death Star")
    .SetSigningKey("my_secret_key_123", Encoding.UTF8)
    // Verifies and deserializes the JWT
    .Parse(token);

That’s all there is to it!

Token-based authentication and JSON Web Tokens are powerful tools for building modern web and mobile applications that are secure and scalable. The Stormpath .NET SDK simplifies the process of creating and managing tokens, so you can focus your effort on building your application.

What’s Next for the .NET SDK?

There’s plenty more to come! Here’s what’s on the roadmap:

  • Integration with ASP.NET
  • SAML Support

Is there something specific you want to see? Report bugs and feature requests on Github or shoot us an email.

New! SAML Support For Your Customer Apps

$
0
0

Support SAML in your application with Stormpath

Integrate with Popular SAML Identity Providers in Minutes.

Today we launched support for the SAML standard for authentication and user management.

Applications that use Stormpath for user management will now be able to use popular identity providers (IdPs) for Single Sign-On (SSO) capability. In other words, Stormpath-backed apps are now SAML service providers that work with SAML services like OneLogin, Okta, Salesforce or any other SAML IdP, including home-grown and open source options.

SAML support is one of the features most frequently requested by our customers, and it raises the bar on the enterprise-readiness of the Stormpath service. With multi-tenant customer partitioning, LDAP/AD integration, social login, high scalability and availability, Stormpath can fully support identity in an enterprise service or cloud platform. B2B applications that require multi-tenancy or have customers using different IdPs will save a great deal of time (and frustration) with this feature. User-initiated Single Sign-On also lets you build applications that provide a seamless end-user experience.

And if you want to skip reading, Sign Up for our free Webinar, “No-Code SAML Support with Stormpath” on Thursday January 21st, 10am PT / 1pm ET.

Let’s dive in!

First, What Is SAML?

SAML (Security Assertion Markup Language) is an XML-based standard for securely exchanging authentication and authorization information between entities—specifically between identity providers, service providers, and users. Well-known IdPs include Salesforce, Okta, OneLogin, Shibboleth. Your apps are the SAML service providers, and the Stormpath API makes it possible to integrate them with the IdPs (but without headaches).

Stormpath SAML Service Provider Support

Our initial support for SAML includes an update to the Stormpath REST API, along with our SDKs (see Resources below). Instead of working with XML or even directly with SAML itself, Stormpath allows you to set up SAML consumption by just adding some configuration to our SDK and the Stormpath console. From there, your applications can consume SAML assertions from any SAML IdP.

Now you can create applications that deliver a unified and seamless SSO experience for end users, without any custom code. Stormpath-backed applications can now authenticate users without requiring a separate login. Like all features at Stormpath, SAML support comes with pre-built customer screens and workflows through ID SIte.

Easy SAML Consumption from Any IdP

With Stormpath your application can support multiple IdPs, so you can connect your application to separate userstores, e.g. Okta, Salesforce, and Shibboleth with just a little configuration. This makes it easy to meet your customer requirements: if one customer needs your app to connect to their home-grown IdP, and another uses Ping Identity, Stormpath SAML makes the integration easy for your applications and developers.

Configuration-based attribute mapping enables seamless support for different identity providers, allowing them to assert account attributes into your application. For example, if one IdP says that variable firstName=Tom and another IdP says fn=Tom, you can use Stormpath to map both to a variable called givenName within your application.

Multi-Tenant Customer Data Are Built In

Many Stormpath-backed applications use our robust Authorization functionality to partition customer organizations in their SaaS application, and this release makes SAML very accessible for those applications.

Typically, SAML implementations require a separate instance for each identity provider. Stormpath’s approach to SAML support is free from this constraint, giving you the flexibility to support diverse IdPs for different customer organizations within the same instance of your application. This also makes it easy to achieve customer compliance and privacy requirements, without a lot of operational overhead to also support SAML.

SP-Initiated Login Flows or IdP-Initiated Flows

Stormpath SAML support also provides flexibility in the point of entry for authentication. End users can access the IdP portal first and then be automatically authenticated for the Stormpath-backed application. Or they can enter through the Stormpath-backed application and automatically be authenticated for all the apps attached to the IdP as well.

Stormpath SAML Resources

We will be publishing a number of tutorials and demos for SAML support in our SDKs in the coming weeks.

Build Multi-Tenant .NET Applications

$
0
0

Designing multi-tenant applications can be tricky. The previous sentence may have been an understatement.

The ability to quickly spin up a new instance of your application is a powerful business case, but getting there involves serious engineering. Partitioning user data (and making sure it stays partitioned) is critical. A common use case involves treating a subdomain of your application URL as a tenant identifier (the acme in acme.yourapplication.com). Incoming requests are then examined and connected to the correct data source based on the subdomain.

Designing for multi-tenancy involves modeling your data stores from the start with multiple tenants in mind. Data security should also be a major consideration. Anyone else have a headache yet?

Have no fear! Alongside support for token-based authentication, the latest release of our .NET SDK also includes full support for the Organization resource, which can make developing multi-tenant applications a lot simpler.

Build Multi-Tenant .NET Applications with Organizations

The high-level overview of using Stormpath to build multi-tenant applications is covered in the Multi-Tenancy with Stormpath guide.

The Organization resource represents a tenant of your application, and is a top-level container for Stormpath Account Stores (Directories and Groups). In addition to logically organizing (and separating) Account Stores, it includes some special sauce for working with multi-tenant applications. The nameKey property must be unique across all of your Organizations, and must follow DNS hostname rules. This constraint specifically designed to support the “subdomain as a tenant identifier” use case.

The .NET SDK makes it easy to:

  • Create and manage Organizations
  • Add Directories and Groups to an Organization
  • Assign an Organization to an Application as an Account Store
  • Authenticate an Account against an Organization

Create and Manage Organizations

Creating an Organization is a snap:

1
2
3
4
5
var rebels = client.Instantiate<IOrganization>()
    .SetName("Rebel Alliance")
    .SetNameKey("rebels") // must be unique and follow DNS hostname rules
    .SetDescription("The Rebellion Against the Empire"); // optional
await client.CreateOrganizationAsync(rebels);

Updating an existing Organization is also straightforward:

1
2
3
4
5
6
7
8
// organizationHref is the Stormpath href of the Organization
var rebelsOrg = await client.GetOrganizationAsync(organizationHref);

// Disable the Organization. Login attempts will be rejected.
rebelsOrg.SetStatus(OrganizationStatus.Disabled);

// Save changes
await rebelsOrg.SaveAsync();

Add Directories and Groups to Organizations

Organizations represent top-level containers for Directories and Groups. Adding Account Stores to an Organization can be accomplished in a few ways:

1
2
3
4
5
6
7
8
9
10
11
12
// Add an existing IDirectory or IGroup instance:
await rebels.AddAccountStoreAsync(myGroupOrDirectory);

// Or, add by name:
await rebels.AddAccountStoreAsync("My Group Or Directory Name");

// Or, add by href:
await rebels.AddAccountStoreAsync(hrefOfGroupOrDirectory);

// Or, perform a lookup query that matches one Directory or Group:
await rebels.AddAccountStoreAsync<IDirectory>(
    dirs => dirs.Where(d => d.Name.StartsWith("My Dir")));

Just like Applications, an Organization can have a default Account Store and a default Group Store, which are the default locations for newly-created Accounts and Groups. If the default store is null, new Accounts or Groups cannot be created in the Organization. These properties can be updated with the appropriate methods:

1
2
3
4
5
6
7
8
9
10
11
12
13
// Get the default Account Store for an Organization
IAccountStore defaultAccountStore = await rebels.GetDefaultAccountStoreAsync();
// defaultAccountStore is an IDirectory or IGroup, or null

// Set the default Account Store
await rebels.SetDefaultAccountStoreAsync(myGroupOrDirectory);

// Get the default Group Store for an Organization
IAccountStore defaultGroupStore = await rebels.GetDefaultGroupStoreAsync();
// defaultGroupStore is an IDirectory, or null

// Set the default Group Store
await rebels.SetDefaultGroupStoreAsync(myDirectory);

Assigning an Organization to an Application

The Organization itself is an Account Store, so it can be assigned to an Application:

1
await myApp.AddAccountStoreAsync(rebels);

Adding an Organization to an Application will enable login for all of the Accounts contained in Directories and Groups assigned to the Organization, as well as any that are added in the future.

Authenticate Using Organizations

Stormpath handles login attempts using a specific login flow that iterates through all the Account Stores associated with an Application. In multi-tenant applications, you frequently need to restrict login to a specific tenant. This is possible by specifying an Organization (or Organization nameKey) during login:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// Using an IOrganization instance
var loginResult = await myApp.AuthenticateAccountAsync(
    request =>
    {
        request.SetUsernameOrEmail("lskywalker");
        request.SetPassword("whataPieceofjunk$1138");
        request.SetAccountStore(rebels); // restrict search to Rebel Alliance tenant only
    });

// Using an Organization href string
var loginResult = await myApp.AuthenticateAccountAsync(
    request =>
    {
        request.SetUsernameOrEmail("lskywalker");
        request.SetPassword("whataPieceofjunk$1138");
        request.SetAccountStore(rebels.Href);
    });

// Using an Organization nameKey
// (This is handy if you're using a subdomain identifier
// that you can quickly pull out of the request URL!)
var loginResult = await myApp.AuthenticateAccountAsync(
    request =>
    {
        request.SetUsernameOrEmail("lskywalker");
        request.SetPassword("whataPieceofjunk$1138");
        request.SetAccountStore("rebels"); // Tenant with nameKey "rebels" must exist
    });

That’s all there is to it! Using Organizations and the features available in the Stormpath .NET SDK can make the development of multi-tenant .NET web applications faster and easier.

Further Reading

For more reading, check out:


How to: Secure Connected Microservices in Spring Boot with OAuth and JWTs

$
0
0

If you’re a developer who, like myself, loves Microservices for their flexibility and scalability then you’ve probably run into this challenge:

How can you easily scale your application while maintaining the security and efficiency of service-to-service communications?

Microservices consist of many independent processes communicating with each other over an API. The keyword there is many. All of these processes need to exchange information to perform complex tasks, and each communication exposes your application to vulnerabilities and latency.

In this post, I’m going to show you how to secure service-to-service communications using OAuth and JWTs. We’ll use a Spring Boot app consisting of two Stormpath-backed services. In this example, you authenticate to the first service, which calls the second service to get a response.

Then, we’ll speed things up by reducing the number of calls over the wire with a distributed cache. Caching FTW!

Jot This Down: Use JWTs for property packed tokens

At the heart of the service-to-service communication are JWTs (pronounced “jots”). JWT stands for JSON Web Token and is an open source standard. The Stormpath Java SDK makes use of the open source JJWT library for anything that requires a token. This is everything from our outward facing OAuth2 integration, to our own SSO service called ID Site.

JWTs can function purely as tokens. That is, a string of letters and numbers with no inherent meaning that services make use of. For instance, in an OAuth authorization workflow, the server will create an access token and store it on the Account for future lookup. End users will present the token to identify themselves and the server will do a lookup to confirm that it matches what is has on file.

However, JWTs are so much more. This is because there can be meaningful information encoded into a JWT. This information is called “claims”. There are a number of default claims, including issuer, subject and others. The standard supports custom claims – meaning, you can encode any type of text based key/value pair you want into a JWT. This enables us to work with tokens in a very powerful way. For instance, a JWT may carry information on what level of access a user has to your application.

Most importantly, JWTs can be digitally signed. This makes it possible to ward against man in the middle attacks as you can verify a JWT in code using standard signing and verification algorithms.

It’s also worth noting the JWTs can be encrypted. This is a step beyond signing. Today, most JWTs are signed, but are not encrypted. This kind of JWT can be easily decoded and, as such, you would never have sensitive information in a JWT of this type. With encryption, new possibilities for passing sensitive data within a JWT arise. Upcoming releases of the JJWT library will include support for encryption.

An exhaustive look at JWTs is beyond the scope of this post. However, this blog post goes into a lot of detail.

Secure Microservice Calls Between Friends

We want to be absolutely sure that our two Microservices can trust each other. JWTs to the rescue!

By using a shared key to sign the JWT that we pass from one service to the other, we can be confident in trusting the JWT by verifying the signature. We can pack whatever information we want to communicate from one service to the other right into the JWT.

Building JWTs with the Java Fluent Interface

1
2
3
4
5
6
7
8
9
10
JwtBuilder jwtBuilder = Jwts.builder()
    .setSubject(account.getHref())
    .setIssuedAt(new Date(System.currentTimeMillis()))
    .setExpiration(new Date(System.currentTimeMillis() + (1000 * 60)))
    .setId(UUID.randomUUID().toString());

String secret = client.getApiKey().getSecret();
String token = jwtBuilder.signWith(
    SignatureAlgorithm.HS512, secret.getBytes("UTF-8")
).compact();

Let’s break this down, line by line.

The JJWT library provides a fluent interface for building JWTs.

Line 1 – and each succesive method call – returns a JwtBuilder object.

Lines 2 – 5 put information into the JWT using the standard claims, subject, issued at, expiration and id. These claims have short names that are specified in the standard. These are sub, iat, exp, and id. The subject is the key bit of information we want to send to the second service. It identifies the Account of the authenticated user by href.

Line 7 is crucial to the way this all hangs together securely. We need a shared key so that both Microservices can verify the authenticity of the JWT that’s passed in. The Stormpath Client already has access to its API Key Secret. The combination of the API Key ID and the API Key Secret are what allows your application to securely communicate with Stormpath. We can reuse the API Key Secret as the shared secret between the services.

Lines 8 – 10 sign the JWT using the Stormpath Client’s API Key Secret. The call to compact returns the final encoded String representation of the JWT. This is what we will pass across the wire from one service to the other.

A Look at the Guts of a JSON Web Token

Here’s an example of what the above code produces (newlines added for clarity):

1
2
3
eyJhbGciOiJIUzUxMiJ9.
eyJzdWIiOiJodHRwczovL2FwaS5zdG9ybXBhdGguY29tL3YxL2FjY291bnRzLzNqaXpRalFRc0JUc3VrRU5tY3VXS2oiLCJpYXQiOjE0NTI2OTkxNTEsImV4cCI6MTQ1MjY5OTIxMSwianRpIjoiZWNlMjlmMjItZGRiNy00OTBiLTg0NjEtYTk2NjFjMWY1YjAzIn0.
fRwYRK6lU-ucOhARQdDwxU2ixdQVfYzlTgHiU-6TWTDeHh2icdeO9Y6Ad2wBr9gj_hp9XmyxepBTm3I-dAG-3g

The middle string is the payload. Decoded, the payload looks like this:

1
2
3
4
5
6
{
  "sub": "https://api.stormpath.com/v1/accounts/3jizQjQQsBTsukENmcuWKj",
  "iat": 1452699151,
  "exp": 1452699211,
  "jti": "ece29f22-ddb7-490b-8461-a9661c1f5b03"
}

Microservices In Action

Let’s take a look at our two services working and then we’ll look at some more of the code.

Stormpath Admin Console Configuration

In order for the example code to work, you’ll need to configure your Stormpath Application and create some Accounts. First, create a Stormpath account here.

In your Stormpath Admin Console, do the following:

  1. Create an Application and make note of the href
  2. Create a Directory and map it to the application
  3. Create a Group in the Directory and make note of the href
  4. Create a number of Accounts and add at least one to the Group from the previous step

For this example, I’ve created these accounts:

  1. nick.fury@avengers.com
  2. iron.man@avengers.com
  3. captain.america@avengers.com
  4. hulk@avengers.com
  5. thor@avengers.com

And, I’ve added nick.fury@avengers.com to the admin group.

Here’s what it looks like in the admin console:

Application:

application

Admin Group:

group

Accounts:

accounts

Admin Group Accounts:

group_accounts

Microservices Launchpad – Right from Your Commandline

Now, let’s fire up our Microservices and see it in action! Note: There is one application codebase, but we are going to start two servers running on different ports. One of the servers will connect to the other as you will see below.

  1. Build the application:

    mvn clean package

  2. Start the first server (default port 8080):

     STORMPATH_API_KEY_FILE= \
     STORMPATH_APPLICATION_HREF= \
     java -jar target/*.jar
     
  3. Start the second server (port 8081):

     STORMPATH_API_KEY_FILE= \
     STORMPATH_APPLICATION_HREF= \
     STORMPATH_ADMIN_GROUP_HREF= \
     java -Dserver.port=8081 -jar target/*.jar
     

We’re going to interact with the first server right from the command line using curl. We’ll authenticate using a standard OAuth2 workflow called grant_type=password. For more information on OAuth, checkout this excellent blog post. We even have a podcast devoted to the topic!

First, we’ll get an access token.

1
2
3
4
5
curl -X POST \
  -H "Origin: http://localhost:8080" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=password&username=nick.fury@avengers.com&password=Passw0rd$" \
http://localhost:8080/oauth/token

Notice that I am passing in the username and password. In a real production environment, you would want this to be an https connection. In fact, Stormpath insists on it!

Here’s what the response looks like:

1
{"access_token":"eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiJhODMxMTEyNC05MzAxLTQwODEtOTU1NC01OWVmM2M4NmRiNGYiLCJpYXQiOjE0NTI3MDc3MTMsInN1YiI6Imh0dHBzOi8vYXBpLnN0b3JtcGF0aC5jb20vdjEvYWNjb3VudHMvNjloRTNZZ3hobzhRUFpiNXNyWWI4cyIsImV4cCI6MTQ1Mjk2NjkxM30.tl-73bkrofE0QxjCoMVGQNZ1JFv9GyXQlfMgT2_4w8Y","token_type":"Bearer","expires_in":259200}

Look familiar? Yup – the access_token is a JWT.

Next, as part of the OAuth flow, we will use the access token we got in the previous step as a Bearer token for our service.

1
2
3
curl \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiJhODMxMTEyNC05MzAxLTQwODEtOTU1NC01OWVmM2M4NmRiNGYiLCJpYXQiOjE0NTI3MDc3MTMsInN1YiI6Imh0dHBzOi8vYXBpLnN0b3JtcGF0aC5jb20vdjEvYWNjb3VudHMvNjloRTNZZ3hobzhRUFpiNXNyWWI4cyIsImV4cCI6MTQ1Mjk2NjkxM30.tl-73bkrofE0QxjCoMVGQNZ1JFv9GyXQlfMgT2_4w8Y" \
http://localhost:8080/accounts

And, here’s the response:

1
2
3
4
5
6
7
8
9
10
11
{
    "emails": [
        "hulk@avengers.com",
        "nick.fury@avengers.com",
        "thor@avengers.com",
        "captain.america@avengers.com",
        "iron.man@avengers.com"
    ],
    "status":"OK",
    "message":"Success!"
}

Maybe not much to look at, but behind the scenes, we’ve achieved service-to-service communication! Huzzah!

Before we look deeper into the code, let’s look at what happens if we try the same thing with an account that’s not an admin. As a convenience, the code repo has a bash script that asks for your email and password and does the two curl commands for you.

1
2
3
4
5
6
7
8
9
 ./get_accounts.sh
email: hulk@avengers.com
Password:

{
    "emails":null,
    "status":"ERROR",
    "message":"You must be an admin!"
}

The system works!

Code Walkthrough: Combining Spring Boot, OAuth & JWT

In the pom.xml file, there are three primary dependencies: The Stormpath Java SDK, the JJWT library and the Apache HttpClient library. We use the HttpClient library to connect from one service to the other.

Here’s the first service endpoint from MicroServiceController.java:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@RequestMapping("/accounts")
public @ResponseBody AccountsResponse accounts(HttpServletRequest req) throws Exception {

    if (!isAuthenticated(req)) {
        throw new UnauthorizedException("You must authenticate!");
    }

    Account account = AccountResolver.INSTANCE.getAccount(req);

    // create a new JWT with all this information
    JwtBuilder jwtBuilder = Jwts.builder()
        .setSubject(account.getHref())
        .setIssuedAt(new Date(System.currentTimeMillis()))
        .setExpiration(new Date(System.currentTimeMillis() + (1000 * 60)))
        .setId(UUID.randomUUID().toString());

    String secret = client.getApiKey().getSecret();
    String token = jwtBuilder.signWith(
        SignatureAlgorithm.HS512, secret.getBytes("UTF-8")
    ).compact();

    return communicationService.doRemoteRequest(remoteUri + REMOTE_SERVICE_ENDPOINT, token);
}

Lines 4 – 6 are making sure that the incoming request is from an authenticated user. The Bearer token in the request ensures this.

Lines 11 – 20 we saw earlier. That’s there we are creating our signed JWT.

Line 22 calls a Spring @Service that makes the request of our second server.

Here’s what that service looks like. The file is CommunicationService.java:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
@Service
public class CommunicationService {
    public AccountsResponse doRemoteRequest(String url, String token) throws Exception {
        // make request of other micro-service
        GetMethod method = new GetMethod(url + "?token=" + token);
        HttpClient httpClient = new HttpClient();
        int returnCode = httpClient.executeMethod(method);

        BufferedReader br = new BufferedReader(
            new InputStreamReader(method.getResponseBodyAsStream())
        );
        StringBuffer buffer = new StringBuffer();
        String line;
        while(((line = br.readLine()) != null)) {
            buffer.append(line);
        }

        ObjectMapper mapper = new ObjectMapper();
        return mapper.readValue(buffer.toString(), AccountsResponse.class);
    }
}

Lines 5 – 16 make use of the Apache HttpClient to make an HTTP request to our other server.

Lines 18 and 19 take advantage of the Jackson JSON serialization/deserialization features built into Spring. It’s taking the raw text String returned from our second server and deserializing that into the AccountsResponse object.

Here’s the second service endpoint from MicroServiceController.java:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@RequestMapping(REMOTE_SERVICE_ENDPOINT)
public @ResponseBody AccountsResponse microservice(@RequestParam String token) throws Exception {

    if (!Strings.hasText(token)) {
        throw new UnauthorizedException("Missing or Empty token!");
    }

    // verify jwt
    String secret = client.getApiKey().getSecret();
    Jws<Claims> claims =
        Jwts.parser().setSigningKey(secret.getBytes("UTF-8")).parseClaimsJws(token);

    String accountHref = claims.getBody().getSubject();

    Account account = client.getResource(accountHref, Account.class);

    return adminService.buildAccountsResponse(account);
}

Lines 9 – 11 verify the JWT using the API Key Secret from the Stormpath Client. Notice that we are again using the Stormpath Client API Key Secret. It’s our shared secret. If the signature on the JWT is not valid, an Exception is thrown when parseClaims is called.

Line 17 calls a Spring @Service that builds our response.

Here’s AdminService.java:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
@Service
public class AdminService {
    @Value("#{ @environment['stormpath.admin.group.href'] }")
    String adminGroupHref;

    @Autowired
    Application application;

    public boolean isAdmin(Account account) {
        return account.isMemberOfGroup(adminGroupHref);
    }

    public AccountsResponse buildAccountsResponse(Account account) {
        AccountsResponseBuilder accountsResponseBuilder = AccountsResponseBuilder.newInstance();
        if (isAdmin(account)) {
            List<String> emails = getAllEmails(application);
            accountsResponseBuilder.emails(emails).status(STATUS.OK).message("Success!");
        } else {
            accountsResponseBuilder.status(STATUS.ERROR).message("You must be an admin!");
        }

        return accountsResponseBuilder.build();
    }

    private List<String> getAllEmails(Application application) {
        List<String> emails = new ArrayList<String>();
        for (Account acc : application.getAccounts()) {
            emails.add(acc.getEmail());
        }
        return emails;
    }
}

Line 15 ensures that the Stormpath Account passed in is a member of the admin Group. If so, then we build a list of email addresses. If not, then we set the status to ERROR.

The important thing is that an AccountsResponse object is always returned. This makes for a consistent API.

Distributed Cache: Spring Boot Makes It Pluggable

Now that we have our services speaking to each other, let’s see what optimizations we can make.

The Stormpath Java SDK comes with a configurable cache out of the box. That cache is really only designed to be used within a single JVM.

The cache subsystem is completely pluggable and, in conjunction with the Spring Boot integration, it’s super easy.

Let’s look at the network interaction with no distributed cache.

I’ve enabled wire logging on the two application servers. What this means is that every interaction over the network will be shown in the log in detail.

Running through the same example as before, we can see that both the first and second application servers are interacting with Stormpath over the Internet.

8080_wire

8081_wire

Now, let’s enable a distributed cache. For this example, we’ll use Hazelcast. Note: Stormpath is completely cache agnostic. Hazelcast, Redis and others are easy to drop in. The only requirement for a Spring or Spring Boot application is that the cache system supports the CacheManager interface.
In the application.properties, we’ll change:

1
stormpath.hazelcast.enabled = false

to

1
stormpath.hazelcast.enabled = true

To understand how this property is used, let’s take a look at the CacheConfig.java file:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Configuration
@ConditionalOnProperty(name = {"stormpath.hazelcast.enabled"})
public class CacheConfig {
    @Bean
    public HazelcastInstance hazelcastInstance() {
        return Hazelcast.newHazelcastInstance();
    }

    @Bean
    public CacheManager cacheManager() {
        // The Stormpath SDK knows to use the Spring CacheManager automatically
        return new HazelcastCacheManager(hazelcastInstance());
    }
}

This takes advantage of some of the great Spring Boot magic, which is all about automatic configuration.

Line 1 identifies this class as a Configuration to Spring.

Line 2 is where the stormpath.hazelcast.enabled property comes into play. The Spring Boot @ConditionalOnProperty annotation ensures that this configuration will only be loaded if the stormpath.hazelcast.enabled is set to true.

Let’s look at this in action. As you can see below, Hazelcast automatically discovers nodes running on the same network. Each Tomcat instance fires up a Hazelcast node and then the nodes connect to each other.

hazelcast_8080

hazelcast_8081

Retrieving the Account in the first server triggers an interaction with Stormpath as expected.

Now, let’s see what happens when the Account object is retrieved in the second service this time:

hazelcast_8081_cache

This time, the Account comes from the cache, which Hazelcast has automatically distributed around to its nodes.

Using a distributed cache in conjunction service-to-service communication minimizes the number of round trips to Stormpath over the Internet.

Exception Handling for Consistent APIs

We want our Microservice to return an AccountsResponse object – no matter what. So, what happens if there’s an Exception? Spring Boot makes it easy to catch Exceptions and return whatever you want.

1
2
3
4
5
6
7
8
@ExceptionHandler(UnauthorizedException.class)
@ResponseStatus(HttpStatus.UNAUTHORIZED)
public @ResponseBody AccountsResponse unauthorized(UnauthorizedException ex) {
    return AccountsResponseBuilder.newInstance()
        .status(AccountsResponse.STATUS.ERROR)
        .message(ex.getMessage())
        .build();
}

The @ExceptionHandler annotation is the hook that causes Spring Boot to associate the named Exception (UnauthorizedException in this case) with the method.

When an UnauthorizedException is thrown, the unauthorized method is entered. An AccountsResponse object is created and returned. And, it’s this object that will be returned from the original method.

Recap

Well, it’s been quite a journey!

In this post, we’ve explored how to:

  1. Enable communication between two Microservices
  2. Secure that communicaton using signed JWTs
  3. Optimize the traffic that goes over the wire using a distributed cache
  4. Handle Exceptions using Spring Boot’s @ExceptionHandler annotation

Feel free to drop a line over to email anytime.

Like what you see? to keep up with the latest releases.

The Fundamentals of REST API Design

$
0
0

Here at Stormpath, we give developers easy access to user management features – including authentication, authorization, and password reset – via our REST API and language-specific SDKs. Our team of experts began with already-significant knowledge about REST+JSON API design. In the process of building the REST API, they learned even more. Our CTO, Les Hazelwood, gave a well-received presentation to a group of Java developers on REST+JSON API design best practices, which you can watch here:

We’ve also written posts on how best to secure your REST API, as well as linking and resource expansion in REST APIs. This post will give a high level summary of the key points that Les touches on in his talk – specifically the fundamentals of good REST+JSON API design.

So Why REST?

Keeping the goal of rapid adoption of an API in mind, what makes RESTful APIs so appealing? Per Dr. Roy Fielding’s thesis on the REST paradigm, there are 6 distinct advantages of REST:

  1. Scalability – not necessarily its performance, yet rather how easy it is for RESTful APIs to adapt and grow and be plugged into other systems.

  2. Use of HTTP – being able to use HTTP methods to manage resources makes RESTful APIs easy to plug into other applications.

  3. Independency – with a REST API you can deploy or scale down specific parts of the application, without having to shut down the entire application or an entire web server form.

  4. Reduced latency due to caching – REST APIs prioritize caching, which helps to improve latency. So always keep caching top of mind when you’re developing your REST API.

  5. Security – HTTP specification lets you sport security via certain HTTP headers, so you can leverage this to make your API secure.

  6. Encapsulation – there are parts of the application that don’t need to be exposed to a REST caller, and REST as an architectural style allows you to encapsulate those gritty details and only show things that you need to show.

And Why JSON?

  1. Ubiquity – over 57 percent of all web-based applications have JSON, are built on JavaScript, or have JavaScript components.

  2. Human readable – it uses very simple grammar and language, so a human can easily read it, including folks just starting to get into software development.

  3. It’s easy to change or add new fields.

What makes REST design difficult?

RESTful APIs are difficult to design because REST is an architectural style, and not a specification. It has no standard governing body and therefore has no hard and fast design rules. What REST does have is an interpretation of how HTTP protocol works, which allows for lots of different approaches for designing a REST API. While use of HTTP methods is a core advantage of the REST approach, it also means that there are lots of different RESTful API designs. We’re going to focus on some of the best guidelines that we’ve come up with in designing our REST API.

REST API Design Guidelines

1. Keep your REST API resources coarse grained, not fine grained

Basically, you don’t know how your user is going to interact with your resources. In the case of Stormpath, resources would be accounts, groups, or directories. There are lots of different actions they might run on those resources and if they are adding in lots of arguments to methods they’ve written for a particular resource, it can be difficult to manage. So we recommend that, for a given resource in your REST API, you write a method that takes the resource itself as an argument, and the method contains all the functionality needed for said resource.

How else do you keep things coarse grained? You work with collection and instance resources. A collection resource is what it sounds like – basically a folder containing similar resources. An instance resource is a singular instance of its parent resource. This allows you to use HTTP behavior that affects an end point definition (an instance resource), but doesn’t actually create another url for each instance-behavior combination. So don’t add behavior to the actual end point definition.

2. Use POST to take advantage of partial updates in your REST API

Since REST APIs run on standard HTTP methods, you can use PUT or POST to either create or update resources. You might think of using PUT to create a resource and POST to update a resource, but you can actually use POST for both, and that’s recommended.

Why would you want to use POST to both create and update a resource?

Because with POST you don’t need to send over all fields for that data resource on every call you make, whereas with PUT, you do. This is important because if for every update you make you are also sending over fields that are not updating, then your data plan is consuming more than it needs to. Using POST instead of PUT can be beneficial if your REST API is metered as it limits the quantity of traffic. Furthermore, when you get into millions or hundreds of millions of requests per month, that impacts your REST API’s performance – so use POST to limit the traffic.

And why can’t you do the same with PUT?

Because per HTTP specification, PUT is idempotent, meaning it has to have all its properties included (or the result will not be the same). For example, if you first create an application without specifying a description, and then in a fourth call you send in the description, the state may have been different in between, therefore breaking the idempotency mandate.

3. Have REST API documents link to other documents based on the notion of a media type

A media type is a specification of a data format and a set of parsing rules associated with that specification. With your REST API, if you’re writing as a client, be sure to include your preferred data format you would like returned in the accept-header. Likewise, as the server, return back a content-type header that notes how the data is actually being returned. You can also add additional parsing rules to whatever data type you’re using. For example, you might have media type application/JSON+foo which tells the client not only is this JSON formatted data, but it’s also foo, which tells the client how to parse that data.

So make sure to send through accept headers specifying what media type you want (if on the client side), send through content-type headers telling the client what data format you are returning (if on server side), and take advantage of customizing your own media types to make your rest API more flexible for your clients.

Conclusion

In this post we’ve covered the advantages of the RESTful API design approach, as well as the fundamentals for creating a developer-friendly REST API. This is merely a summary of Les’ points, and only the first 30 minutes at that, so be sure to check out the rest of the presentation.

Like what you see? to keep up with the latest releases.

Parse is Shutting Down. What's Next for Your Backend?

$
0
0

Like many other mobile app developers, I was really sad to hear that Parse is shutting down. I use Parse quite heavily for some of my personal projects, and I appreciate how Parse enables mobile-first teams to build apps at lightning speed. They also did a phenomenal job at sunsetting their product.

As developers look to migrate off Parse to their own infrastructure, we’ve started to field some questions about how Stormpath is different to Parse, and how developers can leverage Stormpath in their apps.

Many developers see Parse as a useful way to prototype and ship an app quickly, but plan to migrate to their own backend as they gain traction. Parse starts to work against you as you scale. Because of the Parse shutdown, it’s time to evaluate if you should deploy a copy of Parse Server, evaluate another Backend as a Service (BaaS) provider, or migrate your backend off Parse.

Deploy Parse Server

Deploying Parse Server might seem like the easiest option for now. Even though it’s a nontrivial amount of work, you can keep your backend up and running without trouble. However, this can cause problems if you’re not careful.

What many people don’t realize is that Parse Server is not Parse’s infrastructure open-sourced. Instead, it’s a “Parse Compatible” server to keep your Parse apps running. In the migration guide, Parse says “there may be subtle differences in how your Cloud Code runs in Parse Server”. As a developer, I’m not excited to find and fix these “subtle differences”.

Also, Parse Push isn’t one of the open-sourced components, so you’ll still have to look into deploying your own push notification server, and rewrite your logic around that.

Deploying Parse Server, while a great stopgap mechanism, doesn’t look like a winning solution in the long term, and really only looks useful for small personal projects or apps in maintenance mode.

Migrate to Another BaaS Provider

While a clear equivalent isn’t clear just yet, many BaaS providers are already rushing to build migration tools that’ll help you move your application to their service. Even without Parse, other BaaS providers offer a similar value proposition — you’ll be able to build your apps quickly without worrying about the backend.

However, I can’t imagine the transition to be very easy. Just like the edge cases I’m worried about with Parse’s open source server, there will be even more with migrating to another BaaS. Features may not be exactly the same, with some missing and some working in different fashions. As Parse was super feature-rich, I would expect many headaches trying to learn and rewrite your backend for another BaaS provider.

Several entrepreneurs have taken this as an opportunity to build their own Parse-compatible backends, or deploy a hosted version of Parse Server. I’m optimistic about this; I love Parse and would probably use one of these services for my side projects. However, would you want to use this for your business? It’d be difficult to evaluate the trustworthiness of these startups; some of them might shut down less gracefully with Parse, and where would you be then?

Build Your Own Backend

For any mobile app with a sizable amount of traction, I think this makes the most sense.

Many developers have already planned to move off Parse as they grow. Now is the right time to evaluate if you should build your own backend. Utilizing a BaaS provider in the long run limits your ability to build an application tailored to your needs, as you start pushing up against the limits of the built-in data models and design patterns, as well as performance issues related to their architecture.

Having made the decision to build your own backend, you’ll now need to figure out your authentication and authorization schemes. Perhaps you’ve decided on a service-oriented architecture, and you’ll need multiple backend services (possibly written in different languages) to access the same user data. Or, you need to move beyond sessions to using tokens so you can have a scalable backend that works across multiple services & platforms.

Writing that boilerplate for your authentication mechanisms takes valuable time which could be used for building actual features in your app. Do you want to spend the time building, deploying, and maintaining yet another service?

Why Stormpath?

Stormpath can help your team write a secure, scalable application without worrying about the nitty gritty details of authentication, authorization, and user security. We have easy SDKs for popular languages and frameworks including Express.js so that adding a authentication for your application can be done in as little as 15 minutes, and can be shared across multiple teams, web applications, and APIs. And if the need arises, your data is still yours and you’ll always be able to migrate off Stormpath.

In summary, Stormpath helps backend developers build better applications faster by dealing with the hard issues of building a rock-solid authentication system. If you’re considering building your own backend now that Parse is closing, I hope you consider Stormpath for your needs.

Try it now! Sign up for an account and try one of our quickstarts to see how easy it is to begin using Stormpath, or contact us to learn about how we can help migrate your user data to Stormpath.

Like what you see? to keep up with the latest releases.

Getting Started with SAML in PHP Applications

$
0
0

SAML PHP

Rolling out your own SAML integrations has always been hard. It’s a complex implementation that’s difficult to build securely and efficiently whether you’ve built it before or not. Here at Stormpath, we’ve rolled out a simple solution to enable SAML in your applications without custom code!

With only a few steps, you can integrate SAML into your PHP project. No matter which identity provider you are using, the code will remain the same. We can even help you with a no-code SAML experience with our ID Site integration. In this tutorial, we’ll walk you through how to enable SAML support for easy setup and usage of your favorite SAML provider with the Stormpath PHP SDK.

What Is SAML?

SAML (Security Assertion Markup Language) is an XML-based standard for securely exchanging authentication and authorization information between entities—specifically between identity providers, service providers, and users. Well-known IdPs include Salesforce, Okta, OneLogin, Shibboleth. Your apps are the SAML service providers, and the Stormpath API makes it possible to integrate them with the IdPs (but without headaches).

Set Up Your SAML Provider for PHP Applications

Configuration of a SAML provider is stored under a directory in Stormpath. This means the first step will be setting up a directory as a SAML directory. As a refresher, setting up a directory using the Stormpath PHP SDK looks like this:

1
2
3
4
5
$directory = \Stormpath\Resource\Directory::create([
  'name' => 'My directory',
    'description' => 'My directory description'
]);
    

This will create a basic cloud directory in the Stormpath system. To make this a SAML directory, we have to first instantiate a SAML provider then attach it to a directory. To instantiate a SAML provider, you use the following code:

1
2
3
4
5
6
$samlProvider = \Stormpath\Resource\SamlProvider::instantiate([
    'ssoLoginUrl' => '',
    'ssoLogoutUrl' => '',
    'encodedX509SigningCert' => ,
    'requestSignatureAlgorithm' =>
]);
  • SSO Login URL: The URL at the IdP to which SAML authentication requests should be sent. This is often called an “SSO URL”, “Login URL” or “Sign-in URL”.
  • SSO Logout URL: The URL at the IdP to which SAML logout requests should be sent. This is often called a “Logout URL”, “Global Logout URL” or “Single Logout URL”.
  • Signing Cert: The IdP will digitally sign auth assertions and Stormpath will need to validate the signature. This will usually be in .pem or .crt format, but Stormpath requires the text value.
  • Signing Algorithm: You will need the name of the signing algorithm that your IdP uses. It will be either “RSA-SHA256” or “RSA-SHA1”.

Once you have your provider instantiated, you then just add one item to the directory creation. As part of the properties, add a provider item and make it equal to the instantiated provider.

1
2
3
4
5
$directory = \Stormpath\Resource\Directory::create([
  'name' => 'My SAML Provider Directory',
    'description' => 'My SAMP Provider Directory description',
    'provider' => $samlProvider
]);

Now you have a SAML provider you can work with for your application.

Configure Your Service Provider In Your Identity Provider

Your Identity Provider (IdP) needs to understand some information about the Service Provider. We’ve simplified this process by providing a url that you can either give to your IdP, or gather the data from the url which includes all the information needed. To access this information, you have to get it from the directory provider.

1
2
$provider = Stormpath\Resource\SamlProvider::get(self::$directory->provider->href);
$providerMetaData = $provider->serviceProviderMetadata;

This will give you a few items that you need to provide to your IdP. For some IdP’s you can give them the href that is provided as part of this response and they know how to handle it. We follow the standard format for the meta data. Other IdP’s will require you to get some of the information from here and provide it to them. The information you will need from the response follows:

  • Assertion Consumer Service URL: This is the location the IdP will send its response to.
  • X509 Signing Certificate: The certificate that is used to sign the requests sent to the IdP. If you retrieve XML, the certificate will be embedded. If you retrieve JSON, you’ll have to follow a further /x509certificates link to retrieve it.
  • SAML Request Binding: Set to HTTP-Redirect.
  • SAML Response Binding: Set to HTTP-Post.

Configure Your Application To Allow Callbacks

Configuring your application is an important part of the process. You will need to tell your application what urls it is allow to have the IdP send your users back to. These urls should be hosted by you. We have made it just like updating any other property on your application.

1
2
3
4
5
6
$application->setAuthorizedCallbackUris([
    'http://myapplication.com/whatever/callback',
    'http://myapplication.com/whatever/callback2'
]);

$application->save();

Map SAML Attributes To Stormpath

You may be asking yourself now about how Stormpath knows what values to use when putting the account information into the stormpath directory. This is all done from the Attribute Mapping Statements. IdPs will provide you with an XML that has data that you can pull from.

1
2
3
4
5
6
7
8
9
10
11
<saml:AttributeStatement>
    <saml:Attribute Name="uid" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
      <saml:AttributeValue xsi:type="xs:string">test</saml:AttributeValue>
    </saml:Attribute>
    <saml:Attribute Name="mail" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
      <saml:AttributeValue xsi:type="xs:string">jane@example.com</saml:AttributeValue>
    </saml:Attribute>
      <saml:Attribute Name="location" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
      <saml:AttributeValue xsi:type="xs:string">Tampa, FL</saml:AttributeValue>
    </saml:Attribute>
  </saml:AttributeStatement>

In this response you can see that there is a list of attributes and in each attribute is a Name and NameFormat. These are two values that you can use to map it to an attribute in Stormpath. In the above example let’s use the following mapping:

  • uid maps to Stormpath’s username
  • mail maps to Stormpath’s email
  • location maps to a custom data attribute for the account city_state

When mapping these attributes, you can use either name or nameFormat, or both. Stormpath will match as much as you provide to get the attribute value and map it to the correct account field. To set up this mapping, run the following:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
$provider = \Stormpath\Resource\SamlProvider::get($directory->provider->href);

$ruleBuilder = new \Stormpath\Saml\AttributeStatementMappingRuleBuilder();
$rule = $ruleBuilder->setName('uid')
    ->setAccountAttributes(['username'])
    ->build();

$rule2 = $ruleBuilder->setName('mail')
    ->setAccountAttributes(['email'])
    ->build();
$rule3 = $ruleBuilder->setName('location')
    ->setAccountAttributes(['customData.city_state'])
    ->build();


$rulesBuilder = new \Stormpath\Saml\AttributeStatementMappingRulesBuilder();
$rulesBuilder->setAttributeStatementMappingRules([$rule, $rule2, $rule3]);
$rules = $rulesBuilder->build();

$provider->setAttributeStatementMappingRules($rules);

$provider->save();

Once these are mapped, Stormpath does just in time provisioning of the account so we are always synced with the IdP. Stormpath will see the xml that is returned from the IdP and find the attributes that you want to map and map them to what you defined them to.

How to Use Your SAML Provider for PHP Applications

Now that you have set up your SAML provider in your application, you can now use it for logging in. For this example, we are going to make a request to ID Site. Build a login request and redirect the user to ID Site:

1
2
3
4
5
$application = \Stormpath\Resource\Application::get($applicationHref);

$redirectTo = $application->createIdSiteUrl(['callbackUri'=>'{CALLBACK_URI}']);

header('Location: ' . $redirectTo); //or any other redirect method you want to use.

Once here, You should see your SAML Provider as an option on the login screen. Login

Further Reading

Stormpath is really excited to offer SAML as part of the PHP SDK. We have full documentation on our github page where you can go further into detail. We will soon be offering SAML support inside of our integrations as well. Let us know what you think about our SAML support.

Feel free to drop a line over to email anytime.

Like what you see? to keep up with the latest releases.

Secure Password Hashing in Node with Argon2

$
0
0

Storing passwords securely is an ever-changing game. For the past few years (2013 –> 2015), Jean-Philippe Aumasson has been running a world-renowned Password Hashing Competition in which security researchers submit, validate, and vet the best password hashing algorithms.

Just recently, the competition wrapped up, naming Argon2 king of the hashing algorithms.

This is good news for any web developer out there: you can now use the Argon2 algorithm to more securely store your user’s passwords!

Today I’m going to show you how you can easily hash your user’s passwords using the Argon2 algorithm, and introduce you to some best practices.

Argon2 Recommendation

In the crypto community, standards are created by holding open competitions in which researchers analyze various cryptographic algorithms, slowly looking for faults, weeding out the weaker submissions.

This is how Argon2 (pdf) was born.

The Password Hashing Competition yielded 24 separate hashing algorithm submissions, which was eventually pruned down to 9 finalists, out of which Argon2 was named the winner.

What does this mean for normal web developers? If you’re starting a new project, or looking to improve security on an existing project, you should immediately start using the Argon2 hashing algorithm to securely store all of your user passwords.

If you’re into C, you can look at the reference Argon2 implementation on Github here: https://github.com/P-H-C/phc-winner-argon2

Using Argon2 in Node.js

As of just a few weeks ago, you can now get started using Argon2 in Node, thanks to efforts by Ranieri Althoff.

First up, you need to install the argon2 npm package:

1
$ npm install argon2

Next, you need to install (globally) the node-gyp library — this is required as it allows the argon2 library to use the underlying C implementation of the Argon password hashing implementation to function:

1
$ npm install -g node-gyp

Once this is done, you need to ensure your project is a Git repository — this is required because of the way the underlying Argon2 library is being used. To ensure you’re in a Git repository, you can run the following command:

1
$ git init

Next up, you’ll need to import the argon library:

1
var argon = require('argon2');

Now, let’s say you receive a password from a user and want to securely hash the password for storage in a database system, you can do this using the hash method:

NOTE: We’ll also let the argon2 library generate the cryptographic salt for us as well in a secure fashion.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
argon.generateSalt((err, salt) => {
  if (err) {
    throw err;
  }

  argon.hash('some-user-password', salt, (err, hash) => {
    if (err) {
      throw err;
    }

    console.log('Successfully created Argon2 hash:', hash);
    // TODO: store the hash in the user database
  });
});

Now, after you’ve stored a user’s Argon2 hash, how can you log a user in using the plain text password to verify it is correct? Using the verify method, of course!

1
2
3
4
5
6
7
8
argon.verify('previously-created-argon-hash-here', 'some-user-password', err => {
  if (err) {
    console.log('Invalid password supplied!');
  } else {
    console.log('Successful password supplied!');
    // TODO: log the user in
  }
});

And that’s pretty much it, easy right?!

Summary

If you’re building new webapps, you should check out the NPM argon2 module for securely hashing your user passwords. It’s the new recommended password hashing algorithm, so don’t be afraid to get your hands dirty!

Also: if you’re looking for a service that makes creating users and storing user data really simple and secure, be sure to go sign up for Stormpath! We’re free to use, and provide all sorts of awesome features, including transparent password hashing upgrades, secure user data data storage, and lots more.

We even have an amazingly simple and powerful express library that makes building secure websites and API services a few lines of code =)

How to Create a Multi-Tenant User Model for SaaS Applications

$
0
0

Multi-tenant data management is core to the success of any Software as a Service application. With multi-tenancy, SaaS vendors can provide one version of their product to multiple customers instead of building a unique codebase for each one. However, giving your customer organizations a private partition of your SaaS application can be incredibly complicated to build and maintain.

Fortunately, Stormpath was designed for user management in SaaS applications. In this post, we’ll go over how to build secure customer partitions with Stormpath’s multi-tenant architecture out-of-the-box.

Simplified Multi-Tenant User Storage

Stormpath is a separate user system that allows you to connect multiple applications with a shared user base. This makes it really powerful for SaaS Applications, which is what Stormpath was designed for. Not only can you support multiple Customer Organizations within your data store, you can connect multiple applications. If you’re serving your customer a suite of products and services, you can handle their authentication seamlessly between those services, and partition their user data so that they are secure and separate from each other.

What is Multi-Tenant Authorization?

Imagine you’re building a big self-storage building. Inside your big building you build one storage unit. Now the one storage unit you’ve built and rented out is probably not going to make a profitable business for you. The great thing about storage units is that they’re easily replicated. You don’t need a new building, you already have that, and each storage unit has a lock on it granting access only to the set of people that know the combination.

Building out applications for Multi-Tenancy is similar to this. Your application is the big building. We want to grant access to specific groups that are separated from each other. These are called Organizations of people.

Multi-Tenancy models Customer Organizations. It partitions parts of your user database between separate Customer Organizations. Let’s say you’ve built a SaaS application and sold it to Purple Company and Green Company. Those user stores live in partitioned buckets.

Types of Multi-Tenant Applications

There are different three different approaches to Multi-Tenancy that you can choose from when building your application.

Manual Selection Before Authentication

This is when you have an extra field on your log in form where the user would manually type in their Organization. They might type in “Green” for the Organization that they belong to, and then enter their email and password as usual.

Manual Selection After Authentication

First the user would authenticate using their username and password. Then they land in the lobby of the application where they select their Organization from a list. The user would select the right one and go to the main part of the app.

Automatic Selection by Subdomain

This post will focus on the easiest type of Multi-Tenancy to manage for your users which is Automatic Selection by Subdomain. It’s an advanced Multi-Tenant feature supported by Stormpath. Let’s look at how to build this.

Build a Multi-Tenant Application With Automatic Selection by Subdomain

Let’s say you’re building this super sweet new WizBang app and are using Stormpath to manage your user identities. Inside of Stormpath, you’ll create a Stormpath Application backed by a Stormpath Directory. When your user wants to log into your application, they fire up their browser, go to green.wizbang.com, and authenticate.

Users see this process as a completely white label experience. They don’t need to see anything about Stormpath, just the typical authentication process that they’re used to.

Support a Separate User Organization

Next you want to support a new Organization worth of users in the same application. Without Multi-Tenancy support you’d need to replicate this architecture. You would need to have a separate instance of your application, a separate identity management system, and a separate Stormpath application. Stormpath makes Multi-Tenancy easy by letting you swap out that Directory for a core object in Stormpath called the Organizations.

Multi-Tenant Organizations in Stormpath

In Stormpath, Organizations are just a different type of Account Store. Organizations have a unique identifier called an Organization Name Key that matches up to a subdomain of your domain. That’s when you get the automatic subdomain feature of Multi-Tenancy.

multi-tenancy diagram

In this diagram there’s one Organization called Green. If we want to support another Organization named Purple, we simply create an Organization with a Name Key of Purple. It has its own directory of users without redeploying or recreating a separate application. You now have Multi-Tenant support for different Organizations of users!

How to Create Organizations in the Stormpath Console

Let’s take a look at the Stormpath Admin Console and how this works. Across the top of the Stormpath Admin Console, you’ll see the first class objects that Stormpath has to manage user identities. Organizations are first class objects in Stormpath.

First, let’s create a Stormpath Application called WizBang. This WizBang application will have Account Stores consisting of the accounts that are allowed to access this application.

account stores

You’ll see that those Organizations have a Name Key. WizBang Green should have the Name Key of “Green” and WizBang Purple should have the Name Key of “Purple”. Typing in the URL purple.wizbang.com or green.wizbang.com takes us through the Account Stores of these different Organizations for authentication and authorization.

These Organizations have their own Account Stores. The Directory is where we will store the identities of users that are allowed to login. In Purple we have J. Jones, and in Green we have an account called B. Smith.

directory

Hosted Authentication and Authorization Workflows with ID Site

ID Site is a hosted set of authentication and authorization workflows including login registration, forgot my password, change my password, etc. ID Site is powerful for multi-tenancy because it supports the idea of wild carding. For security reasons, you have to specify authorized URLs and authorized redirects. Users will hit your applications and be redirected to ID Site at login.

When they’ve successfully authenticated at ID Site, they’ll be redirected back to your application. You can put in a custom name for your domain that’s secured by your SSL key insert. Then when users are getting redirected to ID Site they only ever see your domain. They have no knowledge that Stormpath is behind the user identity management.

Multi-Tenancy in Your Application

Let’s jump into the app and see this in action. We’ll open an Incognito Window and go to green.wizbang.com. Your application is already aware of the user’s Organization based on the subdomain.

green application home

When we click the login button, we’re redirected to ID Site. That is the long URL up top and can be customized as your domain.

green login

Let’s log in as B. Smith. If you remember, we created accounts in each of the Directories that back the Organizations. We see this “welcome to the Green organization” and it knows us by name. Now we’ve been redirected back into the application and successfully authenticated.

green welcome screen

If go through the same process on purple.wizbang.com we’ll see the same introductory page that knows the Organization based on subdomain. We can log in as J. Jones and it knows what Organization we belong to.

However, if we try to log in to the Purple Organization as B. Smith it’s not going to let us because B. Smith does not belong to the Purple Organization.

Behind the scenes there is a single application running. That’s the power of Multi-Tenancy, you don’t have to replicate your architecture in order to support it!

Add a New Tenant to Your Organization

Let’s say you want to add a new Tenant and support a new Organization worth of users. All you need to do is to create a new Organization and map it into your application.

In the Organizations tab, we’ll create a new Organization called WizBang Blue and give it the Name Key of “Blue”.

We need to give it an Account Store just like we did for the other Organizations. We’ll set up the WizBang Blue Directory and, just like the other directories, create an Account under it.

The last step is go into the WizBang application. Add that Organization as an Organization Mapping for the application.

We’ve gone from supporting Green and Purple to now supporting Blue. Let’s go to blue.wizbang.com.

By updating information in the Stormpath Admin Console, we can now log in with this account and get the same Organizational partitioning by Subdomain.

add organization

It’s that easy to work with Organizations and Multi-Tenancy by Subdomain! Most of it is just configuration in the admin console, your code doesn’t have to change.

Custom Data

We don’t want to update our application overtime we add new tenants. However, there may be some customizations or specialized features that you want to support based on the Organization. Stormpath’s newest feature, Custom Data, allow you to access unstructured JSON programmatically. For the WizBang application, we can define Custom Data to create a customized experience based off the Organization.

![custom data](/images/blog/2016-01-28-multi-tenancy-for-saas-applications/custom_data_raw.png

Recap

We’ve gone over Stormpath’s prebuilt authorization and how to easily configure groups, permissions, and customer organizations for your Multi-Tenant SaaS. We store and secure all your customer profile data, so you don’t need a user database at all. We also allow you to implement Single Sign-On across your applications by asserting a customer identity across connected applications. And with Stormpath’s hosted ID Site, you don’t have to build any customer login interactions or screens.

ID Site is fully supported in all of our libraries. For more information on how to set up ID Site in your application, check out our docs.

You can watch the full demo how to add multi-tenancy to your application here.

Feel free to drop a line over to email anytime.

Like what you see? to keep up with the latest releases.

Stormpath React SDK: Introducing custom login and registration forms

$
0
0

Building forms has never really been any fun. But with the new custom forms feature that we’ve added to the Stormpath React SDK, it suddenly is. This custom forms functionality means you’ll have the ability to plug in your own markup to the forms for user login, registration and reset password without having to think about any of the logic behind them.

React developers can now simply style the form quickly, and Stormpath will take care of all the rest.

Let’s Build a User Form in React

Before we get started: If you haven’t played around with React or want to try these examples in a sample application, then take a look at our previous blog post Build a React.js Application With User Authentication or play along with the example project.

Default Markup

Forms in the Stormpath React SDK still work as previously. If no markup is provided, the form will simply render with the default Boostrap markup, i.e.

1
<LoginForm />

This actually turns into:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<LoginForm>
  <div className='sp-login-form'>
    <div className="row">
      <div className="col-xs-12">
        <div className="form-horizontal">
          <div className="form-group">
            <label htmlFor="spEmail" className="col-xs-12 col-sm-4 control-label">Email</label>
            <div className="col-xs-12 col-sm-4">
              <input className="form-control" id="spUsername" name="username" placeholder="Username or Email" />
            </div>
          </div>
          <div className="form-group">
            <label htmlFor="spPassword" className="col-xs-12 col-sm-4 control-label">Password</label>
            <div className="col-xs-12 col-sm-4">
              <input type="password" className="form-control" id="spPassword" name="password" placeholder="Password" />
            </div>
          </div>
          <div className="form-group">
            <div className="col-sm-offset-4 col-sm-4">
              <p className="alert alert-danger" spIf="form.error"><span spBind="form.errorMessage" /></p>
              <button type="submit" className="btn btn-primary">Login</button>
              <Link to="/forgot" className="pull-right">Forgot Password</Link>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</LoginForm>

Custom Markup for Login Forms

Now, adding your own markup to user forms is easy. When markup is passed to the form, the form will automatically process that markup and bind common input fields and buttons depending on their input type and name. The conditions (spIf) and bindings (spBind) available depend on the form used.

To demonstrate this, a simple, stripped-down login form can look like:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<LoginForm>
  <p>
    <input type="text" name="username" placeholder="Username" />
  </p>
  <p>
    <input type="password" name="password" placeholder="Password" />
  </p>
  <p spIf="form.error">
    <strong>Error:</strong> <span spBind="form.errorMessage" />
  </p>
  <p>
    <input type="submit" value="Login" />
  </p>
</LoginForm>

Field Mapping

As previously mentioned, when markup is provided to a form, that markup is processed and input fields are mapped, with available fields varying by form. For the login form, the valid fields are username (or login, the username to login with) and password (the password to login with).

In order to map an input to the username field, all you have to do is to set the input name to the field name:

1
<input type="text" name="username" />

If you’re interested in seeing what fields can be mapped for the registration or reset password form, take a look at [the Stormpath React documentation][].

Conditional Statements

In order to control what is being shown, each form has a specific set of spIf conditions that you can use. For the login form, the available conditions are form.processing, which is true when the form is loading, and form.error, which is set to true when there is a bindable error message.

In order to only show an element during a form.error, all you need to do is set the spIf attribute:

1
2
3
<p spIf="form.error">
  Form error occurred. Please try again.
</p>

If you’re interested in seeing what spIf conditions are available for the registration or reset password form, take a look at [the Stormpath React documentation][].

Bind Values

In order to show certain texts, spBind can be added on an element to bind that element to a value. For the login form, the bindable values are form.errorMessage, which is an error message present when the form.error condition is true.

So in order to show an error message during a form.error, all you need to do is to set the spBind attribute on an element, as shown below:

1
2
3
<p spIf="form.error">
  <span spBind="form.errorMessage" />
</p>

If you’re interested in seeing what spBind values are available for the registration or reset password form, take a look at [the Stormpath React documentation][].

Intercept Form Submit

If an onSubmit attribute is set on a form, then the handled function attached to that attribute will be called once a form is submitted. The handler that you attach can be used to do custom error validation or format the data that is posted to Stormpath, i.e. providing your own onSubmit handler for the login form would look like:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class LoginPage extends React.Component {
  onFormSubmit(e, next) {
     var data = e.data;

    // Require passwords to be at least 10 characters.
    if (data.password.length < 10) {
      return next(new Error('Password must be at least 10 characters long.'));
    }

    // Force usernames to be in lowercase.
    data.username = data.username.toLowerCase();

    next(null, data);
  }

  render() {
    return <LoginForm onSubmit={this.onFormSubmit.bind(this)} />;
  }
}

Summary

As you’ve just seen demonstrated, the new custom forms feature really makes building forms a lot easier. It’s one of the many improvements we have added to the React SDK lately.

If you have any feedback on the custom forms feature or the React SDK in general. Feel free to leave that in the comment section below.


Hello, Stormpath!

$
0
0

edward jiang

Hi! I’m Edward, and it’s with great pleasure that I’d like to announce that I’m joining the Stormpath team as a Developer Evangelist for iOS!

I’ve always been excited by technology and its potential to change the world. I spent my summers reading about the exponential growth of computing power, how it opened up entirely new markets for computing, and the entrepreneurs that made it happen. At that time, companies like Microsoft and Dell enabled ordinary individuals to access the power of computing, revolutionizing how we access information and communicate with each other.

When growing up, I’d run outside to check the mailbox, and return home with a handful of AOL CDs. To my young self those CDs represented the wonder of technology. While books and VHS tapes were big, bulky, and expensive to store and distribute, mailing CDs seemed like a much better distribution model.

As technology improved, downloads eliminated the CD, web apps eliminated the install process, and mobile apps enabled rich, personal experiences for everyone.

Why Mobile Is Important

While surprising to many, mobile traffic already exceeds desktop traffic on the internet, and will continue to grow as users find the convenience and richer experiences better than a web interface in a desktop environment. Uber spawned hundreds of similar “on-demand” startups after pioneering its ride hailing service, and permanently increased the speed and transparency consumers expect from service companies. Venmo allowed individuals to send money in a way that was faster and safer than cash, and ultimately was acquired by PayPal to jumpstart its business in the mobile sphere. Mobile is a huge opportunity for many businesses to redefine themselves, and the ones that truly understand mobile will be the ones that continue to grow.

Even with these increased opportunities, mobile is a challenging platform to develop for, because it’s limiting in many ways. Smaller screen sizes limit the amount of information apps can present to users, while users will only give an app several minutes of their time before deleting it from their phone. Nobody sits down with a user manual and 30 minutes to learn how to use an app.

App developers need to invest in great onboarding experiences, because if a user deletes their app, every dollar spent on building and marketing the app is wasted. Account creation and logins need to be carefully crafted so they don’t interrupt the user flow.

What I’ll Be Doing

Stormpath does a great job at helping backend developers build authentication and authorization in their APIs and websites, but we’ve traditionally let backend developers work directly with mobile developers to develop the login flow. I’m the first person on the Stormpath team dedicated to thinking about how we can make our product better for mobile, and I’ll be working with our team to make sure that we help our customers build great mobile experiences.

I’ll start out by working with our customers and release an iOS SDK for our existing integrations, and continue improving it by making it as easy as possible for developers to add authentication to their apps, with pre-built ViewControllers, TouchID support, and more. The Stormpath iOS SDK will be the easiest way to plug in secure and scalable authentication into your apps.

After that, I’ll continue to advocate for and find ways to make the core Stormpath product more friendly for companies that want to build mobile-first.

In addition, you’ll start to see me at meetups, conferences, as well as on the Stormpath blog talking about how you can leverage mobile more effectively! If you’re in the Bay Area, I’m also always happy to meet up and talk about mobile trends and the future =]

I’m excited to be part of the Stormpath team, and can’t wait to help create awesome mobile experiences everywhere! Want to chat? Just send an email: edward@stormpath.com, or on Twitter @EdwardStarcraft.

Stormpath Laravel Event Firing Squad

$
0
0

At Stormpath, we want to make it as easy as possible to create your application. Our Laravel Integration is no exception.

Events give developers an important tool to hook into different parts of a package to run your own business logic. Events can dramatically simplify application development, particularly when adding user functionality to a webapp.

A recent update to the Stormpath Laravel integration adds events fired by the built-in Laravel event system which your Laravel app can listen for and handle however you like, and use them to hook into user features like registration, login, logout, and more.

Let’s dive in to see how it works!

What Are Events?

An event in a programming language is a way to notify the developer of something that happened or is about to happen. This event can contain any kind of information, and a developer can program against that information.

One example of this is when a user signs up for your application. Without events, you must code everything related to the signup process. This can make your code very hard to maintain and very messy.

When you create a user signup event, you can trigger various sign-up related processes off that event. Things like sending an email to the user about signup, creating the user in the database, sending alerts to administration, and more.

Why Are Events Important?

There are many reasons why events are important. One of the main reasons is the single responsibility principle. Without events, your signup controller would be responsible for many different things during signup. When you fire an event, you can have handlers listen for them and handle what they need to. Doing so, allows you to not worry about what happens when a user signs up, but allows other parts of your application to handle it.

One of the other big advantages of using events is the flexibility of your code. When starting out with your application, there are some basics that you will want to include for a user registration. Later on, you may have some other business logic that you want to add to the process. With events, this is easy, you add a new process and attach it to the event. There is no need to go into the user registration code to add it there, cluttering up your controller.

What Events Stormpath Laravel Offers

At Stormpath, we want to give you the ability to have every aspect of the Laravel integration fire an event. Thanks to one of our community users of the Stormpath Laravel package, Kryten0807, we now offer events for every process.

The following events (and their corresponding classes) are triggered during Stormpath operations:

  • UserIsRegistering: A potential new user has completed the registration form and submitted it. The form data has passed validation. (cancellable)
  • UserHasRegistered: A new user has registered.
  • UserIsLoggingIn: A user has completed the login form and submitted it. The form data has passed the initial validation, but the user has not been authenticated yet. (cancellable)
  • UserHasLoggedIn: A user has successfully logged in.
  • UserIsLoggingOut: A user has visited the logout URL but has not been logged out yet. (cancellable)
  • UserHasLoggedOut: A user has successfully logged out.
  • UserHasRequestedPasswordReset: A user has completed the password reset form and the password reset email has been sent.
  • UserHasResetPassword: A user has successfully reset their password.

All of the above are the class names for the event and they live in the Stormpath\Laravel\Events namespace

Listening For Stormpath Laravel Events

Continuing with the examples from above of registering a user, lets say you have some business logic that needs to run before a user account is created. To do this, we offer the UserIsRegistering event. This event will be triggered before a user is created at Stormpath allowing you to run your business logic and stopping the registration if needed. You will first need to register a listener for this event:

1
2
3
4
5
protected $listen = [
    'Stormpath\Laravel\Events\UserIsRegistering' => [
        'App\Listeners\HandleNewUserIsRegistering',
    ],
];

This can be placed in your EventServiceProvidrer file of your Laravel install. For more information about events and registering them, please visit the Laravel Documentation.

The file App\Listeners\handleNewUserIsRegistering is a class in your application which handles the event when it is fired. The listener class is defined according to the Laravel documentation on defining listeners.

Terminating Event Actions

There may be times when it is necessary to halt processing based on some processing you are doing in your listener. To do this, simply return false from the handle method of your listener. Note that this will only have an effect for the events that are marked as “cancellable” in the table above.

For example, maybe you want to prevent a user from registering if their first name is “Bob”. Your handler should look like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public function handle(UserIsRegistering $event)
{
    // get the form data that the user has submitted
    //
    $data = $event->getData();

    // check the givenName field
    //
    if ($data['givenName']=='Bob') {
        return false;
    }

    // the name is not Bob, so just carry on...
}

This will abort the registration request. When this is done, a Stormpath\Laravel\Exceptions\ActionAbortedException will be thrown. In the example above, you might catch that exception & redirect the user to a page that says “No Bobs Allowed!”

Try It Out

With the addition of the events in the Stormpath Laravel package, we have opened up a whole new way to work with the package, making it a much more flexible system that is also easier for you to work with.

For full documentation on the events that are used, visit our documentation page.

Let us know what you think of this addition. We love your feedback. You can contact us at support@stormpath.com or hit us up on Twitter @goStormpath.

Like what you see? to keep up with the latest releases.

Getting Started With SAML Single Sign-On in .NET

$
0
0

Single Sign-On (SSO) is a simple idea that can quickly cause developers not-so-simple headaches. At a high level, it’s very straightforward: SSO is what allows you to sign into Gmail and switch over to Google Calendar or YouTube without typing your password in again. It’s so common that you probably use it every day without thinking – and so do your users.

Like most “simple” things in software engineering, making single sign-on work on the backend can be painful. Stormpath already makes SSO between your applications easy with our ID Site solution, and we recently rolled out support for another flavor of single sign-on: SAML.

What is SAML?

SAML (Security Assertion Markup Language) is a standard for exchanging authentication and authorization information between parties. As far as standards go, it’s a relatively old one – it was ratified over a decade ago. As a result, it’s been adopted by a large number of identity providers, such as Salesforce, Okta, OneLogin, and Ping Identity (to name a few).

SAML allows you to sign into a site with your credentials from one of these providers. If you’ve ever used your Salesforce credentials to log in somewhere that wasn’t Salesfoce, for example, you’ve used SAML.

Service Providers vs. Identity Providers

The terminology of SAML can be a little confusing at first glance. There are two main entities:

  • The SAML Service Provider (SP) – This is your application, which will ask an IdP for authentication information when a user tries to log in.

  • The SAML Identity Provider (IdP) – The service that stores the user’s actual credentials – such as Salesforce, OneLogin, or an open-source system like Shibboleth.

Easy SAML SSO for Your .NET Applications

A downside of SAML being an old standard is that it relies on paradigms from the early-2000s, namely every developer’s favorite way of tearing out their hair expressing data: XML. This is one of the reasons why many teams find it difficult to quickly implement SAML.

Never fear! The SAML support in the Stormpath .NET SDK can significantly decrease the time (and pain) it takes to implement SAML login in your .NET application.

If you’re using an older version of the SDK, be sure to update to release 0.5 or greater. That release contains all the SAML goodies.

Then, follow the SAML configuration guide to set up a Stormpath Directory with SAML credentials, and configure your identity provider on the other side.

Time for some code! You’ll need a SAML login controller which constructs a special URL and redirects the user:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class LoginController : Controller
{
    public async Task<ActionResult> Index()
    {
        var app = await stormpathClient.GetApplicationAsync("myApplicationHref"); // Your Stormpath Application href

        var samlUrlBuilder = await app.NewSamlIdpUrlBuilderAsync();
        var redirectUrl = samlUrlBuilder
            .SetCallbackUri("myCallbackUrl") // The URL to your callback controller, see below
            .Build();

        HttpContext.Response.Headers.Add("Cache-control", "no-cache, no-store");
        HttpContext.Response.Headers.Add("Pragma", "no-cache");
        HttpContext.Response.Headers.Add("Expires", "-1");

        return Redirect(redirectUrl);
    }
}

After the user authenticates with the external identity provider, Stormpath will redirect the browser back to the callback URL that you defined. (Make sure this URL is in your Application’s authorized callback URI list!)

The callback controller will need to handle the incoming assertion:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public class LoginRedirectController : Controller
{
    public async Task<ActionResult> Index()
    {
        var app = await stormpathClient.GetApplicationAsync("myApplicationHref"); // Your Stormpath Application href

        var incomingRequest = HttpRequests.NewRequestDescriptor()
            .WithMethod(Request.HttpMethod)
            .WithUri(Request.Url)
            .Build();

        var samlHandler = app.NewSamlAsyncCallbackHandler(incomingRequest);

        try
        {
            var accountResult = await samlHandler.GetAccountResultAsync();
            var account = await accountResult.GetAccountAsync();

            // Success! Do something with the account details
        }
        catch (InvalidJwtException ije)
        {
            // JWT validation failed (see Message property for details)
        }
        catch (SamlException se)
        {
            // SAML exchange failed (see Message property for details)
        }

        return RedirectToAction("Index", "Home");
    }
}

That’s all there is to it!

Further Reading

OAuth2 Token Management with Stormpath and Spring Boot

$
0
0

OAuth2 token management is often misunderstood and difficult to implement correctly. Fortunately, with Stormpath’s SDKs and integrations, we make Token Management easy – fun, even. This 20-minute tutorial will show you how to implement Token Management with Stormpath’s Spring Boot and Spring Security integrations.

While Spring Security does have built in OAuth2 support, there is no native token management support in Spring Boot, and working with the OAuth 2.0 protocol has been known to cause spontaneous outbreaks of hives, cold sweats, and prolonged “face desking”.

face_desk

Stormpath’s Spring Boot integration supports two OAuth flows: grant_type=password and grant_type=refresh_token. The Password Grant Type allows you to pass in a username and password and get back an Access Token and a Refresh Token. The Refresh Token Grant Type allows you to pass in a Refresh Token and get back a new Access Token.

They are both accessed through a single endpoint, /oauth/token, which is available out of the box with the Stormpath integration. So, fear not! Stormpath’s Token Management does all the heavy lifting. You just have to create the HTTP request using some basic rules discussed below.

Resources for This Tutorial

By then end of this post, you’ll have everything you need to swap a username and password for a set of tokens that allows a user to access restricted resources in an application. You’ll also be able to refresh and revoke tokens to provide a fine degree of control over how users access your application and how long they stay logged in.

The code that backs this post is here.

You can see the example in action at: https://jquery-spa.herokuapp.com (due to the Heroku sleep policy, you may have to wait a few seconds for the app to respond initially) and you can deploy it to your Heroku account right now using the button below.

Deploy

While Token Management is typically a behind-the-scenes affair, this example uses a SPA or Single Page Application. To keep the example simple (and javascript framework agnostic), all calls are made using jQuery’s ajax functionality.

Modern Token Management – Access And Refresh Tokens

In a modern application that supports OAuth2 Token Management, a user’s session typically has one Access Token with a short expiration and one Refresh Token with a longer expiration. When the Access Token expires, the application will use the Refresh Token to obtain a new Access Token. This process is repeated until the Refresh Token expires. At this point, the user would need to log into the application again.

For a deep dive into OAuth tokens and how they work, check out my colleague Randall’s post that explores OAuth in detail.

JSON Web Token (JWT) Security PSA

The OAuth2 specification does not specify a particular token format, so Stormpath uses JWTs to represent Access Tokens and Refresh Tokens. JWTs have additional information encoded into them, and more importantly, they are crytographically signed to provide conclusive evidence that the token has not been tampered with.

Stormpath Access Tokens also provide an important layer of additional security – they always contain a reference to the associated Refresh Token. This reference is a claim identified by the code rti. It’s one of the ways Stormpath ensures it is an Access Token being used to access a protected resource and not a Refresh Token. Other implementations of OAuth2 have (inadvertantly) allowed a refresh token to act as an access token, giving users longer access then they should have. We guard against that.

If you want to learn more about JWTs and how to use them securely, chech out our posts on how to Use JWTs the Right Way, Build Secure User Interfaces with JWTs, and Where to Store Your JWTs.

OK, with all that out of the way, lets get started!

Spring Security Configuration

In the sections that follow, we’re going to explore the example application through the lens of the jQuery calls that are made to the backend /oauth/token endpoint in the Spring Boot App.

Before we get to that, let’s look at the Spring Security configuration for this example application:

1
2
3
4
5
6
7
8
9
10
11
12
@Configuration
public class SpringSecurityWebAppConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.apply(stormpath()).and()
            .authorizeRequests()
            .antMatchers("/").permitAll()
            .antMatchers("/decode").permitAll()
            .antMatchers("/static/**").permitAll();
    }
}

Stormpath’s Spring Security integration follows the default access configuration for Spring Security which is that all paths are locked down.

In the above configuration, we are allowing unauthenticated access to / and /decode as well as any path within /static. We’ll see this in action as we work through the example below.

Let’s Get Some Tokens

There are two primary static files in our SPA example: home.html and static/js/token-management-guided-tour.js.

home.html is a Thymeleaf template in which the static/js/token-management-guided-tour.js javascript file is loaded.

Here’s a view of the different sections of home.html:

home

It’s broken down into 7 steps and the application walks you through the example, “guided tour” style.

The first step is to pass in an email and password and get back Access and Refresh Tokens. Let’s look at that in action.

Login with Email and Password

Here’s the jQuery code that processes the initial request to the /oauth/token endpoint (error and complete functions omitted for brevity):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
$('#login-form').submit(function (e) {

    var theForm = $('#login-form');

    $.ajax({
        type: 'post',
        url: '/oauth/token',
        data: theForm.serialize(),
        success: function (data) {
            accessToken = data.access_token;
            refreshToken = data.refresh_token;
            var accessTokenParts = accessToken.split('.');
            $.each(['header', 'payload', 'signature'], function (index, value) {
                $('#access-token-' + value).html(accessTokenParts[index]);
            });
            $('#login-error').hide();
            showOnlyDiv('access-token-div');
        }
    });

    e.preventDefault();
});

line 3 gives us a handle to the form.

Per the OAuth2 spec, the method will be POST and the Content-Type is application/x-www-form-urlencoded (this is the default for jQuery’s $.ajax call). The data passed to /oauth/token will look like this:

1
grant_type=password&username=<usernam>&password=<password>

This is the result of the call to theForm.serialize() on line 8.

The success handler which begins on line 9 stores the access_token and the refresh_token in local variables. It also displays the parts of the access_token (header, payload and signature) in your browser so you can see visually what the JWT looks like:

access_token

Note: As the screenshot shows, the example app is for demonstration purposes only. In “real life” you would not want to show an Access Token in the browser and you would want to use best practices for storing tokens in your client app. We have a great post on those best practices here.

Anatomy of a Stormpath Access Token

In the example app, if you click on the Decode button, you will see something like the following:

decoded

This shows you the header and the payload sections of the JWT that is the Access Token. To understand how we decoded our Access Token, we need to take a look at the decode method in the APIController in the example app:

1
2
3
4
5
6
7
8
9
@RequestMapping("/decode")
public Jws<Claims> decode(@RequestParam String token) throws UnsupportedEncodingException {

    Jws<Claims> claims = Jwts.parser()
        .setSigningKey(client.getApiKey().getSecret().getBytes("UTF-8"))
        .parseClaimsJws(token);

    return claims;
}

The method takes a JWT (which in this case is our Access Token) as a parameter and uses the JJWT library to parse out the claims. It also verifies that the JWT signature is valid as part of the parsing process. To do this, it uses the secret from the Stormpath Client which was used to create the JWT in the first place.

Finally, the method returns the Jws<Claims> object. This is where Spring Boot’s automatic Jackson JSON mapper kicks in and converts that object to JSON. Here’s what the raw response looks like:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
  "header": {
      "kid": "R92SBHJC1U4DAIMGQ3MHOGVMX",
      "alg": "HS256"
  },
  "body": {
      "jti": "6UBPQ975cDDiz8ckHqWIZF",
      "iat": 1456242057,
      "iss": "https://api.stormpath.com/v1/applications/2nBCvauLgETX8wO0VvS9mQ",
      "sub": "https://api.stormpath.com/v1/accounts/49CK1VvY2jQwUBH7UnP5zC",
      "exp": 1456245657,
      "rti": "6UBPQ5n0hcukMJWt5af1xB"
  },
  "signature": "Pm30FjdXOmx_fMGhfku85Z9xc6qE-EZgKHI4mV46KO8"
}

Notice that the body (payload) of the decoded JWT includes a reference to the Stormpath Account in the sub (subject) claim. It is this Account that is used when accessing restricted resources as we will see next.

Using an Access Token

After decoding the Access Token, the next step in our example app’s guided tour is to hit a restricted resource using that Access Token. Here’s the jQuery code that accomplishes that:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$('#restricted').click(function () {

    $('#account-info-table tbody').empty();
    $.ajax({
        type: 'get',
        url: '/restricted',
        beforeSend: function (xhr) { xhr.setRequestHeader('Authorization', 'Bearer ' + accessToken); },
        success: function (data) {
            var newRowContent = '<tr><td>' + data.fullName + '</td><td>' + data.email + '</td></tr>';
            $('#account-info-table tbody').append(newRowContent);
            showOnlyDiv('account-info-div');
        }
    })
});

Line 7 is the key here. We are setting the Authorization header with the keyword Bearer followed by our Access Token. Without this header, the request would be rejected. In your browser, you can try hitting: http://localhost:8080/restricted. You will be redirected to /login. This is a function of our Spring Security configuration. The /restricted path was not one of the paths that we explicitly allowed in the Spring Security configuration and as such, the request must be authenticated. To understand the response from /restricted, let’s look at the restricted method in the APIController:

1
2
3
4
5
@RequestMapping("/restricted")
public AccountInfo restricted(HttpServletRequest req) {
    Account account = AccountResolver.INSTANCE.getAccount(req);
    return new AccountInfo(account.getFullName(), account.getEmail());
}

This is simply returning an AccountInfo model object that has the full name and email address of the authenticated user. The AccountInfo object defined in the example app is easily converted to JSON by the same automatic Spring Boot mapper process that we saw above.

The jQuery success function above displays the Account information returned from the request to /restricted.

Token Management: It’s Refreshing!

The next step in our journey is to use the Refresh Token to obtain a new Access Token. In a typical mobile application, the following would happen behind the scenes without the user ever knowing:

  1. The current Access Token expires
  2. The user tries to access a restricted part of the application using the (expired) Access Token
  3. The application receives a 401 (unauthorized) HTTP response code
  4. The application uses the Refresh Token to obtain a new Access Token
  5. The application tries to access the restricted part of the applicaiton using the new Access Token
  6. The user sees the result of that request without having to login again

Note: If the Refresh Token has expired, then the user of the application would need to login again at Step 4

Stormpath provides an OAuth Policy in the admin console to set expirations for Access Tokens and Refresh Tokens.

A Look at the OAuth Policy

Here’s what the OAuth Policy looks like in the Stormpath Admin Console:

oauth policy

The default time-to-live for Access Tokens is 1 hour and the default TTL for Refresh Tokens is 60 days.

Refreshing the Access Token

When you click the Refresh the Access Token button in the example app, you get a response that looks like this:

refresh

This displays the new Access Token retrieved in the refresh process. To understand what’s going on there, we turn back to our jQuery code (success handler omitted for brevity):

1
2
3
4
5
6
7
8
9
10
$('#refresh').click(function () {

    $.ajax({
        type: 'post',
        url: '/oauth/token',
        data: 'grant_type=refresh_token&refresh_token=' + refreshToken,
        success: function (data) {
        }
    })
});

Once again, we are making an HTTP POST to the /oauth/token endpoint. Unlike the grant_type=password flow, this time we are using grant_type=refresh_token and we are passing in the Refresh Token we saved from earlier.

The response from this ajax call is a new Access Token which is then displayed in the browser underneath the old Access Token.

Kick that Token to the Curb

The last part of our Token Management joyride is revoking the Access and Refresh tokens. This is accomplished by hitting the (built in) /logout endpoint providing the Access Token as a Bearer token as we did when hitting a restricted resource earlier. Let’s look at the jQuery code that accomplishes this:

1
2
3
4
5
6
7
8
9
10
11
$('#revoke').click(function () {

    $.ajax({
        type: 'get',
        url: '/logout',
        beforeSend: function (xhr) { xhr.setRequestHeader('Authorization', 'Bearer ' + accessToken); },
        success: function () {
            showOnlyDiv('revoke-div');
        }
    })
});

Once again, the beforeSend function passed in to the $.ajax call is the key here. We’re sending an HTTP GET request to /logout. Providing the Access Token in the Authorization header enables Stormpath to delete that Access Token and its associated Refresh Token. This is handled automatically behind the scenes.

The example app tries to hit the /restricted path using the (now deleted) Access Token. The result looks like this:

fail

The result shows that trying to use a deleted Access Token will not work.

In Summary

The /oauth/token endpoint provided out-of-the-box in Stormpath’s Spring Boot integration enables all the functionality of a modern Token Management system.

In this post, we’ve covered what Access and Refresh tokens are, as well as how they are obtained, used, refreshed and revoked.

You can see the example application used throughout this post at: https://jquery-spa.herokuapp.com or, you can use the button below to deploy the app to your own Heroku account.

Deploy

Feel free to drop a line over to email anytime.

Like what you see? to keep up with the latest releases.

JWT Authentication with AngularJS - Video and Tutorial

$
0
0

Lately I’ve been on the road, giving talks about web application security. JSON Web Tokens (JWTs) are the new hotness, and I’ve been trying to demystify them and explain how they can be used securely. In the latest iteration of this talk, I give some love to Angular and explain how I’ve solved authentication issues in that framework.

However the guidelines in this talk are applicable to any front-end framework.

Following you will find a video recording of this talk, and a textual write-up of the content. I hope you will find it useful!

Status Quo: Session Identifiers

We’re familiar with the traditional way of doing authentication: a user presents a username and password. In return, we create a session ID for them and we store this ID in a cookie. This ID is a pointer to the user in the database.

This seems pretty straightforward, so why are JWTs trying to replace this scheme? Session identifiers have these general limitations:

  • They’re opaque, and contain no meaning themselves. They’re just pointers.

  • As such, they can be database heavy: you have to look up user information and permission information on every request.

  • If the cookies are not property secured, it is easy to steal (hijack) the user’s session.

JWTs can give you some options, regarding the database performance issues, but they are not more secure by default. The major attack vector for session IDs is cookie hijacking. We’re going to spend a lot of time on this issue, because JWTs have the same vulnerability.

Cookies, The Right Way ®

JWTs are not more secure by default. Just like session IDs, you need to store them in the browser. The browser is a hostile environment, but cookies are actually the most secure location — if used properly!

To use cookies securely, you need to do the following:

  • Only transmit cookies over HTTPS/TLS connections. Set the Secure flag on cookies that you send to the browser, so that the browser never sends the cookie over non-secure connections. This is important, because a lot of systems have HTTP redirects in them and they don’t always redirect to the HTTPS version of the URL. This will leak the cookie. Stop this by preventing it at the browser level with the Secure flag.

  • Protect yourself against Cross-Site-Scripting attacks (XSS). A well-crafted XSS attack can hijack the user’s cookies. The easiest way to prevent XSS-based cookie hijacking is to set the HttpOnly flag on the cookies that you send to the browser. This will prevent those cookies from being read by the JavaScript environment, making it impossible for an XSS attack to read the cookie values.

    You should also implement proper content escaping, to prevent all forms of XSS attacks. The following resources can point you in the right direction:

Protect Yourself from Cross-Site-Request-Forgery

Compromised websites can make arbitrary GET requests to your web application, and the browser will send along the cookies for your domain. Your server should not implicitly trust a request, merely because it has session cookies.

You should implement Double Submit Cookies by setting an xsrf-token cookie on login. All AJAX requests from your front-end application should append the value of this cookie as the X-XSRF-Token header. This will trigger the Same- Origin-Policy of the browser, and deny cross-domain request.

As such, your server should reject any request that does not see a match between the supplied X-XSRF-Token header and xsrf-token cookie. The value of the cookie should be a highly random, un-guessable string.

For more reading, please see:

Introducing JSON Web Tokens (JWTs)!

Whoo, new stuff! JWTs are a useful addition to your architecture. As we talk about JWTs, the following terms are useful to define:

  • Authentication is proving who you are.

  • Authorization is being granted access to resources.

  • Tokens are used to persist authentication and get authorization.

  • JWT is a token format.

What’s in a JWT?

In the wild they look like just another ugly string:

1
2
3
4
5
eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIUzI1NiJ9.eyJ
pc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQo
gImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnV
lfQ.dBjftJeZ4CVPmB92K27uhbUJU1p1r_wW1gFWFOEj
Xk

But they do have a three part structure. Each part is a Base64-URL encoded string:

1
2
3
4
5
6
7
8
9
10
eyJ0eXAiOiJKV1QiLA0KICJhb
GciOiJIUzI1NiJ9
.
eyJpc3MiOiJqb2UiLA0KICJle
HAiOjEzMDA4MTkzODAsDQogIm
h0dHA6Ly9leGFtcGxlLmNvbS9
pc19yb290Ijp0cnVlfQ
.
dBjftJeZ4CVPmB92K27uhbUJU
1p1r_wW1gFWFOEjXk

Base64-decode the parts to see the contents:

Header:

1
2
3
4
{
   "typ":"JWT",
   "alg":"HS256"
}

Claims Body:

1
2
3
4
5
6
{
   "iss”:”http://trustyapp.com/”,
   "exp": 1300819380,
   “sub”: ”users/8983462”,
   “scope”: “self api/buy”
}

Cryptographic Signature:

1
tß´—™à%O˜v+nî…SZu¯µ€U…8H×

The Claims Body

The claims body is the best part! It asserts:

  • Who issued the token (iss).

  • When it expires (exp).

  • Who it represents (sub).

  • What they can do (scope).

Issuing JWTs

Who creates JWTs? You do! Actually, your server does. The following happens:

  • User has to present credentials to get a token (password, api keys).

  • Token payload is created, compacted and signed by a private key on your server.

  • The client stores the tokens, and uses them to authenticate requests.

For creating JWTs in Node.js, I have published the nJwt library.

Verifying JWTs

Now that the client has a JWT, it can be used for authentication. When the client needs to access a protected endpoint, it will supply the token. Your server then needs to check the signature and expiration time of the token. Because this doesn’t require any database lookups, you now have stateless authentication… !!! Whoo!… ?

Yes, this saves trips to your database, and this is really exciting from a performance standpoint. But.. what if I want to revoke the token immediately, so that it can’t be used anymore – even before the expiration time? Read on to see how the access and refresh token scheme can help.

JWT + Access Tokens and Refresh Tokens = OAuth2?

Just to be clear: there is not a direct relationship between OAuth2 and JWT. OAuth2 is an authorization framework, that prescribes the need for tokens. It leaves the token format undefined, but most people are using JWT.

Conversely, using JWTs does not require a full-blown OAuth2 implementation.

In other words, like “all great artists”, we’re going to steal a good part from the OAuth2 spec: the access token and refresh token paradigm.

The scheme works like this:

  • On login, the client is given an access token and refresh token.

  • The access token expires before refresh token.

  • New access tokens are obtained with the refresh token.

  • Access tokens are trusted by signature and expiration (stateless).

  • Refresh tokens are checked for revocation (requires database of issued refresh tokens).

In other words: The scheme gives you time-based control over this trade-off: stateless trust vs. database lookup.

Some examples help to clarify the point:

  • Super-Secure Banking Application. If you set the access token expiration to 1 minute, and the refresh token to 30 minutes: the user will be refreshing new access tokens every minute (giving an attacker less than 1 minute to use a hijacked token) and the session will be force terminated after 30 minutes.

  • Not-So-Sensitive Social/Mobile/Toy Application. In this situation you don’t expose any personally identifiable information in your application, and you want to use as few server-side resources as possible. You set the access token expiration to 1 hour (or longer), and refresh token expiration to 4 years (the lifetime of a smart phone, if you’re frugal).

Storing & Transmitting JWTs (in the Browser)

As we’ve seen, JWTs provide some cool features for our server architecture. But the client still needs to store these tokens in a secure location. For the browser, this means we have a struggle ahead of us.

The Trade-Offs and Concerns to Be Aware Of:

  • Local Storage is not secure. It has edge cases with the Same Origin Policy, and it’s vulnerable to XSS attacks.

  • Cookies ARE secure, with HttpOnly, Secure flags, and CSRF prevention.

  • Using the Authorization to transmit the token is fun but not necessary.

  • Cross-domain requests are always hell.

My Recommended Trade-Offs:

  • Store the tokens in cookies with HttpOnly, Secure flags, and CSRF protection. CSRF protection is easy to get right, XSS protection is easy to get wrong.

  • Don’t use theAuthorization header to send the token to the server, as the cookies handle the transmission for you, automatically.

  • Avoid cross-domain architectures if possible, to prevent the headache of implementing CORS responses on your server.

With this proposed cookie-based storage scheme for the tokens, your server authentication flow will look like this:

  • Is there an access token cookie?
    • No? Reject the request.
    • Yes?
      • Was it signed by me, and not expired?
        • Yes? Allow the request.
        • No? Try to get a new access token, using the refresh token.
          • Did that work?
            • Yes? Allow the request, send new access token on response as cookie.
            • No? Reject the request, delete refresh token cookie.

AngularJS Patterns for Authentication

Because we are using cookies to store and transmit out tokens, we can focus on authentication and authorization at a higher level. In this section we’ll cover the main stories you need to implement, and some suggestions of how to do this in an Angular (1.x) way.

How Do I Know If the User Is Logged In?

Because our cookies are hidden from the JavaScript environment, via the HttpOnly flag, we can’t use the existence of that cookie to know if we are logged in or not. We need to make a request of our server, to an endpoint that requires authentication, to know if we are logged in or not.

As such, you should implement an authenticated /me route which will return the user information that your Angular application requires. If they are not logged in, the endpoint should return 401 Unauthorized.

Requesting that endpoint should be the very first thing that your application does. You can then share the result of that operation a few ways:

  • With a Promise. Write an $auth service, and have a method $auth.getUser(). This is just a simple wrapper around the $http call to the /me endpoint. This should return a promise which returns the cached result of requesting the /me endpoint. A 401 response should cause the promise to be rejected.

  • Maintain a user object on root scope. Create a property $rootScope.user, and have your $auth service maintain it like so:

    • null means we are resolving user state by requesting /me.

    • false means we saw a 401, the user is not logged in.

    • {} assign the user object if you got a logged-in response from the /me endpoint.

  • Emit an event. Emit an $authenticated event when the /me endpoint returns a logged in response, and emit the user data with this event.

Which of these options you implement is up to you, but I like to implement all of them. The promise is my favorite, because it allows you to add “login required” configuration to your router states, using the resolve features of ngRoute or uiRouter. For example:

1
2
3
4
5
6
7
8
9
10
11
12
13
angular.module('myapp')
  .config(function($stateProvider) {
      $stateProvider
        .state('home', {
          url: '/',
          templateUrl: 'views/home.html',
          resolve: {
            user: function($auth) {
              return $auth.getUser();
            }
          }
        });
    });

If the user promise is rejected, you can catch the $stateChangeError and redirect the user to the login page.

How Do I Know If the User Can Access a View?

Because we aren’t storing any information in JavaScript-accessible cookies or local storage, we have to rely on the user data that comes back from the /me route. But with promises, this is very easy to achieve. Simply chain a promise off $auth.getUser() and make an assertion about the user data:

1
2
3
4
5
6
7
8
9
10
11
12
13
$stateProvider
  .state('home', {
    url: '/admin',
    templateUrl: 'views/admin-console.html',
    resolve: {
      user: function($auth) {
        return $auth.getUser()
          .then(function(user){
            return user.isAdmin === true;
          })
      }
  }
});

How Do I Know When Access Has Been Revoked?

Again, we don’t know when the cookies expire because we can’t touch them :)

As such, you have to rely on an API request to your server. Using an $http interceptor, if you see a 401 response from any endpoint, other than the /me route, emit a $unauthenticated event. Subscribe to this event, and redirect the user to the login view.

Recap

I hope this information has been useful! Go forth and secure your cookies :) As a quick recap:

  • JWTs help with authentication and authorization architecture.

  • They are NOT a “security” add-on. They don’t give more security be default.

  • They’re more magical than an opaque session ID.

  • Store JWTs securely!

If you’re interested in learning more about JWTs, check out my article on Token-Based Authentication for Single Page Apps and Tom Abbott’s article on how to Use JWT The Right Way for a great overview.

Use Stormpath for Your User Management Needs

Do you like these ideas, but don’t want to roll it all yourself? Stormpath provides you with an instant user database and robust authentication service, complete with integrations for Express.js (express-stormpath), Angular (Stormpath Angular SDK), and React (Stormpath React SDK).

It’s free to get started, and very easy to demo with our Express-Angular Sample project or React Sample Project.

Sign up for a free account now!

Happy Coding!

-r out

Viewing all 278 articles
Browse latest View live