Difference between OAuth 2.0 "state" and OpenID "nonce" parameter? Why state could not be reused?

56,745

Solution 1

State and nonce seem to be similar. But if you dig deep, you will find that they serve different purposes.

State is there to protect the end user from cross site request forgery(CSRF) attacks. It is introduced from OAuth 2.0 protocol RFC6749. Protocol states that,

Once authorization has been obtained from the end-user, the authorization server redirects the end-user's user-agent back to the client with the required binding value contained in the "state" parameter. The binding value enables the client to verify the validity of the request by matching the binding value to the user-agent's authenticated state

And this is used in authorization request. It enables the client to validate that the authorization response is not altered and sent by the original server which auth. request was sent. In short, it allows the client to cross check the authorization request and response.

(More elaboration : To accept authorization code response, client need to accept a response from authorization server (ex:- In web app, this can be done by a redirect and a form post to back-end). This means, our client application have an endpoint which is open and accept requests. State parameter protect this endpoint by binding original authorization requests to responses. This is CSRF protection.)

Nonce serves a different purpose. It binds the tokens with the client. It serves as a token validation parameter and is introduced from OpenID Connect specification.

nonce - String value used to associate a Client session with an ID Token, and to mitigate replay attacks. The value is passed through unmodified from the Authentication Request to the ID Token. If present in the ID Token, Clients MUST verify that the nonce Claim Value is equal to the value of the nonce parameter sent in the Authentication Request. If present in the Authentication Request, Authorization Servers MUST include a nonce Claim in the ID Token with the Claim Value being the nonce value sent in the Authentication Request. Authorization Servers SHOULD perform no other processing on nonce values used. The nonce value is a case sensitive string

As you can see, nonce value originates from the authorization request and it is generated by the client. And if nonce is included, it will be present in the token. So the client can validate the token it received against the initial authorization request, thus ensuring the validity of the token.

Also, depending on the flow type, nonce can be a mandatory parameter. The implicit flow and hybrid flow mandate nonce value. Both values are generated and validated by client application.

Why state could not be reused?

If an authorization request is captured, then the malicious party can fake the authorization response. This can be avoided by altering state parameter.

Solution 2

Nonce answers the question to the browser: Is this ID token a response to my initial request?

State answers to the backend server: did the consent really come from who I think it did?

So they answer similar questions but to different entities.

Solution 3

I am stating an explanation from their RFCs. The explanation is pretty straightforward.

State

An opaque value used by the client to maintain state between the request and callback. The authorization server includes this value when redirecting the user-agent back to the client. The parameter SHOULD be used for preventing cross-site request forgery

Nonce

The nonce parameter value needs to include per-session state and be unguessable to attackers. One method to achieve this for Web Server Clients is to store a cryptographically random value as an HttpOnly session cookie and use a cryptographic hash of the value as the nonce parameter. In that case, the nonce in the returned ID Token is compared to the hash of the session cookie to detect ID Token replay by third parties. A related method applicable to JavaScript Clients is to store the cryptographically random value in HTML5 local storage and use a cryptographic hash of this value.

Reference Link: State: https://datatracker.ietf.org/doc/html/rfc6749

Nonce:https://openid.net/specs/openid-connect-core-1_0-17_orig.html

Hope this answers your question.

Solution 4

Adding to the above answers which focus on the security aspect of state and nonce, if you're implementing your own 3-legged OAuth2 workflow (client, your middleware and a Federated Identity Provider such as Facebook), your middleware might sometimes need some context. For example, when the response from the FIP reaches back to your middleware before going back to your client, you may need to know more about the details of the original request (i.e., the original request to the FIP). Because your middleware is most likely stateless, it won't be able to answer that question without any help. That's where the OAuth2 state variable comes in. You could store any string that represents the state you want to pass between all the OAuth2 jumps so that your middleware (as well as your client) can use some more context. In the case of your client, this is used for security reason. The nonce is used as part of the OIDC specification for pure security reasons.

Share:
56,745
dvsakgec
Author by

dvsakgec

Currently working as SEM in retail e-commerce company leading engineering of customer management and product information management areas Working as full Web Stack developer in IDM domain, with previous experience in Mobility and Finance domain. My interest areas are OAuth/OPenID, NoR(Not Relational) DBs, Federation, Machine learning and virtually anything which appears interesting

Updated on October 04, 2021

Comments

  • dvsakgec
    dvsakgec over 2 years

    OAuth 2.0 defines "state" parameter to be sent in request by client to prevent cross-site request attacks. Same is mentioned in OpenID spec for "nonce". Apart from the fact that "nonce" is returned in ID token instead of query parameters, they appear to serve the exact same purpose. If someone can explain why they are separate