The client MUST implement CSRF protection [...] typically accomplished by requiring any request sent to the redirection URI endpoint to include a value that binds the request to the user-agent's authenticated state (e.g. a hash of the session cookie [...]
It doesn't say much about the implementation, though. It only puts some light on how the CSRF works:
A CSRF attack against the client's redirection URI allows an attacker to inject their own authorization code or access token, which can result in the client using an access token associated with the attacker's protected resources rather than the victim's (e.g. save the victim's bank account information to a protected resource controlled by the attacker)
But use of the word "rather" rather makes the statement worthless.
I am thinking how to implement the "state" in GAE (using Webapp2). It would be easiest starting at how a hacker could use a CSRF against OAuth2. I found only one good article about the matter: "Cross Site Request Forgery and OAuth2".
Unfortunately, while this blog post is well written, there's not much information beyond explaining the OAuth2. The examples don't work, and I don't know Spring. Still, I found one interesting recommendation there: the server connecting to an OAuth2 provider should store "state" as a random session key (e.g. "this_is_the_random_state":"this_doesn't_matter"), and not a value under a static key (e.g. "state":"random_state_string").
My question is, what's the sane implementation of the "state"?
- Should the randomly generated state be hashed, or can the same value be stored and sent to the OAuth2 provider?
- Is there a difference here if the session backend is secure cookies or a server-side storage technology (e.g. in GAE Memcache, or database)?
- Should state be stored as a key as suggested?
- Should state has validity period, or is session (if there is one) lifetime enough?