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.
Related
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.
So I want to have single sign in, in all the products using a auth server but that's not only for employees, keycloak should be used to that like auth0?
There are also some advantages to Keycloak:
Keycloak is also available with support if you buy JBoss EAP (see http://www.keycloak.org/support.html). This might be cheaper than the enterprise version of Auth0. If you want to use custom DB, you need enterprise version of Auth0 anyway.
Keycloak has features which are not available in Auth0:
Fine-grained permissions and role-based access control (RBAC) and attribute-based access control (ABAC) configurable via web admin console or custom code or you can write yuour own Java and JavaScript policies. This can be also implemented in Auth0 via user rules (custom JavaScript) or Authorization plugin(no code, less possibilities). In Keycloak you can do more without code (there are more types of security policies available out of the box e.g. based on role, groups, current time, an origin of the request) and there is a good support for custom developed access control modules. Here some more detailed research would be interesting to compare them.
Keycloak also offers a policy enforcer component - which you can connect to from your backend and verify whether the access token is sufficient to access a given resource. It works best with Java Web servers, or you can just deploy an extra Java Server with Keycloak adapter which will work as a gatekeeper and decide which request go through and which are blocked. All this happens based on the rules which you can configure via Keycloak web interface. I am not sure such policy enforcer is included in Auth0. On top of that, Keycloak can tell your client application which permissions you need when you want to access a given resource so you do not need to code this in your client. The workflow can be:
Client application wants to access resource R.
Client application asks Keycloak policy enforcer which permission it needs to access resource R.
Kecloak policy enforcer tells the client application which permission P it needs.
The client application requests an access token with permission P from Keycloak.
The client makes a request to the resource server with the access token containing permission P attached.
Policy enforcer which guards the resource server can ask Keycloak whether permission P is enough to access resource R.
When Keycloak approves, the resource can be accessed.
Thus, more can be centralized and configured in Keycloak. With this workflow, your client and resource server can outsource more security logic and code to Keycloak. In Auth0 you probably need to implement steps 2,3,6 on your own.
Both Auth0 and Keycloak should be able to achieve your goal - assuming you want only social (facebook, google etc), and /or username & password authentication?
Auth0 is the less risky option, keycloak is good for non-commercial & where you can afford production outages without a global 24x7 support team. Here a few other reasons why I'd recommend Auth0 - the documentation is world class, they have quickstart samples so you can get up and running in minutes, and easy access to more advanced options - passwordless, authentication, MFA, anomaly detection, x9's reliability, rate-limiting, an extensive management api, extensions for everything eg exporting logs to log aggregator, and so on. Anyhow, good luck with your project, and obviously what suits best may simply be down to your own project requirements.
Should add, if you are doing mobile, then Auth0 put a lot of effort into adding the necessary specialised security flows to target mobile (native / hybrid) apps. For instance, PKCE usage when using /authorize endpoint. Please bear that in mind, as not certain how keycloak has been implemented to handle this - alot of IDMs still do this incorrectly today.
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.
I have a Web API project of ours that needs to be secured. I am planning to allow the user's that registered with my app to use the API [Forms Authentication], users with their own organizational accounts [ADFS] and Social Sign-In.
I have all the middleware available to plug-in and make available to the user's. However, in my application I do have custom roles and privileges that are to be provided so that my application authorizes the service calls based on the existing privileges. What is the best way to accomplish this.
I think that I will be required to provide my own custom implementation of the UserStore and UserManager with my own IUser Implementation.
Kindly suggest the best practice for this scenario.
With multiple authentication middleware registered, you can get multiple claimidentity's.
register each type of authentication you want to support.
I would be sure to add a claims transformation module at the end of the pipeline. Thinktecture has an example. ThinkTecture Owin Claims Transformer
This would give you one place to look up and add all the application type claims for an authenticated user in one spot.
Simple pseudo example (geared to webapi, but concept the same). Authenticate with bearer or basic or both then transform.
//identity 2.0 user manager stuff used in your modules
app.CreatePerOwinContext(ApplicationSession.Create);
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
// Token Authentication -> get a principle
app.UseOAuthBearerAuthentication(OAuthBearerOptions);
// Basic Authentication. -> get a principle
app.UseBasicAuthentication(app.CreateLogger<BasicAuthenticationMiddleware>(),
"Realm", ValidateUser);
// transform claims to application identity. Add additional claims if needed
app.UseClaimsTransformation(TransformClaims);
It sounds like you are looking for externalized authorization. Externalized authorization is the act of:
decoupling business logic from authorization logic
expressing authorization logic as centrally managed, centralized authorization policies
protecting your APIs through a common layer
enabling fine-grained & dynamic access control through the use of attribute-based access control (ABAC) which extends what's possible with RBAC (role-based access control).
Have a look at XACML, the eXtensible Access Control Markup Language. You can find some more information on OASIS's website.
Also check out NIST's project on ABAC.
Once you defined your authorization logic, you can decide how to enforce it. This can be done either via direct enforcement at the entry of your apps or can be done in a provisioning way whereby the permissions derived from the authorization policies are fed into an authentication token e.g. SAML as attribute assignments.
HTH
This is what I ended up designing for a system with similar requirements. The key is to separate the authentication and authorization logic.
Build Owin authentication middleware components that take care of establishing user identity based on various login methods you mentioned. Looks like you have this accomplished. Set ASP.NET identity based on the user.
Retrieve the roles/permissions for the logged in user from your store. This can be done as a separate Owin middleware or a part of your authentication. Add the permissions as Claims to your Principal.
Extend your roles/permissions store to map API service operations to the application permissions.
Implement a custom API Authorize attribute and apply it to every API operation. In this attribute you will have access to the operation name and the user Claims (permissions). Match the Claims with the permissions you mapped in the step above. If there is a match, return IsAuthorized=true, otherwise, return false.
Here is a similar issue at a simpler level.
How do you setup mixed authorizations for different authentications in .net (web api 2 + owin)
I am working on an internal authentication system for users of a set of of RESTful web applications. Our intention is that a user should be able to sign-on once via a web form and have appropriate access to all these RESTful applications in our domain, which may be distributed in a private cloud across many servers. (I understand already that having a single authenticated session is not aligned with a pure RESTful approach, but this is a usability requirement.)
The applications themselves will be written in a variety of programming languages so a language-neutral approach is required. It was suggested to me that we might use OpenID or OAuth or a similar framework to handle the authentication but my understanding is that these are intended for third-party services and not the first-party services that would share data on our internal system. In this case, we might have a central provider service with all the other applications treated as third parties (or relying parties).
Questions:
Are OpenID/OAuth suitable for authentication among first-party services?
If so, how would one be advised to set up authentication for this use case?
Wouldn't a user have to grant individual permission to each first-party server that they wanted to use, just as they would need to grant individual permission to any third-party server? I think this would violate the requirement of having a single sign-on for accessing all the first-party services.
Are there good examples of sites supporting this first-party use case?
What would be a good alternative framework for this first-party use case?
You do not need OAuth for SSO services.
The primary use/advantage of OAuth is, as you know already, granting access to a 3rd party app to access/use your resource in a controlled manner.
Rather than having an authentication/authorization server that you would need for OAuth, why not use a single log in service across all your APIs. An OAuth access token is totally different from what you need.
As far as I understand, what you can have is something like OAuth in a way that your server vends out tokens to the app. (I'm assuming that it's a totally internal system, so tokens cannot be misused).
So basically what I'm proposing is:
When an app tries to access the first API it's redirected to a web-form.
The user enters credentials and is taken to the DB for verification. Let there be a service that generates a token for the user/app
Next API access request would be made with that token - the token uniquely identifies the app
Depending on the level of security you need you can sign some text using HMAC and send it as token, or if its totally internal just generate a unique identifier for the app/user and send it to other API
On receiving the token, each service first calls the main server with the token and internally fetches the corresponding customer/user ID and performs the required function.
In short separate the login + token generation + token verification into a different module. All APIs should use this module for login/token verification.
What I have proposed here works like OAuth but all security aspects have been stripped down since you want to use it in a private cloud.
Oauth supports multiple different kinds of flows. You can use the client crendentials flow from Oauth 2.0 to avoid asking the user to grant permission for every app (this is intended for the cases where you control both the server and the app or where you want to preauthorize certain apps). This post does a good job explaining everything: http://tatiyants.com/using-oauth-to-protect-internal-rest-api/