Skip to content

Instantly share code, notes, and snippets.

@lhazlewood
Created September 8, 2012 01:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save lhazlewood/3671256 to your computer and use it in GitHub Desktop.
Save lhazlewood/3671256 to your computer and use it in GitHub Desktop.
Stormpath Heroku Documentation

Table of Contents

What is Stormpath?

Stormpath is a cloud Identity Management service that automates user management and security for your applications. The Stormpath Heroku add-on allows you to use Stormpath easily in a Heroku application.

Adding Stormpath to an application automates authentication, access control, and common security workflows like Password Reset and Account Email Verification.

Stormpath secures your users' credentials with military-grade encryption and security best-practices so that you never have to worry about managing passwords again. If you have existing identity systems, we have you covered there too - Stormpath integrates with LDAP and Active Directory, even if they're behind a corporate firewall. Additionally, Stormpath is a highly available clustered service that can easily handle millions of user accounts.

Stormpath is accessible via a web UI or REST/JSON API with supported API client libraries for Java and Ruby.

Installing the Stormpath Heroku Add-On

You can add Stormpath to a Heroku application via the CLI:

A list of all plans available can be found here.
:::term
$ heroku addons:add stormpath
-----> Adding stormpath to sharp-mountain-4005... done, v18 (free)

Once Stormpath has been added, a STORMPATH_URL setting will be available in the app configuration and will contain the canonical URL used to access Stormpath for your application. This can be confirmed using the heroku config:get command.

:::term
$ heroku config:get STORMPATH_URL
https://apiKeyId:apiKeySecret@api.stormpath.com/v1/applications/application_id

After provisioning Stormpath the application should be configured to fully integrate with the add-on.

Local Workstation Setup

After provisioning the Stormpath add-on it’s necessary to locally replicate the config vars so your development environment can operate against the service.

Though less portable it’s also possible to set local environment variables using `export STORMPATH_URL=value`.

Use Foreman to reliably configure and run the process formation specified in your app’s Procfile. Foreman reads configuration variables from an .env file. Use the following command to add the STORMPATH_URL values retrieved from heroku config to .env.

$ heroku config -s | grep STORMPATH_URL >> .env
$ more .env

Credentials and other sensitive configuration values should not be committed to source-control. In Git exclude the .env file with: `echo .env >> .gitignore`.

Use with Java

Stormpath has created an excellent Stormpath Java SDK

Begin by adding the Stormpath Java SDK library .jars as dependencies in your pom.xml file:

<dependency>
    <groupId>com.stormpath.sdk</groupId>
    <artifactId>stormpath-sdk-api</artifactId>
    <version>0.5.0</version>
</dependency>
<dependency>
    <groupId>com.stormpath.sdk</groupId>
    <artifactId>stormpath-sdk-httpclient</artifactId>
    <version>0.5.0</version>
    <scope>runtime</scope>
</dependency>

Connect Your Application

When you add Stormpath to your Heroku application, Stormpath creates a record of the application so it can secure users for it. You need to access that Application record to perform further actions:

import com.stormpath.sdk.application.Application;
import com.stormpath.sdk.client.ClientApplicationBuilder;

...

String url = System.getenv("STORMPATH_URL");
ClientApplication clientApp = new ClientApplicationBuilder().setApplicationHref(url).build();
    
Client client = clientApp.getClient();
Application application = client.getApplication();

The Client and Application instances are thread-safe and should be shared across your code where needed. Avoid calling ClientApplicationBuilder … build() multiple times.

You will work mostly with the Application instance, but sometimes you'll need to the Client instance for general-purpose work, like instantiating new objects and other 'meta' tasks.

Now that you have a reference for your Application, you can easily authenticate users, reset passwords, and more. See the sections below for examples.

Register a new User Account

When you want to create a new user for your application, you'll to create an Account resource in Stormpath. Create the new Account instance and then set (at a minimum) an email, first name and last name. For example, you might have a web-based registration form that an end-user visits and populates:

//create a new Account instance:
Account account = client.getDataStore().instantiate(Account.class);

account.setGivenName(request.getParameter("givenName")); //aka 'First' name in western countries
account.setSurname(request.getParameter("surname")); //aka 'Last' name in western countries
account.setEmail(request.getParameter("email"));

//this isn't strictly necessary - if unset, the username will default to the email address:
account.setUsername(request.getParameter("username"));

Next we need to we need to save the Account to a Directory that will 'own' the account. You can access the Stormpath UI and find the REST URL for the Directory that will contain the new Account as shown here. For example:

String directoryHref = "https://api.stormpath.com/v1/directories/YOUR_DIRECTORY_ID_HERE";
Directory targetDirectory = client.getDataStore().getResource(directoryHref, Directory.class);

//now add the new Account to the Directory:
targetDirectory.createAccount(account);

The Account will be added to the Directory and the account's status will be set to either ENABLED, DISABLED based on the Directory's account registration and verification workflow settings. This workflow configuration allows you to automatically verify the account email address is valid as well as send a follow-up welcome email.

You can also explicitly control if the registration/verification workflow is triggered, overriding the directory default behavior by using the createAccount(account, boolean) method instead. (A false argument will make the Account enabled immediately):

boolean workflowEnabled = //true or false if you want to explicitly override the Directory default.
targetDirectory.createAccount(account, workflowEnabled);

Finally, it is very important to store the newly created Account's HREF in your application's data model so you can look up the account later. You can think of Stormpath HREFs as IDs. For example:

String href = account.getHref();

User myUser = new User(username, email, firstName, lastName);
myUser.setStormpathHref(href);
userDao.create(myUser)

Authenticate a User Account

When your user tries to login to your application, you forward that attempt to Stormpath:

//get the user account's submitted username and password however you need to 
//BUT ONLY OVER SSL/TLS!  Keep your logins secure!  We'll use request parameters in this example:

String username = request.getParameter("username");
String rawPassword = request.getParameter("password");

AuthenticationRequest request = new UsernamePasswordRequest(username, rawPassword);
Account authenticatedAccount = application.authenticateAccount(request);

If the authentication attempt was successful, you can access the account's information via the returned authenticatedAccount instance.

Failed Authentication Attempts

If the authentication attempt fails, you can catch the SDK ResourceException and show a generic error message. A big security tip is to NOT expose any information to the end-user - you don't want to give any potential attacker more information than necessary. For example:

try {
    authenticatedAccount = application.authenticateAccount(request);
} catch (ResourceException re) {
    //show user a fresh login screen with a simple "Invalid username or password." message and nothing more.
}

Get a User Account

If you need to lookup an Account, you can access it using the Account's HREF property that you store in your application's data model after account registration. You do this by using your Client DataStore:

String accountHref = myUser.getStormpathHref();
Account account = client.getDataStore().getResource(accountHref, Account.class);

Update a User Account

If you need to change properties on the Account (e.g. surname, email, etc), just set the values and call save():

account.setGivenName("Joe");
account.save();

Use with Ruby

Stormpath has created an excellent Ruby Stormpath SDK

Ruby applications will need to add the following entry into their Gemfile specifying the Stormpath client library.

:::ruby
gem 'stormpath-sdk'

Update application dependencies with bundler. Specify the latest version available.

:::term
$ bundle install
Installing stormpath-sdk (X.Y.Z)

Connect Your Application

When you add Stormpath to your Heroku application, Stormpath creates a record of the application so it can secure users for it. You need to access that Application record to perform further actions:

require "stormpath-sdk"
include Stormpath::Client

...

app_href = ENV['STORMPATH_URL']

client_app = ClientApplicationBuilder.new.set_application_href(app_href).build

client = client_app.client
application = client_app.application

The Client and Application instances should be shared across your code where needed. Avoid calling ClientApplicationBuilder … build multiple times.

You will work mostly with the application instance, but sometimes you'll need to the client instance for general-purpose work, like instantiating new objects and other 'meta' tasks.

Now that you have a reference for your Application, you can easily authenticate users, reset passwords, and more. See the sections below for examples.

Register a new User Account

When you want to create a new user for your application, you'll to create an Account resource in Stormpath. Create the new Account instance and then set (at a minimum) an email, first name and last name. For example, you might have a web-based registration form that an end-user visits and populates:

