State vs nonce in auth0-js

I noticed that auth0js has a nonce parameter: Auth0.js v9 Reference , and was curious about the protection that offers vs the state parameter that is recommended to mitigate CSRF attacks (Auth0.js v9 Reference and https://auth0.com/docs/protocols/oauth2/oauth-state)? Why is state needed to prevent these attacks if we’re already using a nonce?

The nonce is required for the single-page login flow. As you noted, state is for CSRF prevention while nonce is to prevent replay attacks in the single-page login flow since unlike the other flows it can’t pass along the client secret.

I guess to rephrase my question (Why is state needed to prevent these attacks if we’re already using a nonce?), why can’t the nonce be used to provide CSRF protection in the context of a Single Page Application?

Relatedly, there seems to be some inconsistency between this page, which says that auth0-js handles state generation and validation automatically, and these docs, which seem to indicate that we should be providing state manually?

why can’t the nonce be used to provide CSRF protection in the context of a Single Page Application

Good question, and one I had to research further :slight_smile:

While both the nonce and state are generated by the client, one is used by the AS (Authorization Server–Auth0 in our case) and one by the client:

  • The nonce is used by the AS to prevent replay attacks. It tracks nonces and will reject a request that tries to reuse a nonce.
  • The state is used by the client to prevent CSRF of a callback by validating the state. The AS passes the state parameter through as received. The client keeps track of state to be able to validate it when it receives the callback.

Relatedly, there seems to be some inconsistency between this page , which says that auth0-js handles state generation and validation automatically, and these docs , which seem to indicate that we should be providing state manually?

Thanks, that is confusing. auth0.js does generate and validate the state automatically so the former doc is correct, however, the latter is unclear. I’ve submitted a PR for an update to the docs for the latter.

Thanks for following up, Chris! That’s interesting that the primary consumer of the nonce is the AS. If that’s its primary purpose, why does it get “included in the ID Token response from Auth0” back to the client (Mitigate Replay Attacks When Using the Implicit Flow)?

And thanks for taking the time to clarify the docs!