TL;DR: PKCE closes code interception and code injection gaps in OAuth Authorization Code flows by binding each token exchange to a one-time verifier, and OAuth 2.1 now requires it for all clients, according to WorkOS. The practical shift is that teams should treat PKCE as the default control layer, not an optional hardening step.
At a glance
What this is: This article explains how Proof Key for Code Exchange secures OAuth Authorization Code flows by binding each token exchange to a one-time verifier and making PKCE the default expectation in OAuth 2.1.
Why it matters: It matters because IAM teams should treat PKCE as a required control for OAuth implementations, reducing interception and injection exposure across public and confidential clients alike.
Context
PKCE is a protective layer for OAuth Authorization Code flows. It prevents an intercepted authorization code from being redeemed without the matching verifier, which changes the trust model for public clients and narrows the abuse window for server-side applications too.
The identity governance issue is not just protocol hygiene. When authentication and delegated authorization depend on browser redirects, mobile app flows, and third-party integrations, teams need a control that binds the code exchange to the original request rather than to whoever captures the redirect.
OAuth 2.1 turns that control into the baseline. For IAM and application teams, the practical question is no longer whether PKCE is useful, but whether every code flow has been upgraded to require it consistently.
Key questions
Q: How should security teams implement PKCE across OAuth clients?
A: Apply PKCE to every authorization code flow, including confidential clients, and make it non-optional in your authorization server policy. Pair it with exact redirect URI registration and session binding so an intercepted code cannot be replayed into a different context. For workloads and agents, treat this as baseline identity hardening, not an advanced feature.
Q: Why does PKCE matter if a client already has a secret?
A: A client secret protects the application, but it does not prove that the entity redeeming the authorization code is the same one that requested it. PKCE adds that proof. It prevents intercepted codes from being exchanged elsewhere and reduces the risk created by modern browser, mobile, and distributed app delivery models.
Q: What breaks when PKCE is not enforced in OAuth 2.1?
A: Without PKCE, intercepted authorization codes can be redeemed by an attacker, and redirect tampering becomes easier to exploit. The result is that code possession becomes too powerful, especially in browser, mobile, and proxy-mediated flows where front-channel exposure is realistic.
Q: What should security teams do when migrating from implicit or password grants?
A: Move those applications onto the Authorization Code flow with PKCE and remove legacy grant dependencies from roadmap planning. OAuth 2.1 guidance is clear that the safer code flow is the target state, so migration should focus on redirect handling, verifier management, and library defaults.
Technical breakdown
How PKCE prevents authorization code interception
PKCE adds a one-time code verifier and a derived code challenge to the Authorization Code flow. The client sends the challenge up front, then proves possession of the verifier during the token exchange. The authorization server recomputes the hash and only issues tokens when the values match. That closes a common attack path where an intercepted authorization code is redeemed by a different client. In practice, PKCE shifts trust from the redirect alone to a cryptographic proof tied to the original login request.
Practical implication: Require PKCE on every Authorization Code flow so intercepted codes cannot be redeemed out of context.
Why PKCE is now mandatory beyond public clients
OAuth 2.1 removes the old distinction that treated PKCE as optional for confidential clients. The article’s point is that client secrets do not cover every code-flow risk, especially when redirect handling can be manipulated or exposed through proxies, browsers, or extensions. PKCE therefore becomes a universal binding control, not just a workaround for apps that cannot store secrets. That matters because the operational rule gets simpler: if a system uses the Authorization Code flow, it should use PKCE by default.
Practical implication: Update implementation standards so PKCE is enforced uniformly across public and confidential OAuth clients.
Common PKCE implementation failures that weaken the control
The control only works when the verifier is fresh, the S256 method is used, and the verifier is stored safely until exchange. Reusing verifiers creates replay risk, the plain method removes the hash-based protection, and losing the verifier breaks the transaction. Another common failure is inconsistent SDK behaviour, where teams assume the library enabled PKCE but never verify it. These are not theoretical edge cases. They are the places where apparently correct OAuth code still leaves an exploitable gap.
Practical implication: Audit SDK defaults, verifier handling, and S256 enforcement before treating PKCE coverage as complete.
Breaches seen in the wild
- Salesloft OAuth token breach: hackers stole OAuth tokens to access Salesforce data via Salesloft.
- Klue OAuth Supply Chain Breach: OAuth tokens compromised in Klue integration breach affecting 700+ organisations via Salesforce data access chain.
Read and download The State of NHI & AI Agent Breach Report 2026, covering 150+ breaches impacting Non-Human Identities including AI Agents.
NHI Mgmt Group analysis
PKCE is now a baseline trust-control, not a compensating control. The article shows a clear shift in how OAuth code flows should be governed: PKCE is no longer only for public clients that cannot hold secrets. That changes the control model for IAM teams because the secure state is now universal code-binding, not exception-based hardening. Practitioners should treat omission of PKCE as a control gap, not a design choice.
Authorization Code flows now depend on proof of request origin, not just client authentication. Client secrets solve one class of abuse, but they do not stop intercepted or manipulated redirects from being redeemed when the flow itself is not bound to the originating request. That is the important governance lesson for application identity: the assurance target has moved from who the client is to whether the exchange is cryptographically tied to the session that initiated it.
OAuth 2.1 formalises a security posture the ecosystem had already converged on. WorkOS is describing a broader standards pattern, not a vendor-specific preference: risky legacy flows are being pushed out, while PKCE becomes the default expectation. That means migration planning should focus less on feature parity and more on control parity across every application class that participates in delegated authorization.
PKCE closes the gap between protocol theory and real deployment conditions. Redirects, browser exposure, mobile decompilation, and library inconsistency all weaken assumptions that look sound on paper. The practical conclusion is that identity teams need to govern OAuth implementations as runtime security systems, not just as configuration settings.
OAuth code-flow security now depends on implementation discipline at the library level. A standard can mandate PKCE, but production risk still emerges when teams rely on defaults they have not verified. That elevates configuration assurance, test coverage, and platform review to identity controls, not just application engineering tasks.
From our research library:
- Security researchers tracked consent phishing campaigns affecting 900 tenants and 3,000 user accounts in 2025.
What this signals
PKCE baseline drift: OAuth teams should assume that any code flow without PKCE is now operating below current security expectations. The practical issue is not whether the app is public or confidential, but whether the exchange is cryptographically bound to the session that initiated it.
OAuth implementation reviews should now test for verifier freshness, S256 enforcement, and SDK defaults as first-class controls. That shifts PKCE from a documentation checkbox into a runtime assurance requirement for application and IAM teams.
Where organisations still carry implicit or password grant dependencies, the migration target is now clearer. PKCE-backed Authorization Code flows are the secure default, and governance should be written to reflect that default rather than preserve older exceptions.
For practitioners
- Enforce PKCE on every Authorization Code flow Make PKCE a non-optional requirement for public and confidential clients that use authorization-code exchanges, and reject deployments that omit it.
- Standardise on S256 only Block the plain method in policy and SDK configuration so every verifier challenge is hashed with SHA-256.
- Generate a fresh verifier for each login attempt Treat the code verifier as a one-time value and prohibit reuse across sessions to reduce replay exposure.
- Verify SDK behaviour before rollout Check whether your OAuth library enables PKCE automatically or requires explicit configuration, then test the token exchange path end to end.
- Retire deprecated OAuth flows Remove implicit and password grant usage from new builds and migration plans, since OAuth 2.1 guidance centres secure code flows with PKCE.
Key takeaways
- PKCE changes OAuth code flows from bearer-like redirect handling to request-bound token exchange, which reduces interception and injection exposure.
- OAuth 2.1 makes PKCE the default expectation across clients, so treating it as optional leaves implementations behind current guidance.
- The practical control question is whether every flow uses PKCE correctly, with fresh verifiers, S256 hashing, and verified SDK behaviour.
Standards & Framework Alignment
This section maps relevant standards and security frameworks to the operational risks and controls described in this guidance.
OWASP API Security Top 10 addresses the attack and risk surface, while NIST SP 800-53 Rev 5, NIST CSF 2.0 and OWASP ASVS set the governance and control requirements practitioners need to meet.
| Framework | Control / Reference | Relevance |
|---|---|---|
| OWASP API Security Top 10 | API2 — Broken Authentication | PKCE hardens OAuth code exchange against authentication bypass and interception. |
| Recommendation — Require PKCE and verify token exchange to prevent authentication bypass in OAuth flows. | ||
| NIST SP 800-53 Rev 5 | IA-5 — Authenticator Management | PKCE depends on secure generation and handling of one-time verifiers. |
| Recommendation — Manage one-time OAuth verifiers and reject reuse to preserve authenticator integrity. | ||
| NIST CSF 2.0 | PR.AA-05 — Access Permissions, Entitlements and Authorizations | The article is about controlling authorization in delegated OAuth flows. |
| Recommendation — Apply authorization controls to ensure token issuance is bound to the initiating session. | ||
| OWASP ASVS | V10 — OAuth and OIDC | PKCE is an OAuth/OIDC control directly covered by ASVS requirements. |
| Recommendation — Verify OAuth flows against ASVS OAuth and OIDC requirements, including PKCE enforcement. | ||
Key terms
- Proof Key for Code Exchange: PKCE is an OAuth extension that binds an authorization code to the client instance that started the login flow. It prevents a stolen code from being redeemed without proof of initiation, which is why it is now treated as a baseline control in modern OAuth deployments.
- Authorization Code Flow: Authorization code flow is the common OAuth pattern where the client first receives a temporary code and then exchanges it for an access token. The design keeps tokens off the front channel and reduces exposure, but it still depends on correct client validation and careful redirect handling.
- Code Verifier: A code verifier is a high-entropy secret created by the client during an OAuth login request. The client later presents it during token exchange so the authorization server can prove the same client initiated and completed the flow, reducing the value of intercepted codes.
- Code Challenge: A code challenge is the hashed form of the code verifier sent up front in a PKCE flow. The authorization server stores it and uses it later to confirm the verifier matches, which lets the server validate the exchange without exposing the original secret in transit.
Deepen your knowledge
NHI governance, agentic AI identity, and machine identity lifecycle are core topics in our NHI Foundation Level course, the industry's only accredited NHI security programme. If you are responsible for identity security strategy or NHI governance in your organisation, it is worth exploring.
Published by the NHIMG editorial team on June 12, 2026.
Updated on October 8, 2026.
NHI Mgmt Group, the independent authority on Non-Human Identity, IAM, and Agentic AI security. nhimg.org