In the context of user authentication using OIDC/OAuth 2 with Authorization Code + PKCE in a web-based Single Page Application (SPA), a nonce parameter can be generated and sent to the identity provider to mitigate replay attacks.
https://oa.dnc.global/-OpenID-Connect-Autorisation-via-un-code-Authorization-Code-Flow-.html
While the nonce parameter is mandatory for the now-obsolete implicit flow, it's optional for the authorization code flow.
What are the potential attack vectors if the nonce parameter is not used?
The SPA can validate that the ID token is invalid if the nonce claim in the JWT doesn't match, but when an attacker can send a valid but stolen ID token to the SPA?
TLDR;
nonceis meant to provide protection against authorization code injection attacks, BUT it doesn't provide this protection in the case of public clients, e.g., SPA's.For an explanation of what protection the
nonceparameter provides, have a look here:https://datatracker.ietf.org/doc/html/draft-ietf-oauth-security-topics#nonce_as_injection_protection
The last paragraph addresses your question with regard to what protection
nonceprovides specifically for public clients, e.g., SPAs:https://datatracker.ietf.org/doc/html/draft-ietf-oauth-security-topics#section-4.5.3.2-4
The following section then addresses the next concern, i.e., "If the
nonceparameter doesn't provide protection for public clients, then what should I use? "https://datatracker.ietf.org/doc/html/draft-ietf-oauth-security-topics#section-4.5.3.3-2
Now, if you're asking what the difference between PKCE and
nonceis and why PKCE can protect public clients whilenoncecannot, the difference is the different steps of the OAuth/OIDC flow where they come into play.The nonce is generated by the client and sent in with the authorization request similar to how the
code_challengeandcode_challenge_method(optionally) in PKCE. The OP stores the value(s) and returns theauthorization code. However, what follows differs.Using
nonce:authorization codeto the OP.noncereceived in the authorization request into the (ID) token and returns the tokennoncevalue in the token with the value in session storageUsing PKCE:
authorization codeAND thecode_verifierto the OPcode_verifierby transforming it with thecode_challenge_methodand checking if it matches thecode_challengereceived previously.I bolded the steps where the "protection occurs" for each. Using
noncethe burden is more on the client to verify thenoncevalue in the token matches what it created and stored earlier. With PKCE, the OP does the work with thecode_verifiertransformation and compares it to the earliercode_challenge.If a malicious client is able to steal the authorization code, there is no protection against that client getting a token and using it. It doesn't have to check the
nonceparameter. It doesn't care. But, with PKCE, the malicious client needs to have thecode_verifieror the OP will not return a token.