From OpenID Connect in Action by Prabath Siriwardena
In this article, 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.
The flow of events in the implicit authentication flow
Figure 1 shows the sequence of events happens between the OpenID provider, the client application, and the user. The client application in figure 1 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 1.
Figure 1: 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 1, 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. 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 1 is called an authentication request. 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.
Listing 1: Authentication request generated by the client application
https://accounts.google.com/o/oauth2/v2/auth? client_id=424911365001.apps.googleusercontent.com& redirect_uri=https%3A//app.example.com/redirect_uri& scope=openid email&. #A [email protected]& response_type=id_token token&. #B state=Xd2u73hgj59435& nonce=0394852-3190485-2490358
#A The scope values are separated by a space. However, when you type this on the browser, the browser will URL encode the space, so the space will be replaced by %20.
#B The response_type values are separated by a space. However, when you type this on the browser, the browser will URL encode the space, so the space will be replaced by %20.
Let’s go through the query parameters added to the authentication request by the client application, as shown in listing 1. The definition of these parameters are consistent across all three authentication flows the OpenID Connect defines, however, the values may change.
- client_id: This is an identifier the OpenID provider uses to uniquely identify a client application. The client application gets a
client_idafter registering itself at the OpenID provider. For registration at the OpenID provider, either you can follow an out-of-band mechanism provided by the OpenID provider or use OpenID Connect dynamic client registration API. The
client_idis a required parameter in the authentication request, and is originally defined in the OAuth 2.0 specification.
- redirect_uri: This is an endpoint belongs to the client application. After successfully authenticating the user and getting the consent from the user to share the requested data with the client application, the OpenID provider redirects the user to the
redirect_uriendpoint along with the requested tokens (step 5 of figure 1). During the client registration process at the OpenID provider, you need to share the exact URI you use for
redirect_uriparameter in the authentication request, with the OpenID provider.
The OpenID provider will do one-to-one matching of the value of the
redirect_uri in the authentication request against the one already registered by the client application. Most OpenID providers do an exact match between these two URIs. However, some OpenID providers let the client applications register multiple URI and some let the client applications define a regular expression for the validation of the
Doing a validation against a regular expression gives more flexibility to dynamically change the redirection path by the client application, but should use consciously and regular expression used for validation must be thoroughly tested.
redirect_uri is a required parameter in the authentication request, and is originally defined in the OAuth 2.0 specification. However, in the OAuth 2.0 specification the
redirect_uri is not a required parameter for both the implicit and authorization code grant types.
scope: The value of
scope parameter is just a string, where both the client application and the OpenID provider should be able to interpret the meaning of it. Any OpenID Connect authentication request must carry the value openid for the
scope parameter. You can have multiple values for the
scope parameter, each separated by space, but one of them must be
The OpenID Connect specification defines four scope values (profile, email, address and phone) in addition to the
openid scope. A client application can use any of these scope values to request claims from the OpenID provider.
scope is a required parameter in the authentication request, and is originally defined in the OAuth 2.0 specification. However, in the OAuth 2.0 specification the
scope is not a required parameter for both the implicit and authorization code grant types.
- login_hint: The value of
login_hintparameter is a string that carries some hint with respect to the user (or the application), which can be used by the OpenID provider to build a better user experience. For example, if the application already knows the user’s email address (probably from a cookie stored under the domain of the client application), then that can go as the value of the
login_hintparameter and the OpenID provider can directly request the user to share the credentials, rather asking for an user identifier.
login_hintis an optional parameter introduced by the OpenID Connect specification, which you do not find in the OAuth 2.0 specification.
- response_type: The value of the
response_typeparameter in the authentication request defines which tokens the authorization endpoint of the OpenID provider should return back to the client application.
- In the implicit flow there are two possible values: id_token or id_token token. If the value of the
id_token, then the authorization endpoint will only return back an ID token, and if the
id_token token, then the authorization endpoint will return back an ID token and an access token.
response_type is a required parameter in the authentication request, and is originally defined in the OAuth 2.0 specification.
- response_mode: The value of the
response_modeparameter in the authentication request defines how the client application expects the response from the OpenID provider. This is an optional parameter and is not in the listing 1. If you set the value of the
response_modeparameter to query, for example, then all the parameters in the response (from the OpenID provider) are encoded as a query string added to the
redirect_urias shown below.
If you set the value of the
response_mode parameter to fragment, then all the response parameters are added to the
redirect_uri as a URI fragment as shown below.
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.
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
id_token token (implicit flow) for example, then the corresponding default
response_mode is fragment (table 1). That means, when you use implicit grant flow, the OpenID provider sends back the response parameters as an URI fragment.
Table 1: The default response_mode values for the corresponding response_type
The of response_type parameter
The default value of response_mode
id_token token (implicit flow)
Id_token (implicit flow)
code (authorization code flow, section 3.9)
token (OAuth 2.0 implicit grant type)
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).
Figure 2: The client application uses implicit authentication flow to communicate with the OpenID provider to authenticate the user. This is duplicating the figure 1 for readability purpose.
- state: The value of
stateparameter 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 2.
stateis an optional, however, a recommended parameter in the authentication request, and is originally defined in the OAuth 2.0 specification.
- nonce: The value of
nonceparameter carries a unique value added to the OpenID Connect authentication request by the client application. The OpenID provider must include the value of
noncefrom the authentication request to the ID token it builds.
nonce is an optional parameter introduced by the OpenID Connect specification to mitigate replay attacks.
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.
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 2); and also will get user’s consent to share the requested claims with the client application. In step 3 of figure 2 user types the login credentials and in step 4 in figure 2, 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 shows a sample login page, Google OpenID provider pops up during the login flow.
Figure 3: A sample login screen for user authentication from the Google OpenID provider.
The OpenID provider returns back the requested tokens to the client application
In step 5 of figure 4, the OpenID provider returns back the requested tokens to the client application. If the client application, for example, requested only an ID token in step 1, by having
id_token as the value of the
response_type parameter in the authentication request, then the OpenID provider only returns back an ID token as shown below.
If the value of the
response_type parameter was
id_token token, then the OpenID provider will return back both the ID token and the access token as shown below.
In both the above cases the OpenID provider returns the tokens as an URI fragment. That’s because, if you do not explicitly mention the
response_mode parameter in the authentication request, for the implicit flow the default value of the
response_mode is fragment.
Figure 4: In step 5 the OpenID provider returns back the requested tokens to the client application.
Let’s go through the parameters in the URI fragments added to the authentication response by the OpenID provider (step-5 in figure 4). The definition of these parameters are consistent across all three authentication flows the OpenID Connect defines, however, the values may change.
- access_token: The value of the
access_tokenparameter carries the OAuth 2.0 access token. The OpenID provider adds an
access_tokento the response only if the
id_token token, under the implicit flow. A client application can use this access token to securely access OpenID provider’s userinfo endpoint to retrieve claims with respect to the logged in user or access a business API. In case the client application does not need to access any OAuth 2.0 secured APIs, it should use just
response_type. So, there won’t be any
access_tokenin the authentication response.
What you do with an
access_token is defined by the
scope. If you had
scope parameter in the authentication request, for example, then you can use the corresponding
access_token to access the OpenID provider’s userinfo endpoint to retrieve logged in user’s
email_verified claims. If you had
address for the
scope, then you can retrieve the
address claim of the logged in user from the userinfo endpoint.
The OpenID provider (or the authorization server under the OAuth 2.0 terminology) does not necessarily need to respect the scope value in the authentication request all the time. Based on the consent provided by the user and other policies, the OpenID provider can decide which scope out of all the scopes in the authentication request it wants to respect. So, a client application should not expect all the time to get an access token, which is bound to the quested scope values.
If the scope of the access token in the response is different from the requested scope, the OpenID provider must include the corresponding scope value in the response, otherwise the client application can safely assume the token is issued for the requested scope values.
- id_token: The value of the
id_tokenparameter carries the OpenID Connect ID token, which is a JWT. This is a required parameter.
- token_type: The value of the
token_typeparameter carries the type of the OAuth 2.0 access token. This is a required parameter.
- expires_in: The value of the
expires_inparameter carries the validity of the OAuth 2.0 access token in seconds calculated from the time it is issued. This is an optional, but a recommended parameter.
- state: The value of the
stateparameter copies the value of the
stateparameter from the authentication request. The value of the
stateparameter in response must be exactly the same found in the request. This is a required parameter only if the authentication request carries a
- scope: If the scope of the access token in the response is different from the requested scope, the OpenID provider must include the corresponding scope value in the response, otherwise the client application can safely assume the token is issued for the requested scope values.
One important thing you might have already noticed in the authentication response from the OpenID provider is, there is no
refresh_token is defined in the OAuth 2.0 specification and is used by the client applications to refresh (extend the token expiration) the
access_token and the
id_token. However, the implicit flow in OpenID Connect does not return back an
If you don’t have a
refresh_token, the client application won’t be able to renew the
access_token (or the ID token) it got from the OpenID provider, and in that case the client application has to initiate a new authentication request to get a new
access_token and a ID token. This is one of the reasons people prefer to use the authorization code flow over implicit flow. We discuss authorization code flow in detail in part 2.
Figure 5: The client application uses implicit authentication flow to communicate with the OpenID provider to authenticate the user.
access_token and the
id_token from the URL fragment. In practice, what happens is, the OpenID provider does an HTTP redirect (with 302 status code) to the
That’s all for this article. Stay tuned for part 2, where we will delve into authorization code flow.
If you want to learn more about the book, check it out on our browser-based liveBook platform here.
 An out-of-band mechanism could be a developer registering a client application using the UI provided by the OpenID provider.