The Overview
In this episode of Identity. Unlocked, principal architect at Auth0 and podcast host, Vittorio Bertocci, speaks with Aaron Parecki. Aaron is currently senior security architect at Okta, and he has spent much of his career focusing on OAuth. He writes and teaches on the subject and joins Vittorio to discuss the latest project he's been working on: the development of the OAuth 2.1 specification.
OAuth 2.1 is a revision of the OAuth 2 core specification and involves a dramatic reduction in the amount of reading that identity providers and SDK authors need to get up to speed on OAuth. The project aims to consolidate current material on OAuth, offering a guide to best practices and including the most relevant guidance directly in the core specification.
Moving into more of the details of the project, Vittorio first asks what OAuth2.1 adds to the OAuth 2 core. One major addition is the requirement to use PKCE in every authorization grant, including the cases involving confidential clients. Recommendations for browser-based apps are in the works, and the new guide will include some stricter requirements defined in the security best current practices document, such as restrictions around refresh tokens. OAuth 2.1 will also introduce a new term, "credentialed client," defined as a client that has credentials but no confirmed identity. The concept already exists in OAuth 2, OAuth 2.1 simply gives it a name so that it can be treated as a legitimate client type, along with the classic public and confidential. Aaron also explains that OAuth 2.1 omits any mention of implicit flow and password grants, and he and Vittorio finish the conversation with a deep dive on the differences between id tokens and access tokens.
Highlights
[5:59] - Vittorio asks Aaron about OAuth 2.1.
As mentioned during the discussions, OAuth 2.1 (currently in draft 00)consolidates a number of different specifications. Here's the current list:
- OAuth 2.0 Core (RFC6749)
- OAuth 2 Bearer Token Usage (RFC6750)
- Proof Key for Code Exchange by OAuth Public Clients (RFC7636)
- OAuth2 Security BCP (draft 15)
- OAuth2 for Native Apps (RFC8252)
- OAuth2 for Browser-Based Apps BCP (draft 6)
By providing a single document with the best & more relevant sections of all those specifications, developers building identity tools, authorization server products, and SDKs will have a much easier time finding the most up to date guidance on how to implement delegated authorization in their scenarios.
[11:00] - Addressing the main additions to the OAuth 2 core, Aaron first talks about the main new requirement introduced by OAuth2.1: imposing the use of PKCE for every authorization grant, regardless of the client type.
The PKCE requirements is currently introduced in section 4.1.1 of OAuth 2.1 (location likely to change as the spec structure evolves). We don't go in the details of PKCE here, as we'll cover the topic more in-depth in an upcoming episode this season (the one about the OAuth2 security BCP, with Daniel Fett); however, if you are interested in the details of the code injection attack, Aaron mentions, please check out this video.
[14:30] - Besides PKCE, what is being added to the core?
You can find a good backgrounder on refresh token rotation in this post. The podcast episode discussing sender constraint, MTLS and DPoP can be found here.
[20:48] - Vittorio and Aaron turn to credentialed clients, the new term defined in OAuth 2.1.
Credentialed clients are defined in Section 2.1 of the current draft of the OAuth 2.1 specification.
[25:55] - What has been removed from the core?
The arguments for not including in OAuth 2.1 the resource owner password grant (ROPG) are well known; hence there isn't much to add or explain on top of what we say on the podcast.
The implicit discussion is a bit more nuanced. You can find a more in-depth discussion in this post from a while back- but there's no doubt about its omission from OAuth 2.1 being a good move. The detail that is perhaps worth expanding on is how the considerations that led to omitting the implicit flow from OAuth 2.1 don't really impact the use of implicit + form POST to get an id token in OpenID Connect for web sign-on in traditional web apps.
In a nutshell: OAuth 2 introduced the implicit flow as a way of getting access tokens, the only token type it defines, directly from the authorization endpoint- and mostly with single-page apps in mind. As we have seen in the podcast episode on sender constraint, leaking access tokens meant to be used as bearer tokens has serious consequences, as attackers can successfully reuse leaked tokens. If you consider the fact that returning access tokens via implicit flow for single-page apps specifically creates more attack surface for stealing tokens (token bits in referral headers, browser history, etc.), you can see how it's prudent to fall back on more robust methods, such as authorization code with PKCE directly in JavaScript.
None of the above really applies to get id tokens via implicit + form post when implementing web sign-on in OpenID Connect That's for two main reasons, as identified in the podcast discussion:
- The mechanics of returning a token via form post are more robust than the ones using a fragment. Tokens returned via form post don't end up in referral headers or the browser history as query elements do.
- More importantly: OpenID Connect implements measures that make it hard to reuse a leaked id token, for example, by using a nonce.
To better understand the last point, take a look at the following diagram.
When a web app wants to perform a sign in with an OpenID Connect provider, it generates a nonce (random unguessable string), it saves the value of the nonce so that it can be retrieved in the context of the current transaction (for example, by asking the browser to save a cookie containing the nonce value and somehow protected from tampering, for example by signing the cookie with a secret) and it includes the nonce in its sign-in request.
Leg 1 in the diagram shows the step right after all that occurs, with the sign-in request including the nonce reaches the authorization server acting as OpenID Connect provider.
Upon successful authentication, the provider returns an id token that, besides being signed (not shown in the diagram), featuring the canonical claims, etc. etc., also includes a nonce claim carrying the nonce value received during the sign-in request.
In the form post case, the browser reacts as shown in leg 3- by immediately POSTing a form containing the id token to the requesting app, along with the nonce cookie created at request time. Upon receiving the id token, the web app validates it as established by the OpenID Connect spec, and, as part of its validation checks, it verifies that the nonce claim value corresponds to the nonce saved in the tamper-proof cookie. If the values do match, the web app considers the request valid- and, as shown in leg 4 of the diagram, establishes a session of its own and, importantly, removes the nonce tracking cookie (or any other measure that would make the nonce single use).
If an attacker manages to steal the id token and attempts to use it, they will be unable to present a corresponding nonce tracking cookie with the value matching the id token content- as they don't have access to the crypto material the web app uses to manufacture and verify such cookies. Voila, the replay attack is defeated!
Although this is not directly germane to OAuth 2.1 per se, you can expect discussions like above to be common in the months ahead as the community digests the impact of the changes in OAuth 2.1. Hopefully, this diagram, and this podcast episode in general, equipped you to contribute to those discussions and decide how to apply this knowledge to your own scenarios!
If you want to dig further on the topic of OAuth 2.1, you can also take a look at the recording of a 30 mins session from the ASC 2020 conference here.
Links/Resources:
Learn more about Aaron Parecki
Aaron Parecki on Twitter
Aaron’s ebook on OAuth
Vittorio Bertocci on LinkedIn
Vittorio Bertocci on Twitter
Learn more about Identity, Unlocked
Learn more about Auth0
Identity, Unlocked
Identity, Unlocked is the podcast that discusses identity specs and trends from a developer perspective. Identity, Unlocked is powered by Auth0. Vittorio Bertocci is Principal Architect at Auth0 and applies his vast knowledge of the identity industry to Auth0 in all aspects of the company, including internal and external education, product innovation, and customer integration.
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.