Generate an RFC 7636 PKCE code_verifier and S256 code_challenge for the OAuth 2.0/2.1 authorization code flow.
With plain, the code_challenge is the code_verifier itself. Use it only if your client can't compute SHA-256.
code_verifier appears here. code_challenge appears here. state appears here. nonce appears here. Paste a code_verifier above to validate it.
S256 challenge appears here.
Authorization request URL appears here. Token request (curl) appears here. Token request (raw HTTP) appears here.
PKCE (Proof Key for Code Exchange, pronounced "pixy", defined in
RFC 7636)
is an extension to the OAuth 2.0 authorization code flow that binds an
authorization code to the authorization request that produced it. The
client creates a fresh secret code_verifier for every flow and
must present it to redeem the code, so a stolen code can't be exchanged
for tokens, whether the attacker redeems it directly or injects it into
someone else's flow.
PKCE is often described as a fix for public clients, like SPAs and mobile apps, that can't keep a client secret. That's a misconception. RFC 7636 was written to stop a malicious native app from stealing and redeeming an authorization code, but shortly after it was published the authorization code injection attack was discovered, and that attack works against confidential clients too.
In a code injection attack, the attacker never needs to break the client's authentication. They start the code flow through the legitimate client application, then tamper with the front-channel redirect from the authorization server so it carries a stolen authorization code. The client redeems that code using its own valid credentials, and the attacker ends up with a session that holds the victim's authorization. Proxy tools such as the Zed Attack Proxy (ZAP) make this trivial.
PKCE defeats the attack: the stolen code is bound to the victim's
code_challenge, and the attacker's session holds a different
code_verifier, so the token endpoint rejects the exchange. That's
why the
OAuth 2.0 Security Best Current Practice (RFC 9700)
recommends PKCE for every client and OAuth 2.1 makes it a requirement
for the authorization code flow. If you use the authorization code flow
without PKCE, confidential client or not, you're vulnerable.
Always use PKCE.
With S256, the client sends code_challenge = BASE64URL(SHA256(code_verifier))
at the start of the flow, and sends the real code_verifier only at the
token exchange, so the verifier is never exposed on the
(less-protected) front channel. With plain, code_challenge is just
the verifier itself. Always use S256. (To check a base64url value by
hand, use the Base64URL decoder.)
code_verifier for this
authorization request and keeps it with the user's session. RFC 7636
requires 43-128 characters from an unreserved character set
(A-Z a-z 0-9 - . _ ~); 64 characters is a reasonable
default.code_challenge from it (S256) and sends it
with the authorization request.
code.code_verifier.
ASP.NET Core's OpenID Connect handler enables PKCE by default
(OpenIdConnectOptions.UsePkce = true). On the server side, Duende
IdentityServer lets you require it per client with
Client.RequirePkce (on by default for new clients): see
client configuration in IdentityServer.
Keep both turned on for confidential, server-side clients as well:
a client secret doesn't protect against code injection.
Computing the S256 challenge server-side in .NET 9+ is a few lines
with SHA256.HashData and the new
System.Buffers.Text.Base64Url type:
Csharp
using System.Security.Cryptography;
using System.Buffers.Text;
// code_verifier: any RFC 7636-compliant random string, 43-128 chars
var verifierBytes = RandomNumberGenerator.GetBytes(32);
var codeVerifier = Base64Url.EncodeToString(verifierBytes);
// code_challenge = BASE64URL(SHA256(code_verifier))
var challengeBytes = SHA256.HashData(Encoding.ASCII.GetBytes(codeVerifier));
var codeChallenge = Base64Url.EncodeToString(challengeBytes); Generate RFC 9562 v4 and v7 UUIDs/GUIDs in bulk, in any common format.
Encode and decode Base64, Base64URL and MIME-wrapped Base64, text or files.
Decode, inspect and verify JWTs with claim explanations, expiry checks and signature verification.
The OpenID Connect and OAuth 2.0 framework for ASP.NET Core, from the team that built this tool.