State vs Nonce vs PKCE: What Is a Nonce in Security?

Guilliano MolaireGuilliano Molaire10 min read

A nonce is a value used once within a particular security context, often described as a “number used once.” Protocols use it to distinguish a current exchange from a replay of an earlier one. Depending on the protocol, it can be random or a non-repeating counter. NIST’s nonce glossary covers both forms.

In OpenID Connect (OIDC), the identity layer built on OAuth, your application sends an unguessable nonce and checks that the returned ID token, a signed statement about the login, contains the same value. That binds the token to the login request and helps detect replay. OpenID Connect Core’s ID token validation rules say that if a nonce was sent in the authentication request, a nonce claim must be present in the ID token and checked against the value that was sent.

We will follow that value through a Keycloak login, alongside state and Proof Key for Code Exchange (PKCE). If you need the broader flow first, start with our OAuth developer guide and OpenID Connect explanation.

Key Takeaways

  • A nonce is a value used once in its security context. NIST includes random values and counters.
  • state binds the callback to the browser session.
  • An OIDC nonce binds the ID token to the pending login.
  • PKCE requires the verifier to redeem the authorization code.

What makes a nonce useful in security?

A nonce only helps when the receiving system checks it in the right context. A random value attached to a message does not prove freshness by itself. The receiver needs a rule for recognizing an expected value or rejecting one already used. NIST describes nonces as protocol inputs that help distinguish live data from replayed data.

For a login nonce, you need properties that work together:

  • Freshness: Generate a new value for each login attempt, rather than assigning one permanent value to a user.
  • Unpredictability: An attacker should not be able to guess the value for another login.
  • Transaction binding: Keep the expected value with the pending login in the browser session or backend session that started it.
  • Consumption: Expire pending attempts and prevent a completed attempt from being accepted again.

OIDC’s nonce implementation notes say the nonce value needs to include per-session state and be unguessable to attackers. For web server clients, they describe one method: store a cryptographically random value in an HttpOnly session cookie and use its cryptographic hash as the nonce. OAuth Security Best Current Practice describes the nonce as a one-time value created by the client, which the client is supposed to bind to the user agent session.

A nonce is not necessarily secret. The OIDC nonce travels in the authorization request. Its usefulness comes from being unpredictable before that request and checked against the correct pending login, rather than from staying hidden forever. For a separate comparison of credential choices, see our API keys versus OAuth guide.

How do TLS, CSP and Bitcoin use nonces?

When you encounter the word in another protocol, check that protocol’s generation and validation rules before applying the login guidance here.

Context What the value does What you should understand
Transport Layer Security (TLS), which secures HTTPS connections The ClientHello and ServerHello each carry a 32-byte value from a secure random number generator, and the server’s must be generated independently of the client’s. Keep these handshake values separate from the OIDC nonce you validate in your application.
Content Security Policy (CSP), a browser policy controlling permitted resources A random value in the policy, which MDN says must be unique for each HTTP request, and the same nonce goes in the script element’s nonce attribute. Generate it anew for each response; the matching nonce allows the script.
Bitcoin mining The block header reference describes an arbitrary number miners change to modify the header hash until it is at or below the target threshold. Follow the mining protocol’s rules for this field; use OIDC’s nonce rules for a login.

This is also the answer when you encounter “nonce in crypto”: identify the protocol before choosing how to generate or validate it. For the browser policy case, see our Keycloak login CSP guide.

What is the difference between state, nonce and PKCE?

state correlates the redirect callback, nonce binds the ID token to the login attempt, and PKCE binds code redemption to the client that started the exchange. You check them at different points.

Mechanism Sent at authorization Checked where Main protection
state A value bound to the application’s pending browser login The application compares the returned callback value with its stored value Cross-site request forgery (CSRF), where an attacker causes an unwanted login callback. OAuth’s CSRF section says the client should use state to deliver a value that binds the request to the user agent’s authenticated state.
nonce An unguessable value The application checks the ID token’s nonce against the pending login Token replay and injection into the wrong login transaction. See OIDC ID token validation.
PKCE A code_challenge derived from a private code_verifier The authorization server checks the verifier during code redemption Redemption of intercepted authorization codes without the verifier. See PKCE specification.

