How to implement OpenID Connect for single-page applications

The push to shift security left means developers must now consider protecting user and business data through identity and access management when building applications.

One standard developers can use is OpenID Connect, which rests on top of OAuth 2.0. The protocol works with a variety of application types, from popular single-page applications to native web apps and APIs.

To help developers learn how to use OpenID Connect alongside OAuth 2.0, author and identity and access management (IAM) evangelist Prabath Siriwardena wrote OpenID Connect in Action. The book teaches developers how to secure four application types and offers a number of security best practices.

In this excerpt from Chapter 3 of OpenID Connect in Action, Siriwardena explains how to integrate the protocol with single-page applications. Download a PDF of the chapter here, and you can use the code “nltechtarget21” for 35% off the book.

Check out an interview with Siriwardena, where he discusses how to use the book and why OpenID Connect works so well for authentication with different application types.

With the heavy adoption of APIs, over time, single-page applications (SPA) have become one of the most popular options for building client applications on the web. If you are new to single-page application architecture, we recommend you first go through the book SPA Design and Architecture: Understanding Single Page Web Applications by Emmit Scott (Manning Publication, 2015). Also in this chapter we assume you have a good knowledge of OAuth 2.0, which is the fundamental building block of OpenID Connect.

Learn more about
OpenID
Connect in Action here.

Under OAuth 2.0 terminology, a SPA is identified as a public client application. In principle, a public client application is unable to hide any secrets from the users of it. Most of the time a SPA is an application written in JavaScript that runs on the browser; so, anything on the browser is visible to the users of that application. This is a key-deciding factor on how you want to use OpenID Connect to secure a SPA.

In this chapter we’ll teach you what OpenID Connect authentication flows are and how different OpenID Connect authentication flows work with a SPA. You will also learn how to build a SPA using React and then log in to it via OpenID Connect. React is the most popular JavaScript library for developing user interfaces. If you are new to React, please go through appendix A first.

3.1 Authentication flows define the communications between a client application and an OpenID provider

In this section you’ll learn what is an authentication flow in OpenID Connect and different types of authentication flows.

In chapter 1, you learnt that OpenID Connect defines a schema for a token (which is a JSON Web Token (JWT)) to exchange information between an OpenID provider and a client application; and a set of processing rules around it. The OpenID Connect specification identifies this token, as the ID token, which we will briefly discuss in this chapter and in detail in chapter 4.

Diagram of OpenID Connect authentication flow

Figure 3.1: OpenID authentication flows define how the client application communicates with the OpenID provider to authenticate an end user. Some communications happen via the web browser and some happens directly between the client application and the OpenID provider.

In addition to the ID token, OpenID Connect specification also introduces a transport binding, which defines how to transport an ID token from an OpenID provider to a client application (figure 3.1). In OpenID Connect, we use the term authentication flows to define multiple ways by which you can transport an ID token from an OpenID provider to a client application.

OpenID Connect defines three authentication flows:

  • authorization code flow,
  • implicit flow, and
  • hybrid

In section 3.3 you learn how implicit flow works and in section 3.9 how authorization code flow works. We’ll discuss hybrid flow in detail in chapter 6.

3.2 Authentication flows vs. grant types

The OAuth 2.0 core specification (RFC 6749) introduced four grant types, which we discussed in chapter 2 in detail. In this section you’ll learn how an OpenID Connect authentication flow relates to a grant type as well as the differences.

A grant type in OAuth 2.0 defines a protocol how a client application can obtain an access token from an authorization server. Typically, a grant type defines four key components (please see section 2.3 for the details): authorization request, authorization response, access token request and access token response.

An authentication flow in OpenID Connect uses grant types, but an authentication flow is more than a grant type (table 3.1). Typically, an authentication flow in OpenID Connect defines four key components, quite similar to an OAuth 2.0 grant type, but not exactly the same: authentication request, authentication response, token request and token response. You might have already noticed the differences; in a grant type we have an authorization request/response, while in an authentication flow we have an authentication request/response, also in a grant type we have an access token request/response, while in an authentication flow we have a token/request response.

Table of the differences in the terminology, OAuth 2.0 vs. OpenID Connect

The OpenID Connect specification defines the authentication flows in a self-contained manner in itself. So we should not confuse the OAuth 2.0 grant types with OpenID Connect authentication flows. The authorization code flow in OpenID Connect is not as same as the authorization code grant type in OAuth 2.0, and the implicit flow in OpenID Connect is not as same as the implicit grant type in OAuth 2.0.

3.3 How does implicit flow work?

In this section you’ll learn how an OpenID provider transports an ID token to a client application using the implicit flow. The sequence of events or steps happens during this flow, as well as the messages being passed in each step is clearly defined in the OpenID Connect specification.

3.3.1 The flow of events in the implicit authentication flow

Figure 3.2 shows the sequence of events happens between the OpenID provider, the client application, and the user. The client application in figure 3.2 can be any type of an application, but here our discussion mostly focuses on a SPA. Also, the implicit flow is more popular among SPAs than any other application type. In the following sections we discuss in detail what happens in each step in figure 3.2.

Diagram of OpenID Connect implicit authentication flow

Figure 3.2: The client application uses implicit authentication flow to communicate with the OpenID provider to authenticate the user.

THE CLIENT APPLICATION INITIATES A LOGIN REQUEST VIA THE BROWSER

