what is the case of replay attack for which OIDC nonce is a protection

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?

Upvotes: 3

Views: 893

Answers (1)

akdombrowski
akdombrowski

Reputation: 1140

TLDR;

nonce is 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 nonce parameter 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 nonce provides specifically for public clients, e.g., SPAs:

It is important to note that nonce does not protect authorization codes of public clients, as an attacker does not need to execute an authorization code injection attack. Instead, an attacker can directly call the token endpoint with the stolen authorization code.

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 nonce parameter doesn't provide protection for public clients, then what should I use? "

PKCE is the most obvious solution for OAuth clients as it is available today (originally intended for OAuth native apps) whereas nonce is appropriate for OpenID Connect clients.

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 nonce is and why PKCE can protect public clients while nonce cannot, 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_challenge and code_challenge_method (optionally) in PKCE. The OpenIdentity Provider (OP - the authorization server) stores the value(s) and returns the authorization code. However, what follows differs.

Using nonce:

  • The client sends the authorization code to the OP.
  • The OP puts the nonce received in the authorization request into the (ID) token and returns the token
  • The client checks the nonce value in the token with the value in session storage

Using PKCE:

  • The clients sends the authorization code AND the code_verifier to the OP
  • The OP checks the code_verifier by transforming it with the code_challenge_method and checking if it matches the code_challenge received previously.
  • The OP returns the token(s).

I bolded the steps where the "protection occurs" for each. Using nonce the burden is more on the client to verify the nonce value in the token matches what it created and stored earlier. With PKCE, the OP does the work with the code_verifier transformation and compares it to the earlier code_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 nonce parameter. It doesn't care. But, with PKCE, the malicious client needs to have the code_verifier or the OP will not return a token.

Upvotes: 5

Related Questions