daydreamer
daydreamer

Reputation: 91959

Do I not need to secure my API endpoints (resources) with OAuth 2 access tokens?

There are multiple partied involved in OAuth2 conversation. Consider the following diagram from the article here

enter image description here

Consider that I have an application that has data for restaurants and has APIs related to it. Let's call is restaurants APIs. Let us assign some role to each party in context of this example

User - our chefs, who have some recipes in restaurant

Application - Web client written in HTML5, JS, CSS that our Users use to interact with APIs

OAuth Endpoint - Google (who acts as Authorization Server)

API - My application API keeping all data for chefs  

The workflow for Implicit (as per above diagram in the link) states the Application gets the access token and then the Application(browser) calls API (my application with chefs recipes) and gets the data back.

Questions

Looking forward to your ideas here.
Thanks in advance

Upvotes: 0

Views: 238

Answers (1)

YSK
YSK

Reputation: 1614

TL;DR - don't blindly trust the access tokens. Ask Google to reveal the user/email associated with them and the client ID that was used when generating them. You can still provide a /login endpoint for scalability purposes mostly.

Let's deal with the core security first

OAuth is a delegation protocol, not an authentication protocol. To quote from the OAuth website:

The OAuth 2.0 specification defines a delegation protocol [...] OAuth is used in a wide variety of applications, including providing mechanisms for user authentication. [...] Let's say that again, to be clear:

OAuth 2.0 is not an authentication protocol.

Because it's not an authentication protocol, your app/API never learns who the user is. It just gets a token. Delegation in this context means that OAuth lets App A request access to resources in App B that belong to a User, by having the User authenticate to App B and then passing the token back to App A. In your example, it can provide your web app with access to Google resources (email, photos, etc. - depending on the required scopes) that are owned by the Users (chefs).

Note that this isn't what you are doing here, since you're accessing resources managed by your app, not by Google. In particular, as you correctly identified, the access token means nothing to your API. I could just as well give it a random string.

You might be tempted to use the following scheme:

  • Implement the implicit scheme as described in your question.
  • Have the API server validate the access token with Google, and ask Google for the name or email associated with the token. This will be the identity of the user who actually logged in to Google, and you can then decide whether or not to grant permission to that user.

The problem with this approach is that many apps use OAuth with Google, and so many apps will have Google access tokens that don't belong you app. How can you tell the difference?

You can ask Google, when you present it with the access token, to also provide you with the client ID that was provided when this token was generated (see how your diagram indicates that the client ID is sent?). Since that client ID uniquely identifies your app, then your API can tell that it's been given tokens that only came from your app. Note that this critical part of the OAuth flow is very different in mobile apps which is why the implicit flow should not be used with mobile apps (but it's fine with web apps).

Note that your client ID should be considered common knowledge (e.g. it's found in the .js files on the machines performing this flow), but it cannot be spoofed because as part of the OAuth flow, the user's browser will be redirected to a URL that is pre-configured in Google and belongs to your app. So even if a malicious app uses your client ID, Google will still send the token to your app.

Other practicalities

The above requires you to issue a call to Google on every API call, or at least cache the valid access tokens (which means you keep state, which is a bummer for scalability). If you want to avoid this, you can create a /login endpoint which generates a JWT. Note that you'll still need to validate the access tokens upon login.

Upvotes: 1

Related Questions