In the step 1 of figure 3.2, the user clicks on the login link and the client application initiates a login request via the browser. In the case of a SPA, we can expect that the user clicks on a login link on the web page of the client application, and browser does an HTTP GET to the authorize endpoint of the OpenID provider.

The authorize endpoint of the OpenID provider is a well-known endpoint and the client applications can find it by going through the OpenID provider documentation or else using OpenID Connect discovery protocol, which we discuss in detail in chapter 12. If you use Google as your OpenID provider, then this is the authorize endpoint of Google, which you can find from their documentation: https://accounts.google.com/o/oauth2/v2/auth.

The request the client application generates in step 1 of figure 3.2 is called an authentication request. You may recall from the chapter 2, in OAuth 2.0 the request initiated from the client application to the OAuth 2.0 authorization server is called an authorization request.

The following listing shows an example of an authentication request. This is in fact a URL constructed by the client application, which takes the user to the authorize endpoint of the OpenID provider, when the user clicks on the login link.

Screenshot of authentication request code

Listing 3.1: Authentication request generated by the client application

Let’s go through the query parameters added to the authentication request by the client application, as shown in listing 3.1. The definition of these parameters are consistent across all three authentication flows the OpenID Connect defines, however, the values may change.

  • In addition to the query and fragment, the OAuth 2.0 Form Post Response Mode (https://openid.net/specs/oauth-v2-form-post-response-mode-1_0.html) specification defines another response_mode called form_post, and we’ll discuss that in chapter 6.
  • The response_type and response_mode are bit related to each other. If you do not specify a response_mode parameter in the authentication request, then the default response_mode associated with the corresponding response_type gets applied automatically. If the response_type is id_token or id_token token (implicit flow) for example, then the corresponding default response_mode is fragment (table 3.2). That means, when you use implicit grant flow, the OpenID provider sends back the response parameters as an URI fragment. query string.

Table of the default response_mode values for the corresponding response_type

The response_mode is an optional parameter in the authentication request, and is originally defined in the OAuth 2.0 Multiple Response Type Encoding Practices specification (https://openid.net/specs/oauth-v2-multiple-response-types-1_0.html), which is developed by the OpenID Foundation (not by the OAuth IETF working group).

Repeated diagram of OpenID Connect authentication flow

Figure 3.3: The client application uses implicit authentication flow to communicate with the OpenID provider to authenticate the user. This is duplicating the figure [3.2] for readability purpose.

  • state: The value of state parameter is just a string, which is added to the authentication request by the client application and the OpenID provider must return back the same value (unchanged) in the response (step-5) in figure 3.3. In section 3.5 we discuss the use cases of the state parameter and also in chapter 13 we discuss how to use the state parameter to mitigate some possible security threats.
  • The state is an optional, however, a recommended parameter in the authentication request, and is originally defined in the OAuth 2.0 specification.
  • nonce: The value of nonce parameter carries a unique value added to the OpenID Connect authentication request by the client application. The OpenID provider must include the value of nonce from the authentication request to the ID token it builds. The section 3.7 explains how to generate a nonce to be unique and nonguessable.
  • The nonce is an optional parameter introduced by the OpenID Connect specification to mitigate replay attacks and in chapter 13 we discuss nonce in detail.

In addition to the authentication request parameters we discussed in the above list, there are few more optional ones: display, prompt, max_age, ui_locales, id_token_hint, and acr_values. We’ll discuss them in detail in chapter 6.

THE OPENID PROVIDER VALIDATES THE AUTHENTICATION REQUEST AND REDIRECTS THE USER BACK TO THE BROWSER FOR AUTHENTICATION

Once the OpenID provider validates the authentication request from the client application, it checks whether the user has a valid login session under the OpenID provider’s domain. Here the domain is the HTTP domain name that you use to access the OpenID provider using a web browser. If the user has logged into the OpenID provider already from the same web browser, then there exists a valid login session, unless its expired.

If the user does not have a valid login session, then the OpenID provider will challenge the user to authenticate (step 2 in figure 3.3); and also will get user’s consent to share the requested claims with the client application. In step 3 of figure 3.3 user types the login credentials and in step 4 in figure 3.3, the browser posts the credentials to the OpenID provider. The steps 2, 3 and 4 are outside the scope of the OpenID Connect specification and up to the OpenID providers to implement in the way they prefer. Figure 3.4 shows a sample login page, Google OpenID provider pops up during the login flow.

Screenshot of Google OpenID login page

Figure 3.4: A sample login screen for user authentication from the Google OpenID provider.

About the author
Prabath Siriwardena is a member of technical staff for identity at DevRev. He is a developer, architect and evangelist with more than 18 years of industry experience designing and building critical IAM infrastructure for global enterprises, including many Fortune 100/500 companies. From 2007 to 2021, he led the development, architecture and strategy of the open source WSO2 Identity Server from zero customers to 750+, zero annual recurring revenue to $12 million-plus, zero users to more than 250 million, and a four-member team to a 100-member team. As an evangelist, Siriwardena has published eight books, including OpenID Connect in Action (Manning), Microservices Security in Action (Manning), Advanced API Security (Apress) and Microservices for the Enterprise (Apress). Three of his books were translated into Korean, and one is being translated into Chinese. He blogs on various topics, including blockchain, Revised Payment Services Directive, GDPR, IAM and microservices security.

Comments are closed.