I'm currently trying to migrate a multi-tenant system from a "custom" authentication and authorization implementation to OAuth2.
The multi-tenancy model is very similar to GitHub's structure, so I'm going to use it as the main example. Let's assume that in the application we have users, repositories and organizations. Users have access to repositories directly, or through organizations they are members off. Depending on their access rights, users should have different permissions towards repositories and the sub-resources (like /repository/issues), or organizations and their sub-resources (/organization/members) for users who manage them. Unlike, GitHub's OAuth2 solution, this system should be able to provide different levels of permissions across repositories or organizations (GitHub does it at a different level with a custom implementation).
The goal is to keep the logic as simple as possible, encapsulate everything in an authorization service and piggyback on OAuth2 as much as possible.
My approach was to deploy a generic OAuth2 service, and handle the permissions using dynamic scopes:
user:read
user:write
repo:read
org:read
repo:<repo_id>:issues:read
repo:<repo_id>:issues:write
org:<org_id>:members:read
org:<org_id>:members:write
This enables granular permissions for clients and users, such as a user being able to read + write issues in one of his repos, but only read in another.
While this seems to solve the problem, the main limitation is being able to request scopes. Since users would not know the ids for the repos and orgs they have access to, they are not able to request a correct list of scopes when contacting the authorization server.
In order to overcome this I considered 2 solutions:
Solution 1
Issue a token for repo:read and org:read
Retrieve list of repos and orgs the user has access to
Issue a second token with all necesarry scopes
On a deeper thought, this turns out not to be viable since it would not support grants like implicit for authorization_code unless the authorization server would deal with this "discovery" of resources.
Solution 2
The first 2 steps are common to the first solution, while for the 3'rd step, the users would only be able to issue tenant scoped tokens. By extending the OAuth2 with a parameter identifying the tenant (/authorize?...&repo=<repo_id>), clients using authorization_code grant would have to issue tokens for every tenant. The token issued on step 1 would have to persist the identity of the user on the authorization server and eliminate the need of re-authentication when a user would switch between tenants. The downside of this approach would be that it increases the complexity of client integrations and that it might defy the standard in some way.
I'm looking for a second opinion on this, which would possibly simplify the problem and make sure the solution adheres to the standard.
tldr; What about using self contained access tokens which convey user identity information and hold access policy defined at API endpoint ?
The problem you face right now is due to mismatch of what OAuth 2.0 scope is capable of. Scope value in OAuth 2.0 is defined to be used by the client application.
The authorization and token endpoints allow the client to specify the
scope of the access request using the "scope" request parameter.
But in your approach, you try to make it to be defined by end user (the human user).
A solution would be to make authorization server independent of permission details. That means, authorization server only issue tokens which are valid for your service/system. These token can be self-contained, holding user identifier and optionally organisation details (claims). It may contain other details that are required by your service (upto you to decide). Ideal format is to make it an JWT.
Once your client (the consumer of system, like GIT website) obtain this token, it can call the system backend. Once your system backed recieve the token, it can validate the token for integrity, required claims and use these claims to identify what resources are granted for this specific user. Permission levels you defined for scope now are stored with your service backend.
Advantage of this is the ability to let user identity to be reside anywhere. For example you can use Google or Auzure AD and as long as they can provide you a valid token, you can support such users to use your system. This is ideal as permissions are not stored in them. And super users will have ability to define and maintain these permissions.
Agree with everything mentioned by #Kavindu Dodanduwa but would like to add some additional details here.
This problem indeed stays beyond what standard OAuth 2.0 covers. If you want to manage permissions per-resource (e.g. per repo or organization) this should be handled in your service or a gateway in front of it. Typically you need some kind of access-control list (ACL) stored on your backend which you can then use to authorize users.
If you'd like to look at existing standards check out XACML and UMA (which is an extension of OAuth 2.0). However I find them rather complicated to implement and manage especially in distributed environment.
Instead I'd suggest an alternative solutions using a sidecar for performing authorization on your service. Check out related blog posts:
Building a fine-grained permission system in a distributed
environment: Architecture
Building a Fine-Grained Permissions
System in a Distributed Environment: Implementation
Open Policy Agent could be a good solution for such architecture.
Related
We are building an application where the content i.e. data and files would need granular user access the way role and policy works. We use oAuth2 and OpenID connect using one identity provider.
My question is about the possibility of leveraging a platform or AWS Cloud service where this type of granular authorization is available. I don't want to build custom authorization matrix within my application, rather I prefer to use an API of a service and user role/policy for further actions.
When it comes to using scopes from OpenID connect, they are more suitable for defining API level of access.
I would start with your requirements, such as users only being able to only see their own data. Fine grained authorization is typically managed via claims in tokens, which can be highly dynamic when required.
See this Claims Best Practices article for some details. It mentions some specialist authorization systems also.
Cloud solutions may at times be more focused on infrastructure security whereas OAuth deals with application and user level security.
Having said that, defining resource policies as JSON documents like AWS does could be a useful declarative technique to complement claims. At runtime you could then compare a claim from a token, eg a role, against the resource policy to see if the user should be granted access.
We are looking to implement a Micro Services architecture in the future. We don't want permissions at the API gateway to be very clunky and restricted to GET, PUT, POST etc.
We want granular application permissions to be stored and managed centrally, so apps only have to fetch them and not manage them.
I have included a picture of the draft architecture I have in my head as well as logic flow below.
My Question
Can this design pattern be implemented using any of the existing authentication/authorisation specifications such as OAuth2? If not, is it acceptable to create your own Authentication / Authorisation pattern for use with in a private network?
App Life cycle
A developer creates WebApp1
WebApp1 is registered in the Web App Registry Server by the developer. He/She also registers the custom permissions that the App exposes.
Users can have access granted or revoked to the granular permissions exposed by the App by an IT Administrator.
In the example above WebApp1 exposes two permissions CreatePost & DeletePost user1 only has permission to CreatePost
User Process Flow
An unauthenticated user accesses WebApp1 and is redirect to the Login screen.
The user's credentials are validated against LDAP and a UUID Authorisation token is generated. The token is stored in a Security Token Server and the user redirected back to WebApp1 with the token included in an Authorization Header.
WebApp1 requests the permissions this user has from the Web App Registry server, this can be done every x minutes and stores them in local state. The Web App Registry Server also checks the Authorization token is still valid.
WebApp1 checks every x minutes that the users token is still valid, if not the user is requested to login again (or a refresh token could be included with the original token that was sent to the app when the user Authenticated).
Interesting question - some thoughts below on achieving your goals via OAuth based design patterns:
AUTHORIZATION GOAL
The desired end state is usually to give yourself choices:
Use a pattern that enables any API component to do authorization
Sometimes you need to be close to the data source to enforce permissions.
Other times you may want some types of rule to be enforced via a dedicated service
MAPPING TOKENS TO PERMISSIONS
I like this way of doing things. In effect it is a Claims Based Architecture, and the information you need for authorization won't come solely from tokens.
My API Authorization Post describes an extensible pattern that starts with defining a claims / principal object in each API. Here is some sample code, where the Authorizer class provides an overview of behaviour on each API request.
WEB APP REGISTRY
I would be careful about creating components that could come under heavy load and become a bottleneck for your whole software platform - should you need one of these?
CLAIMS AND MICROSERVICES
A pattern that can work well is to design 2 levels of API. Interestingly, both of these can use claims and you can put authorization responsibilities anywhere you want - and give yourself choices:
Entry point APIs: exposed to the internet, do OAuth validation and naturally lock down what clients can do with access tokens:
Microservices: run in a locked down network and can freely call each other without OAuth plumbing
My API Platform Architecture
post explores this option, where claims are passed between microservices via headers.
ACCESS TOKEN VALIDITY
You can often simplify code by following the below rules, since there can be multiple reasons for tokens becoming invalid:
Keep access tokens short lived ~60 minutes
Handle 401 errors in the client as in this code
Our SAAS system is currently using standard Microsoft.AspNet.Identity.Owin libraries to authenticate users via Bearer tokens, as well social logins such as Facebook/Google/Twitter/etc.
Some of our users are asking for us to start allowing of authentication via ADFS.
I'm trying to understand how this can be done. Unfortunately, all of the blogs appear to dive right into the details without providing a good overview as to what's involved. Furthermore, most blogs talk about trusting a specific Active Directory, while we need to trust a whole number of possible customers' active directories - and do it dynamically. IE: customer registers for an account using custom username/password, then provides our SAAS application with some information about their AD. Afterwards, our SAAS application should trust authentication for users in that AD (just the auth part)
Can anyone provide information on what's involved?
TIA
Agree with #vibronet's points.
Another approach would be to add STS support to your SaaS application. This could be either WS-Fed or SAML. You have tagged the question with Azure so AAD could be an option.
You could then federate with any number of other STS's (like ADFS). Note as stated that each ADFS has to agree to add your metadata.
Another approach would be to use IDaaS (e.g. Auth0, Okta). These would do the Identity heavy lifting for you and would essentially provide the STS capability.
The question has 2 parts,
how to work with an ADFS instance and
how to deal with an arbitrary number of ADFS instances from different
owners.
The answer to 1) is to use the WS-Federation middleware, which can be added alongside the middlewares you are already using. However the initialization of that middleware requires knowledge of the location of the metadata document of the ADFS you want to target; furthermore, the ADFS administrator must provision your app explicitly or no tokens will be issued. Hence, the flow you are suggesting (temporary username/password and subsequent details exchange) might be tricky - but not impossible.
About 2) there isn't a way of wiring up an arbitrary number of different ADFS instances unless you modify the middleware setting pretty heavily. The actual answer is that the standard practice for dealing with that scenario is to rely on one intermediary ADFS (or equivalent) that can broker trust toward all others, while your app only needs to trust the intermediary ADFS.
A typical recommendation for securing a REST API is to use HTTP Basic Authentication over SSL. My question is, should HTTP Basic Authentication only be used to authenticate the client (ie. the app accessing the API), or can it also be used to authenticate the user (the consumer of the app)?
It seems most APIs have to deal with both, as almost all web services employ some sort of user accounts. Just consider Twitter or Vimeo—there are public resources, and there are private (user specific) resources.
It seems logical that a simple REST API could do both client and user authentication at the same time using using HTTP Basic Authentication (over SSL).
Is this a good design?
By authenticate the client you probably mean the usage of API Key, this mechanism is used to track the concrete application/client. The second thing is that it gives you the possibility to disable the application by disabling the key, for example when client's author removes his account from the service. If you want to make your API public then it is a good idea.
But you need to remember that it gives you no real protection, everybody can download the client and extract that key.
I would not recommend to use Basic Authentication for API authentication. When it comes to authentication then you should consider that the application (client) developer has to implement its side of the authentication, too. Part of that is not only authentication itself but also how to get credentials and even much more than that.
I recommend to make use of an established authentication standard that ships with client libraries for the most popular programming languages. Those libraries make it much more likely that developers are going to adapt your API, because they reduce implementation effort on the client side.
Another important reason for using authentication standards is that they make developers (and others) more confident in the security of your authentication system. Those standards have been audited by experts and their weaknesses and strengths are well known and documented. It is unlikely that you are going to develop a nearly as solid authentication flow unless you are a security expert :-).
The most established standard in this field is OAuth but you can find alternatives by searching for "oauth alternatives".
How does OAuth help you with your problem setting?
In OAuth 2, the application client has to obtain an access token for a user before accessing any protected resource. To get an access token, the application must authenticate itself with its application credentials. Depending on the use-case (e.g. 3rd party, mobile) this is done in different ways that are defined by the OAuth standard.
An access token should not only represent a user but also which operations may be used on what resources (permissions). A user may grant different permissions to different applications so this information must somehow be linked to the token.
How to achieve such a semantic for access tokens however is not part of OAuth - it just defines the flow of how to obtain access tokens. Therefor, the implementation of the access token semantic is usually application specific.
You can implement such token semantic by storing a link between an access tokens and its permissions in your backend when you create the access token. The permissions may either be stored for every user-application combination or just for every application, depending on how fine-granular you want things to be.
Then, each time that an access token is processed by the API, you fetch this information and check whether the user has sufficient permissions to access the resource and to perform the desired operation.
Another option is to put the permission information into the access token and to sign or encrypt the token. When you receive the access token, you verify or decrypt it and use the permissions that are stored in the access token to make your decision. You may want to have a look on Json Web Tokens (JWT) on how to accomplish that.
The benefit of the later solution is better scalability and less effort during backend implementation. The downside of it are potentially larger requests (especially with RSA encryption) and less control over tokens.
i am looking to build a client to my RESTful hypermedia based API and after reviewing many options am learning towards oAuth* to become the de facto method for authorizing access to the API.
I think i am understanding the overall oauth concepts, i.e. depending on the client (trusted or not) the spec provides several flows in order to "trust" the client (application) from the perspective of the resource owner (user) granting access to the client.
Becuase the application i am building is directly part of the ecosystem of the service it will fall under the umbrella of the trusted clients section so i have decided to implement the Resource Owners Passwords Credentials Grant but here is where my knowledge gets muddied with the terms and the exact role oAuth is there to provide and my brain shuts off :)
I am thinking this is the flow (with some more technical thoughts):
Via a login form the resource owner supplies their credentials
the details are posed to a server (in this case an express.js app)
the app via some local mechanisms authenticates the user credentials against a store
if the user doesn't exist or fails validation then they are returned to the login
if the user does exists and does pass validation the mechanisms to swap their credentials for a token is started (contacting a oAuth server and swapping the details) which stores the encrypted/hashed infor somewhere (redis maybe?)
Once the token is returned it is stored in maybe a session for persistence to the client (i think trello.com do something similar as they have a token cookie but i could be very wrong here)
Is this an acceptable flow? i can't seem to find any examples available and as a sole developer currently would be good to get some feedback.
No need in the end to define my own flow, this is simply the Resource Owner Password Grant where we exchanged the credentials of the user for a oAuth Token for trusted clients.