TL;DR
- The ability to maintain seamless experiences for end-users in Single Page Applications (SPAs) is often business-critical and can have an enormous impact on revenue.
- New browser privacy controls adversely impact the user experience in SPAs by preventing access to third-party cookies, which are used for silent authentication.
- Auth0 now offers an alternative--Refresh Token Rotation--that provides a secure method for using refresh tokens in SPAs while providing end-users with seamless access to resources without the disruption in UX caused by browser privacy technology like ITP.
The Business Imperative
Maintaining an uninterrupted user experience without the need to continually log in is critical for continued engagement, conversion rates, and sustained revenue. If an end-user returns to your site and they are automatically authenticated, they are much more likely to make purchases because they can be shown relevant promotions, see items they may have left in their cart, and have one less barrier on the way to a successful checkout. According to a 2018 report from Accenture, 91% of consumers are more likely to shop with brands who recognize, remember, and provide relevant offers and recommendations.
This is especially important on mobile websites and in mobile applications, where having to re-enter credentials can be a nuisance and result in abandoned carts or users opting to access the content later (when they have time to remember/enter their credentials) rather than being able to do so at the moment. Anyone who’s made an impulse purchase on their phone after seeing something cool or remembering at the last minute that a loved one’s birthday is next week can attest to how nice it is to not have to provide username and password credentials in the throws of inspiration (or panic).
OAuth2 and Securing SPA Access to APIs
Single Page Applications (SPAs) are everywhere, driven by the business needs for richer user experiences and exposed APIs for use by other services. Unfortunately, providing secure authentication in SPAs has a number of challenges based on your application’s use case.
The former guidance of using the Implicit Grant to provide access tokens (ATs) to SPAs is fairly straightforward but carries with it several security risks that each require explicit mitigations you must account for. If you want a more detailed exposition on the challenges of using the Implicit Flow in SPAs, please read this excellent treatise by the incomparable Vittorio Bertocci.
Auth0’s guidance to date is to use the Authorization Code Flow with Proof Key for Code Exchange (PKCE) in SPAs. This is a much more secure solution than the Implicit Flow, and when used in conjunction with silent authentication, it ensures that SPAs can silently renew access tokens without interrupting the user experience.
This technique uses a hidden iframe to request a code from Auth0, leveraging the Auth0 session cookie to prove the user is authenticated, subsequently enabling the SPA to then exchange that code for a new AT without prompting the end-user.
However, recent browser enhancements threaten the uninterrupted user experience businesses rely on. Browsers are building more capabilities to safeguard user privacy, including Safari blocking access to all third-party cookies and Chrome’s commitment to do so within two years.
Beyond the marketing and tracking implications of these changes, which many people applaud, there are unfortunate impacts on how SPAs leverage OAuth to access resources. These advancements, unfortunately, mean that the technique of preserving an uninterrupted user experience via Code Flow with PKCE in conjunction with silent authentication are no longer feasible because the hidden iframe can no longer access the Auth0 session cookie.
What About Refresh Tokens?
Beyond silent authentication, another technique for getting new access tokens is to use Refresh Tokens (RTs), which are typically long-lived and are used to request new ATs after the shorter-lived ATs expire. Refresh Tokens are an elegant solution that is often used in native applications on mobile devices in conjunction with short-lived ATs to provide seamless UX without having to issue long-lived ATs.
(Like our fancy icons? Learn more about Auth0’s free Identicons!)
This is why you can access streaming video services on your smart TV without signing in after you complete the initial Device Authorization; RTs are getting new ATs for you all the time.
Unfortunately, long-lived RTs are not suitable for SPAs because there is no persistent storage mechanism in a browser that can assure access by the intended application only. As there are vulnerabilities that can be exploited to obtain these high-value artifacts and grant malicious actors access to protected resources, using refresh tokens in SPAs has been strongly discouraged.
So... Privacy technology is impeding the Code Flow with PKCE & silent authentication. Refresh tokens can’t securely be persisted in browsers for long periods of time. What can we do?
Introducing Refresh Token Rotation
As previously mentioned, using RTs in SPAs was considered insecure because they typically have long lifetimes (hence, their use in retrieving new short-lived ATs) and browser storage is susceptible to token theft. However, there are acceptable mitigations outlined in the most recent OAuth2 BCP for browser-based applications stipulating that refresh tokens may be used provided that they adhere to specific recommendations, including having a maximum lifetime and requiring rotation to protect against malicious re-use.
"The best practices doc states that another acceptable mechanism for protecting refresh tokens for use in public clients (not just browsers) is refresh token rotation, a feature that invalidates a refresh token and issues a new one whenever it is used to refresh an access token. Security-wise, that's a great feature."
Reference: https://auth0.com/blog/oauth2-implicit-grant-and-spa/
Auth0 is proud to announce that as of today, Refresh Token Rotation with Reuse Detection is available for all customers. With Refresh Token Rotation enabled, every time a client exchanges an RT to get a new AT, a new RT is also returned and the preceding RT is invalidated. This means you don’t need to worry about having a long-lived RT that, if compromised, could provide illegitimate access to resources. As RTs are continually exchanged and invalidated, the threat surface area is greatly reduced.
Auth0 makes it easy to get started with Refresh Token Rotation. You can enable it via API call or using the Auth0 Dashboard with just a few clicks.
RTR is supported for any application using the following flows:
- OAuth2 Authorization Code Flow
- OAuth2 Authorization Code Flow with Proof Key for Code Exchange (PKCE)
- OAuth2 Device Authorization Grant (Device Flow)
- Resource Owner Password Grant (ROPG)
The following diagram illustrates how Refresh Token Rotation is used in conjunction with the Authorization Code Flow with PKCE, but the general principle of getting a new refresh token with each exchange applies to all supported flows.
Automatic Reuse Detection
When a client needs a new AT, it sends the RT with the request to Auth0 to get a new RT/AT pair. As soon as the new RT/AT pair is issued by Auth0, the RT used in the request is invalidated. This helps safeguard your application from replay attacks resulting from compromised RTs.
Without enforcing sender-constraint using techniques like mTLS or Proof of Possession that require the client to prove it is the same one originally authorized, which are not yet widely adopted, it’s impossible for the Authorization Server (AS) to know which actor is legitimate or malicious in the event of a replay attack. Therefore, it’s important that when a previously-used RT (already invalidated) is sent to the AS that the most recently issued RT is immediately invalidated as well, preventing any RTs in the same token family--all RTs descending from the original RT issued for the client--from being used to get new ATs.
Let’s consider the following scenario:
- Legitimate Client has RT1, and RT1 is leaked to or stolen by Malicious Client.
- Legitimate Client uses RT1 to get a new RT/AT pair.
- Auth0 returns RT2/AT2.
- Malicious Client then attempts to use RT1 to get an access token. Auth0 recognizes that RT1 is being reused, and immediately invalidates the RT family, including RT2 because the reappearance of RT1 is indicative of token leakage. It is important that RT2 is also invalidated to prevent any subsequent damage, such as the attacker gaining access to that token.
- Auth0 returns an Access Denied response to Malicious Client.
- AT2 Expires and Legitimate Client attempts to use RT2 to request a new RT/AT pair.
- Auth0 returns an Access Denied response to Legitimate Client. Re-authentication is required.
This protection mechanism works regardless of whether the legitimate client or the malicious client is able to exchange RT1 for a new RT/AT pair before the other. As soon as reuse is detected, all subsequent requests will be denied until the user re-authenticates. And when reuse is detected, Auth0 captures this event in logs to provide visibility for security reviews/audits. This can be especially useful in conjunction with Auth0’s new log streaming capabilities.
This means that you can safely use RTs to mitigate the adverse effects of browser privacy tools and provide continuous access to end-users without disrupting the user experience.
A Little Leeway Sometimes Helps
To ensure that re-use detection doesn’t adversely affect users that suffer intermittent network performance, we’ve also included a configurable reuse interval to account for scenarios where the tokens issued from Auth0 are not received before the client application retries using the original refresh token. This is especially important in cases where users may be on slower cellular connections or congested networks.
For example, a client application has a refresh/access token pair (RT1 & AT1). AT1 is short-lived and expires. The client needs to use RT1 to get a new AT. The client sends RT1 to Auth0, but experiences a network error before getting a response from Auth0, and never receives AT2 or RT2. So the client retries a few seconds later using RT1 again (the only RT it currently has in its possession). Without a sufficient reuse interval configured, Auth0 would recognize the retry as a reuse attempt, invalidate the entire RT family, and require a re-authentication.
By configuring a reuse interval, you can account for known network issues based on your use-cases, such as scenarios where the client is accessed on a mobile device with spotty connectivity. Should you choose to configure a reuse interval, the safest practice is to use the shortest amount of time to afford protection from replay attacks.
SDK Support
The following SDKs are updated to include support for Refresh Token Rotation:
The Auth0 SPA SDK previously did not support refresh tokens of any kind, until today. Now, you can enable the use of rotating RTs and successfully mitigate the effects of browser privacy tools when performing silent authentication.
One additional security feature that has been included is the ability for the SDK to leverage web workers to make requests to the token endpoint and store new RTs. This makes it much harder for malicious actors to retrieve refresh tokens straight out of the in-memory store.
In addition, we now enable the developer to opt-in to storing tokens in either local storage or browser memory, the default being the latter.
You can read more about all of the new features in the SDK documentation.
Let’s Get Started
As of April 15, 2020, Refresh Token Rotation is available for all Auth0 customers. You can read more about Refresh Token Rotation and how to configure it for use in your applications in the Auth0 documentation. We hope that you find this new capability helpful for sustaining user sessions and maintaining engagement in this era of heightened user privacy tools.
Stay healthy. Stay safe. And secure your SPAs!
About Auth0
Auth0 by Okta takes a modern approach to customer identity and enables organizations to provide secure access to any application, for any user. Auth0 is a highly customizable platform that is as simple as development teams want, and as flexible as they need. Safeguarding billions of login transactions each month, Auth0 delivers convenience, privacy, and security so customers can focus on innovation. For more information, visit https://auth0.com.
About the author
Randy Nasson
Director, Product Management (IAM)