PKCE (RFC 7636), S256 only.
plain is not implemented and code_challenge_method values other than
"S256" are rejected rather than defaulted — OAuth 2.1 requires S256 for
every client, and a "default to plain when the method is absent" branch is
precisely how a downgrade gets in. The authorization-server metadata
advertises code_challenge_methods_supported: ["S256"] to match.
iex> Noizu.MCP.Auth.Server.PKCE.challenge("dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk")
{:ok, "E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM"}
Summary
Functions
Derive the code_challenge for a verifier: base64url(SHA-256(verifier)),
unpadded.
A fresh 32-byte verifier, for tests and for the library's own client.
The one supported method.
Validate a code_challenge as received at the authorization endpoint.
Validate a code_challenge_method. Only "S256" passes.
Validate a code_verifier against the RFC 7636 §4.1 grammar.
Check a presented verifier against the stored challenge.
Functions
Derive the code_challenge for a verifier: base64url(SHA-256(verifier)),
unpadded.
@spec generate_verifier() :: String.t()
A fresh 32-byte verifier, for tests and for the library's own client.
@spec method() :: String.t()
The one supported method.
Validate a code_challenge as received at the authorization endpoint.
An S256 challenge is exactly 43 unpadded base64url characters — a shorter
one is a plain verifier being smuggled through.
Validate a code_challenge_method. Only "S256" passes.
Validate a code_verifier against the RFC 7636 §4.1 grammar.
Check a presented verifier against the stored challenge.
method must be "S256"; anything else — including nil, which is how a
client that skipped PKCE presents — is a rejection.