Join our Newsletter — 33% off our NHI Course

What is the difference between PKCE and a client secret?

PKCE binds an authorisation request to the same client that later redeems the code, while a client secret is a shared credential used to authenticate a confidential client to the token endpoint. PKCE protects public clients that cannot safely store secrets. Use PKCE for browser and mobile apps, and never treat it as a substitute for secret protection where a secret is actually required.

How PKCE and a client secret solve different problems

PKCE is a proof-of-possession mechanism for an OAuth authorization code flow. The client creates a one-time verifier, derives a challenge, and later proves it still has the verifier when redeeming the code. A client secret is different: it is a shared credential used by a confidential client to authenticate itself to the token endpoint, so the server can distinguish an approved application from an untrusted caller.

The practical difference is about trust and storage. PKCE binds the code exchange to the same client instance that started the login flow, which is why it fits browser and mobile apps that cannot safely hide a long-lived secret. A client secret is appropriate only when the application can store it securely and keep it out of user-controlled environments.

That distinction matters because PKCE does not replace a client secret where one is actually required. If an application is a confidential client, the secret still authenticates the app, while PKCE reduces code interception and authorization code replay risk. If the application is public, PKCE becomes the main protection for the code exchange, because there is no reliable secret to keep confidential.

Where PKCE fits in the OAuth flow

PKCE protects the handoff between the authorization endpoint and the token endpoint. It reduces the value of a stolen authorization code by making that code useless without the original verifier. In other words, the code alone is no longer enough to complete the exchange.

That is why PKCE is now a standard expectation for modern browser-based and mobile sign-in flows. It is a flow protection, not an application credential. It addresses interception and replay of the code, but it does not authenticate the application in the same way a client secret does.

For the underlying OAuth model and client-type distinctions, the most useful primary references are OAuth 2.0 and OpenID Connect Guide for Identity Teams and RFC 9700: Best Current Practice for OAuth 2.0 Security.

When a client secret is still the right control

A client secret exists to authenticate a confidential client, usually a server-side application that can protect shared credentials better than a browser or mobile app can. It is not just another token in the flow. It is a standing credential, so its protection, storage, rotation, and exposure risk matter much more than they do for PKCE.

If the secret is leaked, the application can be impersonated at the token endpoint. That changes the failure mode from “one login attempt was intercepted” to “the application itself may be abused until the secret is rotated or revoked.” For that reason, secret handling belongs in the same discipline as credential protection, not in the same bucket as proof keys used by PKCE.

This is also why many teams pair PKCE with other token-bound or client-authentication mechanisms instead of treating PKCE as a universal answer. The OAuth standard and the security best-practice guidance both make clear that PKCE hardens the authorization code flow, while the client secret remains an application credential that must be protected separately.

The distinction becomes more concrete when you look at OneLogin API flaw (CVE-2025-59363), which shows how exposed oidc client secret can become a direct impersonation risk, and Secrets Management Guide, which covers how to protect shared credentials when they are genuinely required.

Risk and Threat Considerations

PKCE mainly reduces authorization code interception and replay, while a client secret failure is a broader credential-compromise problem. The operational risk is using PKCE as if it made a public client equivalent to a confidential client, or assuming a secret is safe just because PKCE is enabled.

Failure mechanism: An intercepted authorization code can be replayed if PKCE is absent or implemented incorrectly, while a leaked client secret can let an attacker authenticate as the application itself. Those are different attack paths and they demand different containment actions.

Impact: Code replay can produce unauthorized token issuance for a single flow, but client secret compromise can expose the whole application trust relationship until the secret is rotated, revoked, and any dependent integrations are reviewed.

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-63, NIST SP 800-53 Rev 5 and OWASP ASVS set the governance and control requirements practitioners need to meet.

Framework Control / Reference Relevance
NIST SP 800-63 Digital Identity Guidelines PKCE and client secrets are core OAuth client-authentication choices in digital identity flows.
Recommendation — Apply phishing-resistant and flow-appropriate client authentication for the deployment model.
OWASP API Security Top 10 API2 — Broken Authentication OAuth token-endpoint client authentication and replay resistance are central to this comparison.
Recommendation — Validate client authentication and token exchange to prevent code replay and impersonation.
NIST SP 800-53 Rev 5 IA-5 — Authenticator Management Client secrets are authenticators that require secure storage, rotation, and revocation.
IA-9 — Service Identification and Authentication OAuth clients and app-to-token-endpoint authentication fit service authentication controls.
Recommendation — Manage client secrets with lifecycle controls, rotation, and revocation procedures. Use service authentication controls that match the client’s ability to safeguard credentials.
OWASP ASVS V10 — OAuth and OIDC This question is about OAuth/OpenID Connect client types, PKCE, and token redemption protections.
Recommendation — Require PKCE and correct client-type handling in OAuth and OpenID Connect implementations.

Practitioner Guidance

Decision rule: Use PKCE whenever the client cannot safely store a secret, especially in browser and mobile apps. If the app can truly protect a shared credential, keep the client secret and treat PKCE as an added code-exchange safeguard, not as a replacement.

What to verify: Confirm that the app is correctly classified as public or confidential, that PKCE is enforced for the relevant flow, and that any client secret is stored outside user-controlled code or front-end delivery paths. A flow that depends on a secret the client cannot actually keep private is misdesigned.

What practitioners underestimate: PKCE reduces one class of attack, but it does not change the secret-handling burden where a secret exists. The right question is not “PKCE or secret?”, it is “Which trust model does this client actually support?”

Practitioner takeaway: PKCE protects the authorization-code exchange; a client secret authenticates a confidential client. Choose them based on the client’s trust model, and never let PKCE become a substitute for credential protection where a real secret is still required.