Reputation: 91959
There are multiple partied involved in OAuth2
conversation. Consider the
following diagram from the article here
Consider that I have an application that has data for restaurants
and has APIs related to it. Let's call is restaurant
s 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
Shouldn't I secure
my application endpoints or rather just believe the accesssTokens
? Yes, the trust is established between Application
and OAuth Endpoint
(Google), but there is no trust
developed API
and Application
by confirming the validity of accessToken
with OAuth Endpoint
(Google)?
If I should secure my application API endpoints, shall I have a /login
endpoint for my APIs
where my application accepts accessTokens
, validate and create a JWT
based headers for clients to use for further communication with protected resources like /recipes
.
Looking forward to your ideas here.
Thanks in advance
Upvotes: 0
Views: 238
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.
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 scope
s) 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:
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.
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