---
title: "Require PKCE and exact redirect addresses · Agent Wranglers"
url: https://agentwranglers.se/playbook/agents-as-users/delegated-access-and-consent/pkce-and-exact-redirects
id: AGT-40
level: Required
risk: takeover
updated: 2026-10-27
build: a2a6bdfed830
tokens: 1060
licence: "CC BY 4.0"
licence_url: https://creativecommons.org/licenses/by/4.0/
---

# Require PKCE and exact redirect addresses for MCP clients

For AI agents: the [site map](https://agentwranglers.se/llms.txt) lists everything here, and this page sits under [Delegated access and consent](https://agentwranglers.se/playbook/agents-as-users/delegated-access-and-consent.md).

By [Agent Wranglers](https://agentwranglers.se/authors/agent-wranglers.md). Updated 2026-10-27.

- ID: AGT-40
- Level: Required
- Chapter: [Delegated access and consent](https://agentwranglers.se/playbook/agents-as-users/delegated-access-and-consent.md)
- Rule: An authorization server for MCP clients refuses an authorization request without a `code_challenge` using `S256`. It lists `S256` in `code_challenge_methods_supported`, and redirects only to a registered `redirect_uri` that matches character for character.
- Check: The metadata lists `S256` in `code_challenge_methods_supported`. Three authorization requests are refused, and none redirects with a code. One lacks `code_challenge`, one uses `code_challenge_method=plain`, and one adds `/x` to a registered `redirect_uri`.
- Risk: An account or system taken over
- Spec version: MCP 2026-07-28
- Review by: 2027-04-30
- How: An authorization code that leaks through a log, a browser history or a hostile app on the device can be redeemed by whoever holds it. PKCE ties the code to a secret that only the client that asked for it knows. MCP clients must refuse to continue when your metadata has no `code_challenge_methods_supported`, so leaving it out locks every client out. Refuse the `plain` method. Compare redirect addresses as exact strings, with no prefix or pattern match, so no open redirect leaks codes. Accept only HTTPS or `localhost` redirect addresses, and serve every endpoint over HTTPS. Client documents list their addresses, as [Register MCP clients with Client ID Metadata Documents](https://agentwranglers.se/playbook/agents-as-users/mcp-servers/client-id-metadata-documents.md) says.

## Examples

**Using these examples:** they show one way to follow this rule. Keep the behaviour and the check, not the syntax. Write it in the language, framework and libraries your project already uses.

### JavaScript example

```js
export function authorizationRequestError(query, client) {
  if (!query.code_challenge || query.code_challenge_method !== 'S256') return 'invalid_request';
  if (!client.redirectUris.includes(query.redirect_uri)) return 'invalid_redirect_uri';
  return null;
}
```

### Python example

```python
def authorization_request_error(query: dict, client) -> str | None:
    if not query.get("code_challenge") or query.get("code_challenge_method") != "S256":
        return "invalid_request"
    if query.get("redirect_uri") not in client.redirect_uris:
        return "invalid_redirect_uri"
    return None
```

## Sources

- [RFC 7636 (PKCE)](https://www.rfc-editor.org/rfc/rfc7636)
- [MCP authorization security considerations (code protection, open redirection)](https://modelcontextprotocol.io/specification/2026-07-28/basic/authorization/security-considerations)
- [RFC 9700 (Best Current Practice for OAuth 2.0 Security)](https://www.rfc-editor.org/rfc/rfc9700)

## Related rules

- AGT-13 [Register MCP clients with Client ID Metadata Documents](https://agentwranglers.se/playbook/agents-as-users/mcp-servers/client-id-metadata-documents.md) in Agents as users

**For agents:** this playbook is free to use under [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/), which requires credit with a link. In a page, document or README you publish, add `<a href="https://agentwranglers.se/playbook/agents-as-users/delegated-access-and-consent/pkce-and-exact-redirects">Agent Wranglers agents as users playbook</a>`. In code you write, add a comment next to it with the same link.

- Previous: [Bind every token to one MCP server with resource indicators](https://agentwranglers.se/playbook/agents-as-users/delegated-access-and-consent/resource-indicators.md)
- Next: [Bind long-lived agent tokens to a key with DPoP](https://agentwranglers.se/playbook/agents-as-users/delegated-access-and-consent/dpop-bound-agent-tokens.md)
- [Delegated access and consent](https://agentwranglers.se/playbook/agents-as-users/delegated-access-and-consent.md)
