Safeguard
AI Security•

What is PKCE and why must MCP clients use it?

PKCE stops a stolen OAuth authorization code from being redeemed by an attacker. The MCP spec requires S256 and says to refuse servers without support.

Safeguard Security Team
3 min read

PKCE (Proof Key for Code Exchange) is an OAuth extension that ties an authorization code to the client that asked for it. The client creates a secret and sends a hash of it first, then proves it holds the secret when redeeming the code. The MCP specification requires clients to use PKCE with the S256 method.

Definitions

Authorization code. A short-lived value the authorization server sends back to the client after the user approves access. The client swaps it for an access token.

Code verifier. A random secret the client generates and keeps.

Code challenge. A hash of the verifier, sent with the first request. With S256 the hash is SHA-256.

Interception. An attacker obtains the authorization code, for example from a redirect they can observe on the device. Without PKCE, the code alone can be redeemed.

How the exchange works

  1. The client generates a verifier and computes the challenge.
  2. It sends the user to the authorization server with the challenge, a state value, and the MCP server it wants a token for.
  3. The user approves. The server redirects back with a code.
  4. The client calls the token endpoint with the code and the original verifier.
  5. The server hashes the verifier and compares it with the stored challenge. If they match, it issues the token.

An attacker who copies the code in step 3 has no verifier, so step 4 fails for them.

What the MCP specification asks

RequirementDetail
Clients must implement PKCEPer OAuth 2.1
MethodS256 when technically capable
Check support firstThe client must look for code_challenge_methods_supported in the authorization server metadata
If the field is absentThe client must refuse to proceed
Redirect URIsRegistered and matched exactly
StateClients should send and verify it, and discard mismatches

The refusal rule matters. A client that quietly falls back to a flow without PKCE has removed the protection the specification relies on.

What to test in your own setup

  • Start an authorization request without a challenge and confirm the authorization server rejects it.
  • Check the metadata document for code_challenge_methods_supported and confirm S256 is listed.
  • Confirm redirect URIs are exact strings, not patterns.
  • Confirm access tokens are short-lived and refresh tokens for public clients rotate. The specification says so.

Common confusions

PKCE does not authenticate the user and does not replace token audience checks. It protects one step: the swap of code for token. You still need audience validation, minimal scopes and HTTPS everywhere.

Quick check

Is PKCE only for mobile apps?

No. It began as protection for public clients and is now a baseline for OAuth 2.1, including the clients MCP assumes.

What if my authorization server does not advertise PKCE support?

The MCP specification says the client must refuse to proceed. Ask the provider to enable and advertise S256.

Does PKCE stop a malicious MCP server?

No. It protects the code exchange. Malicious servers are handled by consent prompts, URL validation and sandboxing.

Where Safeguard fits

Safeguard scans the OAuth and MCP client libraries in your projects for known vulnerable versions and can gate pull requests that introduce them. Try a free scan at gold.safeguard.sh/scan.

Sources

Last reviewed: 19 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.