I am setting up OAuth2 for Apple, and it requires a POST response to the callback URL if certain scopes (e.g. email address) are included.

My intended process for preventing CSRF:

  1. Set a cookie with a nonce.
  2. Redirect to the OAuth2 provider with state=<nonce>.
  3. OAuth2 provider redirects to callback with the nonce.
  4. Check cookie value against nonce.

The Problem

Both SameSite=Strict and SameSite=Lax block the cookie, so SameSite=None is the only configurable option. If I additionally verify the origin of POST callback request to be the Apple provider origin, would that be reasonable to prevent CSRF? What other attacks would circumvent this strategy?

1 Answer 1


You don't even really need to verify the origin of the callback (which, if it's done via the typical approach of redirection, you can't truly verify anyhow). The OAuth provider (Apple) will reflect the State parameter in its callback to you, but nobody else would know it. In other words, this is effectively already a "double-submit cookie" anti-CSRF pattern; the value is known only to you and the OAuth provider (who you trust, obviously; you're delegating auth to them). So long as the same value is present in the cookie and the state param (sent as either a URL parameter or - in this case, since it's POST - in the message body), you can be decently sure it's not a CSRF attack.

Now, to be clear, double-submit cookies are one of the weaker anti-CSRF approaches. If an attacker can ever plant or manipulate a cookie, then they can still carry out a CSRF attack by choosing the value of the cookie in question, getting an authorize code from the OAuth provider, and then redirecting your browser to the callback with a spoofed state matching the planted cookie. You can mitigate this by having HSTS enabled for your actual domain (the one that gets redirected to in particular, but due to the way cookies work it needs to be all your domains so usually you set it, with includeSubDomains, everywhere), as HSTS blocks the easiest way to plant a cookie, but sometimes other vulnerabilities make it possible too.

Note, of course, that the state value must be high-entropy (long and highly random; use a cryptographically secure random number generator). The whole protection breaks down if the attacker can compute or predict what state value another user will get!

Also, CSRF on OAuth generally only matters in two situations. One is login CSRF, which is so rarely given any attention that it's really only worth considering if you think there's substantial risk that a user who gets logged into an attacker's account would proceed to expose sensitive data to said attacker. The other is if the victim already has an account on your site that they authenticate to some other way (e.g. username + password), and is linking that account to an OAuth provider (Apple, Google, Facebook, etc.) account. If the first doesn't concern you and the second doesn't apply, then you can probably ignore the state parameter, at least for now.

In the second case from the paragraph above, you presumably already have some kind of random cookie or similar token (for the account that the user already has, which is being linked to the OAuth provider account). You can use that token, rather than adding another cookie, for OAuth CSRF protection. Make the state parameter be a cryptographically secure hash (something from the SHA2 or SHA3 families) digest of the cookie's random value. (If you want to be extra secure, use an HMAC with a key that is known only to the server, rather than just a hash.) Then an attacker can't tamper with the cookie without changing who your server thinks the victim is, and therefore the attacker can't link their OAuth account to a victim's account on your site.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .