Over a million developers have joined DZone.

Google, OAuth, and the Confused Deputy – A Tale of Security

DZone's Guide to

Google, OAuth, and the Confused Deputy – A Tale of Security

· Integration Zone ·
Free Resource

It sounds like the title for a fantasy movie, but Google, OAuth and the “confused deputy” is a very common issue. Wikipedia defines a confused deputy as “a computer program that is innocently fooled by some other party into misusing its authority. It is a specific type of privilege escalation” (complete article here).

The Wikipedia article shares an example of a compiler exposed as a paid service. This compiler receives an input source code file and the path where the compiled binary is to be stored. This compiler also keeps a file called BILLING where billing information is updated each time a compilation is requested. If a user were to request a compilation setting the output path to “BILLING”, then the file would be overwritten and the billing information lost. In this case, the compiler is a “confused deputy” because although the client doesn’t have access to the file, it’s tricked the compiler (who does have access) into altering the file.

Applying the Concept to Google Authorization

In which situation could Google’s OAuth provider become a confused deputy? OAuth is an impersonation protocol. It allows an application to perform actions on behalf of a user who has authorized the application to do so, by consenting the application’s scopes and entering their credentials into a browser displaying a login hosted by the provider. In the case of Google, that login page supports having multiple users logged in at the same time, as shown in the screenshot below:

Here we see two of my accounts. So, imagine you’re doing a multi-tenant application that synchronizes your Salesforce contacts with your Google Contacts, moving valuable marketing information from one system to the other. Let’s call this application “The Contacts Avenger”. There’re two ways in which the above screen can lead you to a confused deputy:

  • You accidentally click on the wrong account. This has no major consequence other than the effort of cleaning up the information that ended up in the wrong account.
  • Someone physically or by other means takes control of your computer or your “Contacts Avenger” account, and by presses the “Add Account” button, thereby authenticated a third one which they use to steal your information. This just got serious! There’s somebody stealing the leads that took you so long to collect.

Mitigating the problem

Google is well aware of the problem. They say that you must validate the access token before using it to prevent the confused deputy from happening. What’s validating the token? Google’s OAuth provider has an endpoint that provides information about a given access token such as user id, email address, expiration time, etc.

So, if you’re making a multi-tenant application such as the “Contacts Avenger”, that means that the user probably has a registered account with you. Verifying that the access token you just obtained actually matches that account is a simple step you can take.

How Does Mule Help Solve the Problem

Our Google connector suite not only helps by making it easy to perform the whole OAuth authentication dance, it also helps you validate the access token. While authenticating, the connectors will validate the access token by requesting the user id and email associated with the obtained token. Those values are exposed through two flow variables called GOOGLE_USER_ID and GOOGLE_USER_EMAIL. You could then make sure that the obtained email matches the one you were expecting with a flow similar to this:

<google-contacts:config-with-oauth name="Google_Contacts" consumerKey="${consumerKey}" consumerSecret="${consumerSecret}">
  <google-contacts:oauth-callback-config domain="localhost" localPort="${https.port}" path="oauth2callback" connector-ref="https.connector" />

<objectstore:config name="tenantStore" partition="tenants" persistent="true" />
<flow name="authorize">
  <https:inbound-endpoint path="authorize" port="${https.port}" exchange-pattern="request-response" />
  <flow-ref name="loadTenantInformation" />
  <google-contacts:authorize config-ref="Google_Contacts" />
    <when expression="flowVars['GOOGLE_USER_EMAIL'] != flowVars['tenantInfo']['email']">
      <flow-ref name="rejectAndReportInvalidAuth" />
      <logger message="successfully authorized tenant" />

  <enricher target="#[flowVars['tenantInfo']]">
    <objectstore:retrieve config-ref="tenantStore" key="#[message.inboundProperties['cookies']['tenantId']]" />  

The above snippet shows a standard OAuth authorization flow which begins with a reference to a flow that loads tenant information (the example shows a mock implementation, in real life you’d have to take this from a persistent store). After performing the authorization, there’s a choice router which verifies that the authenticated account is the one actually expected. If that’s not the case, another flow with rejection and reporting logic is invoked.

Long Story Short

Remember that when authenticating through OAuth, it’s not you receiving and validating the user’s credentials. So no matter which API you’re using or if the API support multiple logins like Google does, you should always take measures against a confused deputy attack.

Do you know other API’s particularly vulnerable to this problem? If so, please do share!

Related posts:

  1. Introducing the Google Cloud Connectors Suite (Part 1/3)
  2. OAuth 2 just got a bit easier
  3. MS Office is so last year, Connect to Google Apps
  4. How to Protect Your APIs with OAuth

Build and deploy API integrations 7x faster. Try the Cloud Elements 100% RESTful platform for 30 days free. Access your trial here.


Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}