This is the problem you are trying to prevent by validating the token:
As a simplified example, imagine there are two apps: (1) FileStore, a
legitimate file storage app, and (2) EvilApp. Both apps use Google's
authentication process for client-side apps. Alice is an innocent end
user, and her Google user ID is XYZ.
- Alice signs into FileStore using Google.
- After the auth process, FileStore creates an account for Alice and associates it with Google user ID XYZ.
- Alice uploads some files to her FileStore account. So far everything is fine.
- Later, Alice signs into EvilApp, which offers games that look kind of fun.
- As a result, EvilApp gains an access token that is associated with Google user ID XYZ.
- The owner of EvilApp can now construct the redirect URI for FileStore, inserting the access token it was issued for Alice's Google
account.
- The attacker connects to FileStore, which will take the access token and check with Google to see what user it is for. Google will
say that it is user XYZ.
- FileStore will give the attacker access to Alice's files because the attacker has an access token for Google user XYZ.
FileStore's mistake was not verifying with Google that the access
token it was given was truly issued to FileStore; the token was really
issued to EvilApp.
I believe proper use of the OAuth "state" parameter can also prevent
this vulnerability. "Proper use" being cryptographically and securely
binding the state parameter value to the current browser session. This
can be done by hashing a combination of the session ID and a nonce
(I'm not sure if including the nonce is necessary).
I have two questions:
My primary question is: Can proper use of the OAuth "state" parameter,
along with using TLS with server certificate validation, mitigate the
confused deputy problem, without validating the audience of the access
token, for some definition of "proper use" that mitigates cross site
request forgery?
No, you need to validate audience
, not state, as per this article:
Some people believe that using the state parameter in OAuth protects
against token substitution. The only binding a browser cookie to state
protects against is Cross Site Scripting [think they mean CSRF]. In the attack I am
proposing the client generates a legitimate request to a bad user
agent that captures it and provides a response that includes state
unchanged from the request. Their is nothing in the OAuth client-side
flow that proves the issuer you sent the request to through the
browser ever received it and is the one responding. Only the
access_token parameter is generated by the Authorization server, all
the other parameters are dropped or echoed back. The client has no
way to tell who the authorization server thought it was issuing that
access_token to.
Imagine that an attacker clicks a button on your app in order to give it access to her Google account in order to validate her identity (i.e. authentication). However, instead of following the redirect she instead grabs the state value and stores it somewhere. She then gets a token from her malicious app, and then replays it to your redirect_uri
, substituting in the state
that she has captured herself.
Your app will then authenticate the user as the one that gave access to her malicious app. Validating the audience instead is the secure approach because this is checked by Google when you validate the token server-side.
My secondary question is: Is cross site request forgery a type of confused deputy problem? And if "yes", then isn't the answer to my primary question also "yes" necessarily?
Yes, CSRF is another type of confused deputy problem.
state
can be used for this, as this would validate that a malicious party has not enticed a user to their site and redirected them to your endpoint to authorise the attacker's account against your app. For example, if your app copies content from itself and syncs with a Google account, the attacker could redirect the user to your endpoint, you would then check server-side that the token matches, and then start syncing your content to the Google account - as this is the attacker's account, they have now gained access to your user's files. Hence why checking the state
is a good mitigation against this.