account = data_store.instantiate Account
account.set_given_name 'Given Name' # aka 'First' name in western countries
account.set_surname 'Surname' # aka 'Last' name in western countries
account.set_email 'email@somewhere.com'

# this isn't strictly necessary - if unset, the username will default to the email address:
account.set_username 'Username'

Next we need to we need to save the Account to a Directory that will 'own' the account. You can access the Stormpath UI and find the REST URL for the Directory that will contain the new Account as shown here. For example:

href = 'https://api.stormpath.com/v1/directories/YOUR_DIRECTORY_ID_HERE'
directory = client.data_store.get_resource href, Directory

# now add the new Account to the Directory:
directory.create_account account

The Account will be added to the Directory and the account's status will be set to either ENABLED, DISABLED based on the Directory's account registration and verification workflow settings. This workflow configuration allows you to automatically verify the account email address is valid as well as send a follow-up welcome email.

You can also explicitly control if the registration/verification workflow is triggered, overriding the directory default behavior by using the create_account(account, aBoolean) method instead. (A false argument will make the Account enabled immediately):

workflow_enabled = # true or false if you want to explicitly override the Directory default.
directory.create_account account, workflow_enabled

Finally, it is very important to store the newly created Account's HREF in your application's data model so you can look up the account later. You can think of Stormpath HREFs as IDs. For example:

my_user = User.new username, email, firstName, lastName
my_user.stormpath_href = application.href
my_user.save

Authenticate a User Account

When your user tries to login to your application, you forward that attempt to Stormpath:

# get the user account's submitted username and password however you need to 
# BUT ONLY OVER SSL/TLS!  Keep your logins secure!

# when the account is authenticated, it produces an AuthenticationResult instance
request = UsernamePasswordRequest.new 'aUsername' 'aRawPassword'
auth_result = application.authenticate_account request

# from the AuthenticationResult instance we obtain the Account we just authenticated
account = auth_result.get_account 

If the authentication attempt was successful, you can access the account's information via the returned account instance.

Failed Authentication Attempts

If the authentication attempt fails, you can rescue the SDK ResourceError and show a generic error message. A big security tip is to NOT expose any information to the end-user - you don't want to give any potential attacker more information than necessary. For example:

begin
    account = application.authenticate_account request
rescue ResourceError
    # show user a fresh login screen with a simple "Invalid username or password." message and nothing more.
end

Get a User Account

If you need to lookup an Account, you can access it using the Account's HREF property that you store in your application's data model after account registration. You do this by using your Client data_store:

account_href = my_user.stormpath_href
account = client.data_store.get_resource account_href, Account

Update a User Account

If you need to change properties on the Account (e.g. surname, email, etc), just set the values and call save():

account.set_given_name 'Joe'
account.save

Dashboard

For more information on the features available within the Stormpath dashboard please see the docs at stormpath.com/docs.

The Stormpath dashboard allows you to manage your user accounts, groups, and roles as well as configure security workflows.

Stormpath Dashboard

The dashboard can be accessed via the CLI:

:::term
$ heroku addons:open stormpath
Opening stormpath for sharp-mountain-4005…

or by visiting the Heroku apps web interface and selecting the application in question. Select Stormpath from the Add-ons menu.

Stormpath Add-ons Dropdown

Migrating between plans

Application owners should carefully manage the migration timing to ensure proper application function during the migration process.

Use the heroku addons:upgrade command to migrate to a new plan.

:::term
$ heroku addons:upgrade stormpath:newplan
-----> Upgrading stormpath:newplan to sharp-mountain-4005... done, v18 ($49/mo)
       Your plan has been updated to: stormpath:newplan

Removing the add-on

Stormpath can be removed via the CLI.

This will destroy all associated data and cannot be undone!
:::term
$ heroku addons:remove stormpath
-----> Removing stormpath from sharp-mountain-4005... done, v20 (free)

Support

All Stormpath support and runtime issues should be submitted via on of the Heroku Support channels. Any non-support related issues or product feedback is welcome at feedback@stormpath.com or via Twitter @goStormpath.

Additional resources

Additional resources are available at:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment