OAuth 2.0 was published as RFC 6749 in 2012. In the decade since, the threat landscape shifted dramatically and the security community accumulated hard-won lessons about how OAuth deployments fail in practice. BCP 212 - formally published as RFC 9700 - codifies those lessons into updated security best practices that every OAuth implementer should understand.
This is not a new version of OAuth. The core protocol remains the same. What BCP 212 does is narrow the set of acceptable implementation choices, deprecating patterns that were originally permitted but have proven dangerous, and mandating protections that were previously optional.
For organizations building or maintaining OAuth-based authentication and authorization systems, these changes have immediate practical implications.
The Implicit Grant Is Deprecated
The implicit grant was designed for browser-based applications that could not securely store client secrets. Instead of exchanging an authorization code for tokens at a token endpoint, the authorization server returned the access token directly in the URL fragment.
This was always a compromise. Tokens in URL fragments are exposed to browser history, referrer headers, and any JavaScript running on the page. The implicit grant also provides no mechanism for refresh tokens, forcing repeated authorization flows.
BCP 212 formally deprecates the implicit grant. Browser-based applications should use the authorization code grant with PKCE instead. Modern browser capabilities - including the ability to make cross-origin requests to token endpoints - eliminate the technical constraints that originally motivated the implicit flow.
For implementers, this means auditing existing OAuth clients that use response_type=token and migrating them to the authorization code flow. Authorization servers should consider logging or alerting on implicit grant usage to track migration progress.
PKCE Is Required for All Clients
Proof Key for Code Exchange (PKCE, pronounced “pixy”) was originally introduced in RFC 7636 as a protection for mobile applications against authorization code interception attacks. BCP 212 extends this requirement to all OAuth clients, including confidential clients that authenticate with client secrets.
The reasoning is straightforward. PKCE protects against authorization code injection attacks regardless of client type. A confidential client that authenticates with a client secret is still vulnerable if an attacker can inject a stolen authorization code into the client’s redirect URI. PKCE prevents this by binding the authorization request to the token request through a cryptographic challenge.
The implementation overhead is minimal. The client generates a random code_verifier, derives a code_challenge using SHA-256, sends the challenge with the authorization request, and sends the verifier with the token request. The authorization server verifies that the verifier matches the original challenge before issuing tokens.
Authorization servers that do not currently enforce PKCE should add support and plan a timeline for mandatory enforcement. Clients that do not currently send PKCE parameters need to be updated.
Exact Redirect URI Matching
OAuth’s redirect URI is one of the most security-sensitive parameters in the protocol. The authorization server uses it to send the authorization code (or token, in the deprecated implicit flow) back to the client. If an attacker can manipulate the redirect URI, they can intercept authorization codes.
RFC 6749 allowed authorization servers to support pattern matching for redirect URIs - for example, allowing any path under a registered domain. In practice, this created vulnerabilities. Open redirectors on registered domains, path traversal, and subdomain takeover attacks all allowed redirect URI manipulation when pattern matching was used.
BCP 212 requires exact string matching for redirect URIs. The URI registered by the client must exactly match the URI included in the authorization request. No wildcards, no pattern matching, no prefix matching.
This is stricter than what many authorization servers currently enforce. Implementers should audit their redirect URI validation logic and tighten it to exact matching. Client registrations that rely on wildcard or pattern-based redirect URIs need to be updated to register each specific URI individually.
Sender-Constrained Tokens
Bearer tokens - the default token type in most OAuth deployments - have a fundamental weakness: anyone who possesses the token can use it. If a token is stolen through a compromised log, a man-in-the-middle attack, or a server-side vulnerability, the attacker can use that token as if they were the legitimate client.
BCP 212 recommends sender-constrained tokens as a mitigation. Two mechanisms are defined:
DPoP (Demonstrating Proof of Possession) allows clients to prove they hold a private key associated with the token. The client generates a key pair, includes the public key in the token request, and signs each API request with a DPoP proof. The resource server verifies that the proof was signed by the key associated with the token. A stolen token is useless without the corresponding private key.
Mutual TLS (mTLS) certificate-bound tokens bind the token to the client’s TLS certificate. The authorization server records the certificate thumbprint when issuing the token, and the resource server verifies that the presenting client’s certificate matches. This provides sender-constraining at the transport layer.
DPoP is generally more practical for browser-based and mobile applications because it does not require client certificate infrastructure. mTLS is better suited for server-to-server communication where certificate management is already established.
Adopting sender-constrained tokens is a more significant engineering effort than the other BCP 212 changes. It requires updates to the authorization server, the client, and every resource server that validates tokens. For many organizations, this will be a multi-phase rollout.
Additional Recommendations
BCP 212 includes several other notable recommendations:
Refresh token rotation - authorization servers should issue a new refresh token with each use and invalidate the old one. This limits the window of exposure if a refresh token is compromised and enables detection of token theft (when both the legitimate client and the attacker try to use the same refresh token).
Authorization code lifetime - codes should be short-lived (recommended maximum of 10 minutes) and single-use. The authorization server should revoke all tokens issued from an authorization code if the code is presented a second time.
Resource indicators - RFC 8707 resource indicators should be used to restrict tokens to specific resource servers, preventing a token issued for one API from being used at another.
Token revocation - clients should actively revoke tokens when they are no longer needed, rather than relying on expiration alone.
Practical Impact for Implementers
The BCP 212 changes fall into three categories of implementation effort:
Straightforward changes that should be addressed immediately: deprecating implicit grant usage, enforcing PKCE for all clients, and tightening redirect URI validation to exact matching. These are configuration and validation changes that most authorization server platforms already support.
Medium-effort changes that require coordinated updates: refresh token rotation, authorization code hardening, and resource indicators. These need changes to both server and client implementations but follow well-documented patterns.
Significant architectural changes that require planning: sender-constrained tokens via DPoP or mTLS. These touch every component in the token lifecycle and should be phased in, starting with the most sensitive API endpoints.
Organizations running commercial identity platforms (Auth0, Okta, Ping, ForgeRock) should verify their provider’s BCP 212 compliance timeline. Most major platforms have announced support for PKCE enforcement and redirect URI tightening. DPoP support varies more widely.
Organizations running custom OAuth implementations have more work to do, but BCP 212 provides a clear and prioritized roadmap for hardening their deployments. The security improvements are substantial, and the threat models that motivated these changes are actively exploited in the wild.