Assisted Token Flow: The Answer to OAuth Integration in Single Page Applications

OAuth is an incredibly popular internet standard for granting apps and web services access to the information available on other websites. Though the implementation is complex, the premise is simple: you tell a website you want to access its data, you log in with the user’s details, and off you go — but without some kind of protocol the process would be a whole lot more complicated.

There is one drawback in the current core version of OAuth, and it’s increasingly evident with the recent trend towards building single page applications (SPAs). The issue is that designing a seamless, secure OAuth solution is difficult without a backend to do the heavy lifting, and, by definition, single page applications don’t have one…

In this article, we’ll follow along with Curity solutions architect Daniel Lindau, as he presents the solution to OAuth usage in single page applications at our Austin API Summit in Texas, 2018.

Implicit Flow: The Status Quo for OAuth in Single Page Applications

The current method of choice for handling OAuth delegation within single page applications uses the implicit flow — also known as the client-side flow.

It’s simple, just redirect the browser to the authorization server, where the user directly authenticates and gives the app access, before returning to the application with an access token embedded in the URL. Then, the service can parse the URL for the token and immediately start using it.

There’s no doubt that this is a messy approach. Redirects are inherently counter-intuitive if the goal is to build a single page application. What’s more, you need to design an architecture whereby the application can seamlessly resume execution after you’re done with all the redirects. Then, there’s the question of storing your precious access token in a secure way.

Daniel says that Curity typically works with developers who aren’t so familiar with OAuth; they don’t exactly know the best practices for storing and using these tokens. Therefore, it’s important to promote a more failproof alternative.

The iFrame: A Coffin for Your OAuth Delegation

An obvious workaround to all the problems caused by a redirect-powered, implicit flow is to hide away your OAuth implementation inside an iFrame — an inline frame.

Exactly as it sounds, tucking away your OAuth in an iFrame is a bit like putting it in a coffin. The reason is that an iFrame keeps your OAuth flow and the rest of your application separate, which can make it pretty difficult to communicate between the two.

Another problem with using iFrames, which coffins don’t exactly suffer from, is that they can be accessed from multiple places. In the interests of secure authorization, you’ll probably need to design it such that the frame can only be accessed from the active page.

So what’s the solution?

Assisted Token Flow: iFrame Integration Done Right

Curity has built OAuth solutions to their customers’ varying needs and constraints in a range of ways. While each case was slightly different, a common denominator was the usage of iFrames — but with precautions taken to avoid the associated problems.

Creating similar OAuth integrations time and time again gave the team a brilliant idea: why not standardize the process of OAuth delegation within an iFrame?

That’s how Assisted Token Flow was born. It’s a draft specification built onto OAuth — which is to say that it uses everything that is today OAuth — but adds new flows and endpoints to facilitate usage on single page applications.

The protocol uses iFrames for communication between the parent page and OAuth server, which prevents the pesky redirects we commented on earlier, and JavaScript’s postMessage functionality for communication between the frame itself and the parent page.

A much-welcomed addition of new endpoints allowed the developers to remove unnecessary OAuth parameters, streamlining the entire delegation process. This is an important feature, as it makes page-iFrame interactions much easier to follow.

The result is a flow whereby only the client_id parameter needs to be communicated between the iFrame, parent page, and authorization server — any other parameters are optional.

In the event that other parameters are used, the Assisted Token Flow protocol also offers parameter validation within the implementation — on the side of the OAuth server — which cuts down on any excess back-and-forth between the application and authorization server.

Token Grants with Assisted Token Flow

The beauty of using a standard for OAuth integration is that every implementation uses the same workflow — in this case, with a simple but effective design.

Let’s look at how tokens are granted with Assisted Token Flow when the user is already authenticated versus when the user hasn’t yet authenticated.

Assisted Token Flow for an Authenticated User

With Assisted Token Flow, the workflow for an already authenticated user is extremely straightforward:

  1. The application requires access to data at an external resource server.
  2. The page opens a hidden iFrame and points it to the OAuth server with just the client_id parameter.
  3. The OAuth server serves a near-empty HTML page to the iFrame, including a postMessage script with the result of the transaction.
  4. The page is loaded in the iFrame and a postMessage is performed, sending a success message along with the access token to the parent page.

In comparison to core OAuth, the primary advantage here is that Assisted Token Flow doesn’t mandate the inclusion of a scope parameter (or any other parameter beyond client_id, for the matter); if the client specifies scopes, the user grants them. If the client does not specify a scope parameter, the user will be asked to grant all scopes available for the client.

Assisted Token Flow for an Unknown User

Assisted Token flow for a user who hasn’t yet been authenticated is similarly easy, with a few extra steps:

  1. The application requires access to data at an external resource server.
    The page opens a hidden iFrame and points it to the resource server with just the client_id parameter.
  2. The OAuth server sends a more detailed HTML page to the iFrame, including a postMessage script that asks the parent page asking for the login details
  3. The iFrame is made visible for user authentication (e.g. as a username/password dialog) and the user logs in.
  4. The application then retrieves data as necessary per the steps for an authenticated user.

Again, Assisted Token Flow shows the benefit of not needing any extra parameters, while it also shows how simple OAuth integration can be made when the iFrame aspect is taken care of.

Security Precautions in Assisted Token Flow

As we mentioned earlier, there are few security constraints apparent in using OAuth on single page applications. Two of the more major issues are the security of the iFrame itself, as well as the storage of access tokens.

Here’s the precautions that Assisted Token Flow has taken against any such vulnerabilities:

iFrame security

There’s a double-barreled approach to keeping the iFrames safe: for starters, the client is registered at the OAuth server to a particular domain (which is enforced with HTTP headers and content security policies), and, secondly, the domain is specified in the postMessage to prevent external access to the token.

Token storage

As for token storage, there are only really two options: localStorage, as written into JavaScript, or cookie storage. Curity recommends cookie storage, as it allows the access token to be stored with a domain, path, and expiry time — so all interactions with the endpoint will send an access token for the OAuth server to act on.

Conclusion: Assisted Token Flow Makes OAuth Easy on Single Page Applications

Assisted Token Flow makes OAuth easy, especially for those who’ve struggled to find a sleek, but secure way to use it within single page applications.

It takes care of iFrames and token storage, creates a new, lightweight endpoint with just one mandatory parameter, and even validates any parameters for you. Best of all, the majority of this is achieved server side, so the developer doesn’t have to worry about all the basics in their implementation.

The result is an OAuth protocol which is a heck of a lot easier to use, but sacrifices no functionality.

And just how easy is it? Here’s an 8-line JQuery implementation where Curity sets up the origin and client_id, initiates the library, and off we go:

var settings = {
	clientId: "client-assisted-example",
	autoPrepareJqueryAjaxForOrigins: ['https://example.com'],
};

var assistant = curity.token.assistant(settings);

$(document).ready(function () {
	assistant.loginIfRequired();
});