
Could your OAuth setup quietly be leaking customer data?
OAuth 2.0 is foundational for API security, but subtle implementation mistakes can expose sensitive customer data. RFC 9700 (also known as OAuth 2.0 Best Current Practice) provides concrete, real-world advice to harden OAuth implementations and avoid common vulnerabilities.
This guide translates RFC 9700 into actionable practices for developers building secure, high-performance APIs.
OAuth 2.0 offers flexibility, but this comes with risks. Older or insecure flows, such as implicit grants and resource owner password credentials (ROPC), are vulnerable to attacks like token interception or replay. RFC 9700 deprecates insecure methods and strengthens OAuth flows with mandatory security measures like PKCE (Proof Key for Code Exchange).
Implicit grants: An OAuth 2.0 flow where access tokens are returned directly in the URL fragment. Designed initially for browser-based JavaScript apps. However, tokens can leak through browser history, referrer headers, or logs. Here’s an example of an implicit grant:
Resource Owner Password Credentials (ROPC): A flow where users directly give their username/password to the client app, which exchanges these credentials for an access token. This exposes user credentials directly to the client app, increasing risk. Here’s an example of ROPC flow.
RFC 9700 explicitly recommends dropping these insecure flows.
The authorization code flow is OAuth’s most secure flow. Instead of directly sending tokens, the authorization server first returns an authorization code that the app exchanges for tokens. PKCE enhances this further.
What is PKCE (Proof Key for Code Exchange)?
PKCE is a security mechanism that prevents interception attacks by associating each authorization request with a unique secret (called a code_verifier). The server receives only a hashed version (code_challenge) during authorization, ensuring tokens are delivered securely only to authorized clients. PKCE is mandatory, even for server-side apps, in RFC 9700.
code_verifier: Secret randomly generated by client (never shared openly).
code_challenge: SHA-256 hashed version of the code_verifier sent to the server.
code_challenge_method: Hashing algorithm, always use S256.
After the user authenticates, the server responds with an authorization code. The app exchanges this code, including the original code_verifier, for an access token.
Mistake: Not validating redirect URIs exactly.
Correct approach: Perform strict string equality checks.
Mistake: Using PKCE incorrectly or insecurely (e.g., weak random strings).
Correct approach: Always generate cryptographically strong verifiers (use Node’s crypto library).
Here's a practical, secure JavaScript snippet (using Node.js's built-in crypto library) for generating cryptographically strong PKCE verifiers.
generateCodeVerifier(): Creates a random, high-entropy string using crypto.randomBytes(). This is ideal for secure OAuth PKCE implementations.
generateCodeChallenge(): Hashes the verifier with SHA-256 as required for the PKCE flow. The challenge is safe to transmit publicly in authorization requests.
But for customer-facing, sensitive APIs, RFC 9700 practices should be followed rigorously.
RFC 9700 provides essential, actionable guidance that significantly enhances OAuth 2.0 security. By clearly outlining secure flows (Authorization Code with PKCE), explicitly discouraging risky methods (implicit and password grants), and highlighting critical implementation details like strict redirect validation and secure token handling, RFC 9700 helps developers build APIs resistant to real-world OAuth vulnerabilities.
Adopting RFC 9700 ensures:
For developers serious about protecting customer data and maintaining trust, RFC 9700 is a practical blueprint for secure OAuth.
The implicit grant flow exposes access tokens directly in the URL fragment. This exposure makes tokens vulnerable to leakage through browser history, referrer headers, or system logs. RFC 9700 recommends replacing this legacy method with the authorization code flow combined with PKCE. By moving token delivery to a secure backchannel exchange, developers eliminate the primary attack surface found in browser based applications. This shift is critical for modern B2B applications where protecting customer data and session integrity remains the top priority for engineering teams and CISOs who want to avoid accidental data exposure.
PKCE introduces a dynamic secret called a code verifier to the authorization process. The client sends a hashed version of this secret initially and provides the raw secret only during the token exchange phase. This mechanism ensures that even if an attacker intercepts the authorization code, they cannot exchange it for a token without the original verifier. RFC 9700 now mandates PKCE for all client types, including server side apps. This prevents interception attacks and provides a cryptographically strong binding between the initial request and the final token issuance, significantly hardening the entire OAuth lifecycle for high performance APIs.
The Resource Owner Password Credentials flow requires users to share their primary credentials directly with the client application. This practice increases the risk of credential theft and bypasses the security benefits of centralized identity providers. RFC 9700 explicitly deprecates this flow because it creates a massive trust burden on the client app and complicates the implementation of multi factor authentication. Modern B2B architectures should instead use redirected flows or federated identity to ensure that sensitive user passwords never touch the application code, thereby reducing the overall blast radius of potential security breaches in enterprise environments.
Lax redirect URI validation allows attackers to intercept authorization codes by redirecting users to malicious endpoints. If an application accepts wildcard matches or subdomains, an attacker could craft a request that sends sensitive codes to a server they control. RFC 9700 insists on strict string equality checks for all redirect URIs. This simple but effective practice prevents open redirector vulnerabilities and ensures that tokens are only delivered to pre approved, trusted environments. Consistent validation is a cornerstone of secure OAuth implementations, protecting both service providers and their end users from sophisticated phishing and interception attempts.
For machine to machine or agent to agent communication, RFC 9700 and modern standards suggest moving away from simple client secrets. Instead, developers should utilize strong authentication methods like JWT client assertions or mutual TLS. These methods provide higher assurance and are less susceptible to accidental exposure in configuration files or logs. In the context of AI agents and MCP servers, utilizing secure M2M flows ensures that autonomous systems can interact with APIs without human intervention while maintaining a high security posture. Implementing these robust authentication patterns is vital for scaling enterprise grade B2B integrations safely and efficiently.
Refresh token rotation is a defensive strategy where a new refresh token is issued every time the current one is used. This process ensures that if a token is stolen, the original holder and the attacker will eventually conflict, allowing the authorization server to detect the anomaly and revoke all associated sessions. RFC 9700 emphasizes the importance of this technique alongside short lived access tokens. By limiting the lifespan of credentials and rotating them frequently, organizations can minimize the window of opportunity for attackers and improve their overall ability to detect and respond to unauthorized access within their systems.
AI agents often require delegated access to external tools and data via MCP servers. Using OAuth with PKCE allows these agents to obtain scoped permissions without ever handling user credentials directly. This architectural approach follows the principle of least privilege by using minimal scopes tailored to the specific task the agent needs to perform. As AI agents become more autonomous in B2B environments, implementing RFC 9700 compliant flows ensures that their access is auditable, revocable, and secure. This foundation allows organizations to leverage AI capabilities while strictly adhering to enterprise security policies and complex compliance requirements.
RFC 9700 serves as a comprehensive blueprint for modernizing B2B authorization by consolidating years of security lessons into a single standard. It shifts the industry toward the authorization code flow with PKCE as the universal best practice. For engineering managers and CTOs, adopting this standard means reduced technical debt and a more resilient security architecture. By following these guidelines, B2B platforms can offer their customers a secure and standardized way to integrate services, ensuring that data exchange is protected against common vulnerabilities like token injection, mix up attacks, and unauthorized credential exposure across complex distributed systems.
To prevent token replay attacks, RFC 9700 recommends several strategies including the use of unique token identifiers and short lived credentials. Authorization servers should enforce that each authorization code is used exactly once. If a code is presented a second time, the server must revoke all tokens issued from that original request. Additionally, implementing sender constrained tokens using mTLS or DPoP provides an extra layer of protection by binding the token to the specific client that requested it. These measures collectively ensure that intercepted tokens cannot be reused by malicious actors, maintaining the integrity of the authentication system.