I am in the process of designing 3 components that will work in symphony with one another:
- A RESTful web service which requires
BasicAuth
over HTTPS on all calls, and which is what actually does all the heavy lifting for my system (does the work) - A web UI that translates end user actions into API calls to the above-mentioned web service; hence the UI is "backed by" the WS
- A command-line interface (CLI) tool that developers can install and run locally, that also translates commands into API calls to the WS (hence it too is "backed by" the WS)
One of the first hurdles I'm trying to cross is with respect to authentication and authorization.
Let's pretend that the WS uses a LDAP/directory service (like AD or perhaps Apache DS) as its authentication realm. Meaning, when an API call come in over the wire (say, an HTTPS GET
for some resource), the BasicAuth
credentials are extracted from the request, and forwarded on to the LDAP service to determine whether this is a valid user or not. If they are authenticated, then let's say that a separate authorization realm, perhaps a database, is used for determining whether or not the identified user can do what they are attempting in the HTTPS request. So far, so good.
In the case of the CLI tool, the user will have to authenticate prior to running any commands, and so this model works just fine, as a single user will only ever be operating the same CLI instance at a given time.
The problem comes when we try integrating the web app (UI) with the WS, because many people could be logged on to the app at the same time, all with different permissions dictating which underlying API calls they're allowed to make.
As far as I see it, it looks like I have but 4 options here:
- Cached Credentials: After logging into the app, the credentials are somehow, somewhere cached (such that the app has access to them), and the app doesn't enforce any kind of authorization policy itself. When users attempt to do things that generate API calls under the hood, their credentials are looked up from the cache, and forwarded on with the API calls. If the WS determines they aren't authorized, it sends back an error.
- Service-Level Accounts: The app and the WS both use the same authentication/authorization realms, except the web UI now enforces authorization on what users can actually see and do inside the app. If they're allowed to do something that generates an underlying API call, the app sends service account credentials (e.g.
myapp-admin-user
) with each API call on the user's behalf. - OAuthv2: I have no idea what OAuth is or if its applicable for this scenario, but feel it may be a solution here somehow.
- Token Servers: Use a token server such as CAS or maybe Kerberos to vouch for users, in a similar way as the Service-Level Account option behaves. Here, when a user logs into the app successfully, the token server sends the app back a session UUID, and also registers that UUID with the WS. Every time the app generates an API call, it tacks the UUID on to the request, which is then validates on the WS side.
The "Cached Credentials" option just feels like an aberration of everything that is good and wholesome in security-land. It just feels wrong to cache credentials anywhere, ever.
The "Token Server" option seems valid for an SSO type setup, but not in this particular case and feels awkward to me. I also think there's no good way to use the session UUID concept and BasicAuth
/HTTPS at the same time.
So this leaves OAuthv2, which I know nothing about, and "Service-Level Account (SLA)*" as the only remaining options. The SLA option seems OK, but has a few following drawbacks:
- It requires the service account to basically have "god privileges" over the WS. In other words, once the app deems a user is allowed to click a button or do something in the UI, that translates to an unconditional API call by the service account being used by the UI. This just feels bad, mkay?
- It occurs to me that maintaining two sets of permissions (the permission set for each user of the app, and then the permission set for the service account used by the app against the WS) can result with the permissions getting out of synch with each other somehow
So it appears that I don't really have any good options here. Surely I can't be the first dev to run into this, but asking the Google Gods have not helped me much here. Any ideas?