Serverless architectures are an easy new way to build scalable backend applications, without the hassle or cost of operating your own servers. With the proliferation of hosted cloud services, whether for compute, file storage, or databases, developers can link essential services together without the need to build a traditional REST API for their mobile and frontend applications. This architecture also allows developers to move logic directly into frontend clients, which can speed up prototyping of new apps and features.

Stormpath helps developers manage and authenticate users for your web applications, and works great with serverless architectures. With authentication from a hosted service like Stormpath, independent services can verify the identity of the end user and properly authorize them to perform various actions, ensuring that the developer has control. With the release of the Stormpath Client API, Stormpath enables frontend and mobile clients to authenticate in a consistent manner. Serverless code can still use the same SDKs developers enjoy with other backend architectures.

In this post, we’ll walk you through an application we built with a serverless architecture, and talk about the design thinking behind it.

Building Stormpath Notes with a Serverless Architecture

To demonstrate what you can do with Stormpath in a serverless environment, we’ve re-built Stormpath Notes, a note-taking app that we built for the iOS and Android launch tutorial. Users can log in, edit, and save their personal notes. Instead of building a REST API to power the backend, we’ve built it in a serverless environment within AWS.

Here’s a demo of the app in action:

stormpath notes demo

Check out our serverless example code on GitHub

We’ve used the following tools to build Stormpath Notes:

Serverless Application Architecture

If we were building this backend the normal way (and we did! Check out this tutorial), we’d build a REST API with endpoints for registration, login, retrieving, and saving your notes.

In a serverless environment, instead of building an register and login endpoint, Stormpath powers the authentication. The Stormpath SDK in our iOS app powers registration and authentication for end users. DynamoDB directly stores user notes, with AWS Identity and Access Management (IAM) to authorize users to read and write to the DynamoDB table.

This allows us to build a cheap and scalable backend that requires no maintenance to run!

DynamoDB Setup

DynamoDB is a NoSQL database; it stores an arbitrary JSON blob against a set of keys. We’ll use those JSON blobs to store the end user’s notes. The Stormpath user account’s href, or its identifier, is the primary key for the table. This ensures that we have a unique entry for each user that we can use to store data.

stormpath notes dynamodb setup

AWS Identity and Access Management Configuration

IAM enables us to build a serverless backend by properly authorizing access to end users. IAM uses the concept of both users and roles to authorize actions. IAM Users represent who is performing an operation, whether an actual end-user, administrator, or automated service. IAM Roles represent a set of permissions assigned to a user, which can be used to perform an action.

stormpath notes iam

A user called stormpath-notes-unauthenticated represents the iOS application making calls to AWS, when not associated with a specific end user. This allows us to authorize access to a subset of our Lambda functions.

Next, the our Lambda function runs under the stormpath-notes-lambda role. This role allows Lambda to issue temporary credentials for end users.

Last, a role called stormpath-notes-authenticated authorizes end user access to our Stormpath Notes DynamoDB table.

Set Up Lambda to Generate Temporary Credentials

With IAM set up, we can create a Lambda function to validate Stormpath access tokens, and issue temporary credentials to our end users. While you can see the full code here, here’s a brief overview of how this function works.

We begin by using the Stormpath Node.js SDK to validate the Stormpath access token. After it’s validated, we issue temporary credentials against the stormpath-notes-authenticated role, and further restrict them with an additional IAM policy. The policy statement looks like this:

All IAM policies have three components: action, resource, and condition. In this policy, we restrict the credentials to dynamodb:GetItem and dynamodb:UpdateItem, which do what they sound like they do. We apply this policy against the arn:aws:dynamodb:us-east-1:569073598720:table/stormpath-notes table that we created in DynamoDB. Then, we add an additional condition, which is that the dynamodb:LeadingKeys has to ForAllValues:StringEquals the user account’s href, or its unique identifier.

Last, we need to pick a role for this Lambda function. Lambda, when spinning up our function, automatically sets up credentials with a specific IAM role. This is the stormpath-notes-lambda role we discussed earlier.

Note: Stormpath is building in support for OpenID Connect, which will make the token exchange process discussed here even easier. Once that feature is available, we would be able to set up Stormpath as an OpenID Connect identity provider in IAM, eliminating the need for this Lambda endpoint

Configure IAM Policies to Authorize Access to AWS Resources

With all of the resources created and defined, here’s how we have the trust relationships set up between all of the IAM roles.

For the stormpath-notes-unauthenticated users, we give them access to our Lambda function with this AWS policy:

Then, the stormpath-notes-authenticated role allows it to access our DynamoDB table, and get / update items.

Last, the stormpath-notes-lambda role allows it to request temporary credentials for the stormpath-notes-authenticated role:

iOS App

The app is based on the Stormpath Notes demo built in last year’s tutorial. We’re using both the Stormpath SDK, as well as the DynamoDB and Lambda SDKs. Check out the iOS project on GitHub. Try compiling and running it — it should automatically hit the backend we have set up!

To use the Stormpath and AWS SDKs, we’ve used Cocoapods to add the following dependencies:

When looking through the code, you’ll want to pay attention to two key parts of this project:

  • APIClient – class that wraps the Stormpath and AWS SDKs.
  • AppAWSCredentialsProvider – stores the auth tokens for accessing AWS and its current state.

Let’s take a look at how we built the iOS app in more depth.

Providing AWS Credentials to the AWS SDK

The AWS SDK defines the AWSCredentialsProvider protocol, which we implemented to provide the correct credentials to AWS. The implementation is fairly straightforward, with this basic class signature:

By default, unauthenticatedCredentials should be a set of credentials representing the stormpath-notes-unauthenticated role. By creating a set of credentials in IAM, we can set this to:

Note: this might seem a bit insecure because we are embedding a secret key in the app. However, when we created this account in IAM, we limited the scope to a specific Lambda function, stormpath-authorizer. Because it’s limited to a specific function, it’s almost as if we built that lambda function as an unauthenticated API endpoint. This set of API credentials are very limited in scope, and are OK to embed in the app.

Authenticated credentials will be set if we are authenticated by the stormpath-authorizer function. Thus, the credentials() function returns the current set of credentials. This allows the CredentialsProvider to choose between the correct API keys / token for accessing AWS.

In addition, we add an authenticate(accessToken: String) function to this credentials provider. This function takes a Stormpath access token, hits Lambda, and exchanges it for a set of AWS credentials.

Login With Stormpath

Since we’re using Stormpath to handle authentication, a login method in APIClient handles username/password based login.

After calling the Stormpath SDK and getting an access token, we then call the credentials provider’s authenticate method to exchange the Stormpath access token for an AWS access token.

Get Note from DynamoDB

To use the DynamoDB SDK, we need to create a model for how our data in Dynamo looks like. To do so is really simple! A Note class extends from AWSDynamoDBObjectModel and defines the fields we’ll be using:

With an authenticated session, we can get a note from DynamoDB:

And save a note to DynamoDB:

And that’s it! Serverless authentication with Stormpath, plus AWS’s services, allow you to quickly and easily draft up an app with little work.

And if we want to add more? It’s easy. For instance, we could add a file upload feature with Amazon S3. In a similar fashion, we would create a S3 bucket, and add additional permissions to the policy generated by our Lambda function. Then, using the AWS SDK, we would implement file upload in our iOS app, and viola! Uploads! Building an application with a serverless architecture is a fast, fun, and rewarding way to architect the backend of your next application. We suggest you try it out!

What’s next?

Check out the code!read the full code behind this app on GitHub
Try building this as a REST API — Serverless architectures are great, but for higher degrees of maintainability, it’s nice to know how to build your own REST API. Learn how to build this same backend, but with a REST API using Node.js
Learn how to build the app! — We did a brief overview of how to build the API client for this app, and use the Stormpath and AWS SDKs. If you’d like to learn how to build this app (but more in depth), check out this tutorial.
Learn more about Stormpath — Stormpath is free to use, and can help your team write a secure, scalable application without worrying about the nitty gritty details of authentication, authorization, and user security. Sign up for a forever-free developer account today!
Talk with us — We’re proud of the exceptional level of support we provide our community, and would love to hear from you about your project! Please don’t hesitate to contact us at [email protected], file an issue against one of our GitHub projects, or leave a comment below! Or, follow us @EdwardStarcraft and @goStormpath!