I work for a web company that's undergoing a massive rewrite in order to separate our Data out into its own RESTful service application - the goal is to be able to sell access to third parties and quickly prototype internal applications without needing direct access to the DB.

We currently have three Applications - The aforementioned Data API, a CMS, and a Front-end. Users need to be able to log in to the CMS to modify Data through the API, and we'd really like to integrate our Google Web Apps into this - logging in Via Google. Ideally, this would use the OAuth flow, because it's the most transparent to our users - but I'm unaware of any way to share the OAuth information between applications without possibly compromising their security.

What I've tried

Concretely? Nothing. My initial proposal was to generate what is essentially "Nested OAuth" - set my Data Application as an OAuth Provider for all other applications, then use the Google OAuth flow as the unspecified Authentication standard within the Data Layer - it's an entirely Restful API, so it would be pretty much transparent to the user, but it seems to violate the concept of OAuth, and I feel like there should be a better way to do it. The flow would look like this:

  1. User Requests Login for the CMS
  2. CMS gains an Auth Token from the Data Layer
  3. CMS Redirects the User to Login page hosted at the Data Layer
  4. Data Layer Gains an Auth Token from Google
  5. Data Layer redirects the User to Google Login Page
  6. Google Authenticates the User, then redirects the User back to the Data Layer with an Auth token
  7. Data Layer uses Auth Token to get Access Token for Google Services
  8. Data Layer redirects User back to the CMS with another Auth Token
  9. Auth Layer uses Auth Token to get an access token for Data Services

But it seems, well, clunky. I'd also like to not have to force the user through mutiple "Allow" pages - one from Google to allow the Data Layer, and One from The Data Layer to allow the CMS (or some later application) to access. What I really need is to use Google for a SSO or Kerberos situation, and have Google give out tickets for my applications. If anyone knows a way to leverage that with Google, I'd gladly trash this whole design.

  • How much trust is there between your three applications? If the front-end implicitly trusts the data layer, then it can collect the user's auth token itself, and pass this to the data layer. If there's less trust than this, then having the complete a separate OAuth login with each site is a prudent approach. I don't see that "nested OAuth" gains you anything. – paj28 Nov 11 '13 at 16:07
  • Well, becoming our own OAuth provider gives us the ability to bring in third party applications at a much lower level of trust - we don't have to feed them secrets or give them unfettered access to our data, and we can ensure they're making changes on behalf of a specific user. Using Google as an Identity provider offloads the need to write an authentication stack, while giving our users access to a much higher security standard (Two factor auth, etc) and a suite of tools we don't need to build (Forgot your password, Register new user, etc). – FrankieTheKneeMan Nov 11 '13 at 16:11
  • Additionally, in order to share Auth tokens between the front-end and the data layer, they also have to share a secret with Google, which (I feel) undermines the standard. – FrankieTheKneeMan Nov 11 '13 at 16:14

After a lot of research, I've discovered that Google has an Unsecured Access Token verifier - https://developers.google.com/accounts/docs/OAuth2UserAgent#validatetoken which can be used to verify

  1. What application the Token was issued to
  2. Which email address the token was issued on behalf of.

By keeping track of the application's Google Identifier, The data layer can accept an Access Token and verify it to authenticate the user and the application, with a little help from a standard API Signature scheme involving a secret known only to the Data Layer and the accessing application. This requires no trust, as each application that needs information from the Data Layer can register itself with Google oAuth, and without the secret shared between them, the Data API cannot use the access token on the users behalf. This does preclude the Data Layer from accessing Google APIs on the user's behalf, but a separate oAuth specifically for the Data API can be implemented to get access to the user's resources.

  • Oh cool, glad you got something sorted. I don't think this is how that verifier is supposed to be used, but if this hack suits you better than your original, all good. – paj28 Nov 12 '13 at 20:27
  • Check out this sample request Since it returns JSON, One can use the "issued to" or "audience" fields to verify the application (which has Identified itself with a signature) against known applicaitons, and the email against known users. We're using user email as a unique identifier per user anyway. If the "issued-to" field matches the signature in the request, we can authenticate the application. Google has already authenticated the user, so all three parties are verified. – FrankieTheKneeMan Nov 12 '13 at 21:24
  • @paj28 It doesn't take care of authorization, necessarily, but our user base is captive (employees of the company), and they can be told that providing a Known application with their google account automatically authorizes that application to use their Data on our network. We're a pop news website, not a bank, so that's secure enough for our current purposes. – FrankieTheKneeMan Nov 12 '13 at 21:26

I think the solution you propose is the best you are going to find.

Lets recap your problem to check I understand correctly. You have a "Data Layer" which stores data owned by users. Users are authenticated using Google's OAuth endpoint. You also have a number of "Front end" apps that can access the data layer, but are not implicitly trusted. The behaviour you want is that if User A approves "Front end app A" then that app can access data belonging to User A in the data layer, but not data belonging to other users.

To support this design, every user will have to explicitly approve every front-end app that they use - although they will only have to do this once. This is inherent in the design. The question is whether users authenticate to front-end apps using Google directly, or using an OAuth provider in the data layer.

If they used Google directly, then the front-end app would know the user's identity. However, the front-end app would not be able to securely prove to the data layer that it knew the user's identity. OAuth does not support this, and there is a good reason. In this setup, at what point does the user agree to allow "Front-end app A" to access the data layer? There is no ability for your data layer to add a capability to Google's OAuth endpoint.

With the "nested OAuth" setup you suggest, the user does see such a message. And when they approve it, the front-end app can securely prove to the data layer that the user has approved the app.

Between the front-end and the data layer, you are using OAuth as it was originally intended - granting external applications some privileges to your data on a website. Between the data layer and Google you are using OAuth for authentication, which is a slightly different use case.

Incidentally, you mention Kerberos, but this has exactly the same problem. In a Kerberos environment, you can identify yourself to the mail server, and to the file server, but the mail server cannot then authenticate to the file server on your behalf.

Your Answer

