Question

Please note: Months ago I asked this question that received a truly amazing answer and introduction to OAuthv2. I’m now knee deep in the implementation of such a system and have similar (but notably different) concerns, and so this question is not a dupe of it. It’s more like a “Part 2” that, hopefully, documents the proper setup for a distributed OAuthv2-backed architecture. I think there’s value to that for future readers and onlookers.


Essentially I have the following architecture:

enter image description here

  • A public RESTful web service provides CRUD operations on resources stored in other web services, databases, systems, etc.; and
  • A web application sits “in front of” that REST service and provides a nice web/mobile GUI to those REST endpoints, allowing logged in users the chance to hit the endpoints through a user interface
  • There is also a command-line tool that uses a HTTP client under the hood, so that if devops folk wish to hit the REST endpoint from their command-line, they can do so without having to write their own HTTP client or go through the UI (however they still need to authenticate/authorize themselves)
  • Sitting “behind” this public REST service are other “backing” web services, some of which are backed by other things such as databases, LDAP directories, etc.

Since the REST service is public, other clients/customers can build their own HTTP clients and integrate with it, and so the auth option must be tolerant to that scenario as well.

Every component needs to be authenticated and authorized to do anything here. The CLI tool that devops folk use must be authenticated against the public REST service. Mobile/web users must be authed before they can even log in to the web app, and the web app must auth against the public REST service. The public REST service must auth against its backing services. Those services must auth against their backing resources/services/databases. Etc. I’m looking for an OAuthv2 solution for all of this.

One item that is not in the picture above, but very important, is that there will be a single OAuthv2 Auth Server used by all the server-side components (because I own everything except the client-side). Hence all services, databases, etc. will have access to the same auth server (and in reality, it is a cluster of HA Auth Servers).

Which grant types to use for each component?

My understanding of OAuthv2’s Client Credentials grant is for components updating their own metadata with the Auth Server, such as their client secrets or redirect URLs (yes???).

This means I really have to “map” each of those components to one of the other 3 grant types:

  • Authorization code grant
  • Implicit grant
  • Resource Owner Password Credentials (hereafter ROPC)

After reading several | great OAuthv2 tutorials, it feels like the implicit grant is not applicable to any of the components here. It seems to be for when you have an unprotectable, client-side app that has no way of protecting access tokens. In my scenario, the only component that might qualify for this is the web app, however that will be on its own protected, trusted server that I control/own 100%.

So unless I’m misunderstanding something fundamental here, it seems I need to choose between Authorization Code grant and ROPC for all the following components/interactions:

  1. End user authentication against web app (to login to the web app itself)
  2. Web app authentication against public REST service
  3. CLI authentication against public REST service
  4. Custom built HTTP clients (not built by me, that is) authenticating against public REST service
  5. Public REST service authenticating against each backing (private) web service
  6. Private backing web services authenticating against their databases or external dependencies

Finally, my concerns!

I would imagine that the web app should use the Auth Code grant, but have concerns about that (see below). I would imagine the CLI tool and custom HTTP clients should use ROPC, but I have doubts about that as well. As far as the service-to-service and service-to-database use cases, I’m at a total loss. And so, finally, my questions:

  • For each of the 6 use cases identified above, what is the proper grant type to use, and why?
  • OK great, so that takes for of authentication. What about authorization?!? How does the auth server (or each component) assign roles/permissions to each access token?
  • In each of the 6 uses cases that require the Auth Code grant, who hangs onto the refresh token (the client app, the auth server, the user agent)? How often will the end user need to authorize the client app (just one time ever, each working session/login)? It would be strange to force users to authorize the client app every single time they sit down to work in that system.
Was it helpful?

Solution

OAuth2 Flows

The OAuth flows in order of strongest to weakest are Authorization code grant then Implicit grant, then Resource Owner Password Credentials.

Authorization code grant

The Authorization code grant flow is used where not only the user needs to authenticate to gain access to a protected resouce but so does the 3rd party application. This means only applications you have approved in advance can act on the users behalf

In the Authorization code grant there are 2 sets of credentials; the users, and the 3rd party applications (called the client ID and client Secret - like a username and password but for a server

Implicit Grant flow

This flow is used when either the client secret and client ID can't be protected (that being if they wouldn't be held on a server but would be distributed as an application) or you explicitly want non preapproved applications to be able to act on the users behalf

Resource Owner Password Credentials

In this case the 3rd party app collects the credentials and then passes them onto you. If you're thinking that the 3rd party app could also email them to a hostile party; you're absolutely correct, they could. But sometimes this is the only practical implementation (e.g. a mobile app - although it is technically possible to use the Implicit Grant flow with a mobile app it is clunky)

Your Scenarios

I can see 2 things you want to protect; the public REST endpoints and the private web services.

public REST endpoints

  • End user authentication against web app (to login to the web app itself)

Here it is possible to use the Implicit Grant flow as redirecting to an authentication page is easy

  • Web app authentication against public REST service

Again it is possible here to use the Implicit Grant flow as redirecting to an authentication page is easy. However, as we're about to allow ROPC anyway don't worry about using ROPC if it is easier to implement (you are as secure as your weakest endpoint)

  • CLI authentication against public REST service

This seems like it will have to be ROPC or a slighly clunky autoopening of a webpage

  • Custom built HTTP clients (not built by me, that is) authenticating against public REST service

Again this seems like it will have to be ROPC or a slighly clunky autoopening of a webpage

Private web services

  • Public REST service authenticating against each backing (private) web service

Now this is an entirely different beast, you do want it only accessable by preapproved applications. These may not be authenticated by an OAuth flow at all but if they are you definately want to use a client ID and client Secret. As the user is not "present" in the interactions between the REST endpoints and the webservices you can only use the ROPC flow, but here you oblige the passing of valid clientID/clientSecrets. This means your (presumably) more high level access to your private webservices can't be accessed by anyone not approved by you. It may make more sense to use a 2 legged server to server OAUTH for this but that is outside my area of expertise.

  • Private backing web services authenticating against their databases or external dependencies

This is probably out of scope and will depend on exactly how your system is set up. I would expect to be inside your private network by this point.

Authorisation and authentication.

Technically OAuth is all about authorisation; authorising a 3rd party to act on behalf of the user. Howver this implicitly authenticates the user to the 3rd party (the authorisation wouldn't have succeeded unless they are who they say they are. OAuth implimentations intended for authentication will generally have an endpoint which gives information about the user.

The 3rd party requests certain authorisations using the scope parameter(e.g. to post to a users facebook wall) and in implicit and authorisation code flows the user should be asked if they permit the requesting application the requested permissions; the authorisation server then only allows the permitted actions (stored against the token)

Who holds the tokens

The 3rd party app (whatever form that may take) holds onto the tokens (both regular and refresh), their validity time is entirely up to you and dependant on your application. This could be between a few seconds (for authentication only applications) to infinity - generally refresh tokens are used for very long lived interactions.

Licensed under: CC-BY-SA with attribution
scroll top