OpenID Connect defines three flows, two of which build upon flows defined in OAuth 2.0. These flows dictate what response types an authorization request can request and how tokens are returned to the client application.
This article describes each flow, when to use it, and how to secure it.
Authorization Code Flow
The authorization code flow allows you to request an authorization code from the authorization endpoint, which you can then exchange at the token endpoint for an identity token and, optionally, an OAuth access token. This flow was initially created for server-side applications.
This flow does not expose any tokens to the front-channel, as only the authorization code is returned in the authorization response.
To ensure only an authorized client application can swap codes for tokens, use client authentication when using a confidential client (a client application that can keep a secret).
To prevent authorization code injection, use Proof-Key for Code Exchange (PKCE).
This flow allows you to continue to act on the user’s behalf, when they are no longer present, by using a refresh token authorized for offline access. Ideally, offline access refresh tokens are only used with confidential clients.
Implicit Flow
The implicit flow allows you to request an identity token and, optionally, an OAuth access token, directly from the authorization endpoint. This flow was initially created for browser-based applications.
This flow exposes tokens to the front-channel. Tokens will always be visible to the browser and, therefore, code running within the browser. However, this can be acceptable when only dealing with identity tokens, assuming you are using nonce validation, and the identity token is not stuffed with PII.
This flow is generally regarded as deprecated in the OAuth community; however, using OpenID Connect nonce and access token hash (at_hash
) validation significantly improves its security profile compared to pure OAuth.
Now that we have CORS and PKCE, I recommend following the OAuth for browser-based apps BCP and avoiding this flow in favor of the authorization code flow with PKCE.
Hybrid Flow
The hybrid flow allows authorization codes and tokens to be returned from the authorization endpoint at the same time. This flow can be useful if the client needs to perform some processing before swapping an authorization code for tokens.
This flow exposes tokens to the front-channel, in the same way as the implicit flow. However, this can be acceptable when only dealing with identity tokens, assuming you are using nonce validation, and the identity token is not stuffed with PII.
Requesting an authorization code and an identity token from the authorization endpoint at the same time can even be advantageous for the client application.
Performing nonce validation early can be beneficial, and checking the code hash (c_hash
) allows the client application to detect authorization code injection.
To have the authorization server also detect authorization code injection, use Proof-Key for Code Exchange (PKCE).
This flow also allows you to continue to act on the user’s behalf, when they are no longer present, by using a refresh token authorized for offline access. Ideally, offline access refresh tokens are only used with confidential clients.
Which Flow Should I Use?
The general advice is to use the authorization code flow with PKCE for all types of applications. This flow requires the least amount of effort for the client application to implement while giving the best level of security. This is the recommendation that is being proposed for OAuth 2.1.
If the client application cannot support PKCE, I recommend falling back to using the hybrid flow response type of “code id_token” with nonce and c_hash
validation.
Flow Features
Authorization Code | Implicit | Hybrid | |
---|---|---|---|
All tokens returned from authorization endpoint | |||
All tokens returned from token endpoint | |||
Tokens sent via user agent | |||
Client can be authenticated (e.g. using client secret) | |||
Can use refresh tokens | |||
Communication in one round trip | |||
Most communication server-to-server |
Response Types by Flow
Flow | Response Types |
---|---|
Authorization Code | code |
Implicit | id_token |
Implicit | id_token token |
Hybrid | code id_token |
Hybrid | code token |
Hybrid | code id_token token |
Tables adapted from OpenID Connect 1.0 Core Specification.
Further Reading
If you want to get started with your own OpenID Connect Provider, check out the open source framework IdentityServer4.
To learn more about OAuth and OpenID Connect best practices, check out some of my other articles: