24

Between access tokens, refresh tokens, scopes, audiences, and client IDs, I was confused when the Google OAuth documentation instructed me to validate all tokens in order to prevent the confused deputy problem. The Wikipedia article linked to only describes the general problem at a high level, not specific to OAuth or even network authentication. If I understand it correctly, token validation is not even part of OAuth2 but actually depends on the specific implementation. So here is my question:

How and why is Google OAuth token validation performed?

A concrete example of the confused deputy problem in this context would be especially appreciated. Also note that I ask this in the context of entirely client-side apps, if that makes a difference.

Jakob
  • 2,588
  • 5
  • 27
  • 34

2 Answers2

48

Google is referring specifically to the access token.

In the context of OAuth 2.0, the confused deputy problem applies to the Implicit Grant protocol flow when used for authentication. What Google calls "OAuth 2.0 for Client-side Applications" is based on the implicit grant protocol flow.

Since the implicit flow exposes the access token to the end user through the URI fragment, it introduces the possiblity that the access token might be tampered with. A legitimate app (an OAuth client) can become the confused deputy by accepting an access token that was issued to a different (malicious) app, thereby giving an attacker access to a victim's account.

The critical step in validating the access token is that the app verifies that the access token was not originally issued to a different app. Google calls attention to this when they say:

Note: When verifying a token, it is critical to ensure the audience field in the response exactly matches your client_id registered in the APIs Console. This is the mitigation for the confused deputy issue, and it is absolutely vital to perform this step.

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.

  1. Alice signs into FileStore using Google.
  2. After the auth process, FileStore creates an account for Alice and associates it with Google user ID XYZ.
  3. Alice uploads some files to her FileStore account. So far everything is fine.
  4. Later, Alice signs into EvilApp, which offers games that look kind of fun.
  5. As a result, EvilApp gains an access token that is associated with Google user ID XYZ.
  6. The owner of EvilApp can now construct the redirect URI for FileStore, inserting the access token it was issued for Alice's Google account.
  7. 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.
  8. 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.

Others have described this much more elegantly than I:

I hope this explains the why part of access token validation with client-side apps, and how it relates to the confused deputy problem.

Community
  • 1
  • 1
Andre D
  • 4,585
  • 1
  • 19
  • 26
  • 2
    I think that makes sense. Here's my understanding of it: The Google server can be sure which user the token was issued to, so that part is fine. However, the client cannot (without token validation) be sure which client the token was issued to. In other words, it's the client that gets confused. Is that correct? – Jakob Jul 03 '13 at 21:41
  • 1
    explained in very simple terms. thanks. wish everyone provided such examples! – arajashe Mar 07 '14 at 13:14
  • Could you explain why there is two tokens? An "access_token" and an "id_token"? Surely one would suffice https://developers.google.com/+/web/signin/server-side-flow – samthebest Dec 14 '14 at 18:43
  • 1
    @samthebest I suspect the id_token you're referring to is actually an OpenID Connect id_token. You can extract from it information about the user. http://openid.net/specs/openid-connect-core-1_0.html#TokenResponse – Andre D Dec 16 '14 at 02:19
  • 1
    It seems to me that a malicious client could obtain a token by using the client-ID of another application (client-IDs are not secrets) – The Tahaan Oct 13 '16 at 06:43
  • @TheTahaan I don't understand what your point is. You are correct that Client IDs are not secrets, but OAuth doesn't treat them like secrets. A malicious client cannot obtain an access token meant for another client unless it can inject its own redirect URI in the authorization process; that's a different problem. – Andre D Oct 13 '16 at 20:35
  • @andre Without CSRF: Malicious app entice innocent user to log in with FB to share cat pictures. User select Login with FB. Malicious App uses Client-ID harvested from GoodApp in subsequent Auth process. Malicious app receive Access Token valid for Good Client. Malicious app sends a copy of the Token to Owner_of_malicious_app and continues. This is for implicit grant. The window of opportunity with other flows are much smaller because the Authorisation token is single-use. Owner_of_malicious_app now have a token which can be used to impersonate Innocent user on GoodApp. – The Tahaan Oct 14 '16 at 05:31
  • The problem is not that OAuth is Authorization vs Authentication. The problem is that the AZP / IDP doesn't establish a call back to RP in the back-end as part of the dance. I assume this decision was taken for the same reason why FB and OpenID Connect signs ID-tokens - to save the cost of a call from RP-to-AZP. – The Tahaan Oct 14 '16 at 05:33
  • @TheTahaan The part where you say "Malicious app receive Access Token valid for Good Client" will not work. – Andre D Oct 14 '16 at 06:20
  • You're wrong. It is trivial to write a client and insert the App ID and Client ID from another app. – The Tahaan Oct 14 '16 at 08:12
  • @TheTahaan Please re-read my original reply to you and RFC 6749 Section 4.2.1. It does not matter if you try to use someone else's client ID, you will never receive an access token because the redirection URI will not match. – Andre D Oct 14 '16 at 08:29
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/125680/discussion-between-the-tahaan-and-andre-d). – The Tahaan Oct 14 '16 at 08:53
  • 1
    @TheTahaan Did you and Andre D ever settle this discussion in the chat? I'm extremely interested in the conclusion since I (like you) believe that client IDs can be easily spoofed by malicious apps. I don't see how the redirect URI can help in the case of a native mobile app (as opposed to a web app) - it's not as if Facebook will send the access token directly to "good" app via the redirect URI, is it? Rather, as I understand it, the malicious app will receive the redirect request along with the access token. – YSK Apr 18 '17 at 18:27
  • @YSK The salient points are captured in my comments above, especially regarding the redirection URI. Now for your query, remember that we are discussing the implicit flow here, and native mobile apps are somewhat special. You should read the [native apps draft](https://tools.ietf.org/html/draft-ietf-oauth-native-apps-09), especially sections 8.4 and 8.5: _"...the use of the Implicit Flow with native apps is NOT RECOMMENDED."_ – Andre D Apr 19 '17 at 01:36
3

How are you using OAuth2? Do you obtain an authorization code and exchange for refresh token? Or are you obtaining access tokens directly via your frontend?

If you're receiving an authorization code, you're done, as the check for client_secret performed by Google in the backend guarantees that all tokens returned in exchange for the authorization code were issued for your application.

If you're receiving an access_token+id_token through frontend, then you should validate the id_token signature using the recommended libraries, then validate that the 'aud' field in the id_token matches the one you registered for your application w/ Google. For complete security, also cross-validate the access_token with the id_token (the id_token includes a truncated hash of the access_token as filed 'at_hash'), as documented in: https://developers.google.com/accounts/docs/OAuth2Login

breno
  • 3,226
  • 1
  • 22
  • 13
  • 1
    Could you also explain the confused deputy problem in this context? That's the most confusing part. – Jakob Jun 23 '13 at 00:48
  • 1
    Confused deputy hear means that you need to check that the token was issued to your application; not only the user it was issued to. Otherwise, if your users authorize another app (EvilApp), the tokens that EvilApp obtained can be used to 'authenticate' users to your application. – breno Aug 14 '13 at 02:52