These protections overlap. OAuth Security Best Current Practice says clients that have ensured the authorization server supports PKCE may rely on the CSRF protection PKCE provides, that the nonce parameter provides CSRF protection in OpenID Connect flows, and that otherwise one-time CSRF tokens in state must be used. For the login we build here, keep explicit state and nonce checks alongside PKCE so the checks remain visible.

Nonce cannot stop someone redeeming a stolen public client’s code directly at the token endpoint. PKCE addresses that problem, and it also helps prevent code injection. The security guidance distinguishes these attacks. For mobile clients, see our mobile OAuth guide.

Follow the values through a Keycloak login

Use an OIDC library to manage the transaction. The following examples expose the values so you can review a library’s behavior; they are not a complete login implementation. The authorization-code exchange is defined in OAuth’s authorization code flow.

Create and store a pending attempt

Generate independent values for state, nonce and the verifier. In browser JavaScript, crypto.getRandomValues supplies cryptographically strong random bytes. This example uses the PKCE specification’s recommended 32 random bytes for the verifier, and chooses the same size for state and nonce.

function randomValue() {
  const bytes = crypto.getRandomValues(new Uint8Array(32));
  return btoa(String.fromCharCode(...bytes))
    .replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
}

const state = randomValue();
const nonce = randomValue();
const codeVerifier = randomValue();

Store them together as one pending attempt through your library’s transaction storage. Keep a separate record for each concurrent login attempt and look it up using that attempt’s state value. Also record the expected issuer, client identifier and redirect URI rather than taking them from an incoming callback.

Send the authorization request

For PKCE’s S256 method, compute the challenge as the base64url encoding of the verifier’s SHA-256 digest, without padding. The PKCE challenge definition specifies that transformation. The verifier stays with the application until the token request.

This illustrative Keycloak request is wrapped for readability; the capitalized values stand for generated transaction values:

https://identity.example.com/realms/demo/protocol/openid-connect/auth
  ?client_id=web-app
  &response_type=code
  &scope=openid
  &redirect_uri=https%3A%2F%2Fapp.example.com%2Fcallback
  &state=STATE
  &nonce=NONCE
  &code_challenge=CHALLENGE
  &code_challenge_method=S256

Keycloak’s OIDC endpoint documentation documents this authorization endpoint. The openid scope requests OIDC authentication.

Check the callback and redeem the code

When the browser returns, match state against the pending attempt before processing the code. Reject missing, mismatched or already consumed attempts. The OAuth authorization response rules list state as required in the response if it was present in the request, carrying the exact value received from the client.

Then exchange the code at the token endpoint, supplying the stored redirect URI and verifier. OAuth’s token request rules require the redirect URI to match the authorization request and require confidential clients to authenticate. The PKCE token request adds code_verifier to the authorization-code request.

How do you validate the nonce in an ID token?

Compare the ID token’s nonce claim with the value stored before the redirect. Reject a missing or different value. Also validate the token’s signature, expected issuer, audience, expiry and any applicable additional OIDC requirements through your library. A decoded token is only readable data until validated. Follow OpenID Connect Core’s validation rules; the OpenID Foundation’s basic client guide provides additional implementation guidance.

This isolated check assumes the library has already authenticated the ID token and validated its other claims:

function assertNonce(validatedClaims, expectedNonce) {
  if (typeof expectedNonce !== "string" || expectedNonce.length === 0) {
    throw new Error("No pending login nonce");
  }
  if (typeof validatedClaims.nonce !== "string" ||
      validatedClaims.nonce !== expectedNonce) {
    throw new Error("ID token nonce mismatch");
  }
}

Do not establish the application session or use returned tokens until the checks succeed. Consume the transaction so a second callback cannot reuse it. OAuth’s nonce countermeasure says a client using the nonce against code injection must validate the nonce in the ID token obtained from the token endpoint, and must disregard all tokens unless and until that check succeeds.

Check the ID token, rather than expecting an API’s access token to carry this login binding. For the token comparison, see our ID token versus access token guide. For API validation, see verifying a Keycloak access token on the backend.

Identity you do not have to patch yourself

Skycloak is a managed identity platform for SSO, MFA, SCIM and audit logs. When an advisory lands, the fix is ours to ship: Keycloak 26.7.2 closed an account takeover through password reset and customers had it the same day upstream published it.

How do you require PKCE in Keycloak?

