SPA developers: Migrate to auth code flow with PKCE

Emily Lauber

We recommend all single-page applications (SPA) be migrated from the implicit flow to the authorization code flow with Proof Key for Code Exchange (PKCE). The auth code flow with PKCE improves the resiliency, security, and user experience of SPAs. The improvement in user experience is especially helpful when the user is on a browser that blocks third-party cookies by default.

Auth code flow with PKCE has been our recommended approach to handle the authentication experience since Safari enabled Intelligent Tracking Protection by default for users. With Chrome announcing similar third-party cookie blocking as the default behavior in 2024, we are reiterating to SPA developers the recommendation to migrate away from the implicit flow and onto the auth code flow with PKCE.

Why migrate to the auth code flow?

A key benefit introduced in the auth code flow is the Refresh Token (RT). Refresh tokens are used to renew Access Tokens (AT), which are the tokens used for authentication. Refresh tokens have a lifetime of 24 hours compared to the 1 hour lifetime of access tokens. To read more about tokens and their lifetimes, check out the tokens and claims overview.

When a SPA is run in a browser that blocks third-party cookies, silent Single Sign-On (SSO) calls fail since the hidden iframe used to silently acquire new tokens cannot access the session cookies as the cookies are considered third-party cookies to the SPA. The implicit flow requires this hidden iframe every hour when the AT expires whereas the auth code flow with PKCE uses the hidden iframe every 24 hours when the RT expires. Instead of a hidden iframe, the app will need to use an interactive method for login that puts the login server in the top-level domain and can then appropriately access the login session to renew the token. The interactive method can be either the redirect or popup method. For embedded app scenarios, popups are required as Microsoft Entra ID will not render the login page in an iframe to prevent clickjacking attacks.

When an interactive method is called while the user still has an active session, then the popup or redirect could auto-complete with no user clicks required. More details on how to set this up at prompt behavior with MSAL.js The end user would see the app reload with redirects or a popup screen flash and then the SPA would be authenticated again. The exceptions to this are if there are conditional access policies or consent prompts that interrupt the session and require active user engagement. App developers will see a higher rate of interaction_required errors during silent calls when third-party cookies are blocked, but this error means the app will have to interact with a popup or redirect, not necessarily that every end user will interact by clicking. The recommendation is to always have an interactive fallback method if failures during silent token acquisition occur.

How to migrate to the auth code flow

To migrate from the implicit flow to the auth code flow on the Microsoft identity platform, you need to change 3 things on your apps:

  1. Switch your app registration redirect URI(s) from web platform to single-page application platform.
  2. Update your code to the latest MSAL.js v3 (see migration guides below)
  3. Disable the implicit grant in your app registration when all applications sharing the registration have been updated to the auth code flow.

As part ADAL’s end of life in June 2023, many apps have already been migrated from ADAL to MSAL. Although MSAL.js v1 still supports the implicit flow, we recommend migrating off v1 to a later version that supports the auth code flow.

MSAL.js migration guides:

All the latest versions of the wrapper libraries for MSAL.js (Angular, React, and Node) support the auth code flow with PKCE.

As part of this migration, we also recommend not using a Content Delivery Network (CDN) for hosting MSAL. We recommend hosting the MSAL library with the application URLs. The MSAL libraries are updated regularly and app developers should plan to update to the latest versions of the library as they are released. We have found CDNs reduce the likelihood of an app developer updating their MSAL version so we have removed support for CDNs in MSAL.js v3.


Discussion is closed.

Feedback usabilla icon