Set the client’s required PKCE method to S256. The Keycloak administration guide’s PKCE method setting says that with the setting blank, Keycloak does not apply PKCE unless the client sends the PKCE parameters, so PKCE stays possible but is not required, while S256 applies PKCE with that challenge method to the client.

These console instructions follow the Keycloak 26.8.1 administration guide, which documents the setting, labelled PKCE method, in the client’s Capability Config section. They were checked against the documentation, not a running console:

  1. Select your realm, open Clients, and select the OIDC client.
  2. Enable Standard Flow for authorization-code login and configure the intended redirect URI.
  3. Under Settings, Capability config, set PKCE method to S256 and save.

Our PKCE client setup guide shows the same setting as Proof Key for Code Exchange Code Challenge Method under Advanced settings on the client’s Advanced tab, so check there if your console does not show it in Capability config.

Our Auth0 migration guide’s client creation example uses the client attribute pkce.code.challenge.method. This client representation fragment shows the underlying setting, not a complete client update:

{
  "attributes": {
    "pkce.code.challenge.method": "S256"
  }
}

For browser applications using keycloak-js, the adapter reference’s init method options list useNonce with a default of true and pkceMethod with "S256" as the default. Check that your init options have not set useNonce to false or pkceMethod to false.

OpenID Connect Core says the nonce claim is passed through unmodified from the authentication request to the ID token, and the keycloak-js reference describes useNonce as adding a cryptographic nonce to verify that the authentication response matches the request. Those are separate responsibilities: a server-side PKCE setting cannot make another application’s nonce validation correct.

Verify the failure cases before shipping

Use a test realm and client to check that invalid transactions fail, not just that valid logins succeed. Treat this as a review checklist for your integration:

  • Change or omit callback state and confirm that your application rejects the callback.
  • Supply validated test claims with a missing or different nonce and confirm that your nonce check rejects them.
  • Repeat a completed callback and confirm that the application cannot reuse its transaction.
  • Omit the PKCE challenge from a fresh authorization request and confirm that the configured client rejects it.
  • Redeem a fresh code with the wrong verifier and confirm that no tokens are issued.

For issuer selection, see our MCP OAuth issuer-pinning analysis. Also see our Better Auth OAuth and magic-link analysis and AgentCore Identity versus Keycloak guide.

Frequently asked questions

Is a nonce always random?

No. NIST’s definition includes non-repeating values such as sequence numbers. An OIDC login nonce needs unpredictability, so a predictable counter is not an appropriate substitute there.

Does a nonce replace state or PKCE?

It does not replace PKCE’s protection against direct redemption of a stolen public-client code. Some CSRF defenses overlap, but each check has conditions. Follow your library’s documented flow and the OAuth security guidance before removing a protection.

Why does the nonce match but login still fail?

A matching nonce is only one check. An expired ID token, wrong issuer, wrong audience or invalid signature can still make the login fail. Follow the validation error instead of disabling nonce checks, and refer to our OIDC guide.

Sources and version context

Sources retrieved on 2026-10-17:

Review your next login transaction

Trace state from request to callback, nonce from request to ID token, and the PKCE verifier from transaction storage to code redemption. You can inspect a test ID token’s nonce with our JWT Token Analyzer, while keeping the actual validation in your application.

We run managed Keycloak at Skycloak, so you can configure the server’s PKCE requirement without operating the underlying cluster yourself. For the broader login setup, see our single sign-on feature. Your application still owns its callback and ID token checks. If you want managed hosting for that setup, compare Skycloak plans.

Identity you do not have to patch yourself

Skycloak is a managed identity platform for SSO, MFA, SCIM and audit logs. When an advisory lands, the fix is ours to ship: Keycloak 26.7.2 closed an account takeover through password reset and customers had it the same day upstream published it.

Guilliano Molaire
Written by
Founder, Skycloak

Guilliano is the founder of Skycloak and a cloud infrastructure specialist with deep expertise in product development and scaling SaaS products. He discovered Keycloak while consulting on enterprise IAM and built Skycloak to make managed Keycloak accessible to teams of every size.

© 2026 Skycloak. All Rights Reserved. Design by Yasser SolimanKeycloak™ is a trademark of the Linux Foundation. Skycloak is not affiliated with the Keycloak project.