How to return specific scope according to given user role in Curity - curity

Given :
a oauth client using Authorization code flow used by a website to fetch resources from an API located behind a Reverse Proxy,
some users with differents roles (admin & customer) defined in the roles part of the SCIM 2.0 User schema in Curity
a custom claim 'roles' based on the 'roles[]' field retrieve from the account-manager-claims-provider
two scopes (product_read & product_write)
How can we attached the right scope based on a given role for an unique client in Curity to get :
the product_read scope for all users with 'customer' role
the product_write scope for all users with 'admin' role
Curity docs or videos talk about custom mapper for claims, but it seems there is no example of procedure to dynamically verify which scopes must be attached to a token based on the role of an authenticated user.
I'm looking for an answer dedicated to Curity.io solution and the recommanded best practices to adapte scopes based on a given user role in a web app using RBAC, to secure the calls to the APIs during the user journey.

This type of scenario is usually managed as follows:
Scopes are application level privileges set at design time, and are requested before the user is known
Claims are identifiers with user specific values set at runtime, once the user has been identified
MULTIPLE ROLES APP DESIGN
Personally I would look to model the authorization around the mainstream use case:
Customers can buy things and look at products, and this constitutes the majority of app usage
There is an internal admin operation to update products, which is an exception
This might lead to the following API authorization code:
updateProduct(input: Product) {
if (!this.hasScope('product') || !this.hasRole('admin')) {
throw new ForbiddenError();
}
this.repository.updateProduct(input);
}
I think my personal preference for your use case would be to use the below values:
Scope: product_read
Claim: (role=customer)
You may prefer to call this scope product or product_write. It is true to say that the app has scope to a product but that exact permissions are not known until the user's claims are identified.
APP PER ROLE DESIGN
At one previous company we used to design separate apps for each persona, since the security and UX effort sometimes varied between the two cases:
The main internet app for customers, with scope=product_read
An internal UI for administrators, with scope=product_write
If this made sense for you at some future point, I think my suggested scope would translate nicely.

Related

Identity Server - Multiple users with different access levels on different accounts

My application is composed of an API layer which is accessable by presenting a Bearer Token, obtained from our Identity Server. Each of our API has a level of scopes that the token must contain in order to be invoked: this means, for example, that if you want to make the API call which "creates a product" you need a write access to products (i.e. the scope "products") while you may just need the scope "products_read" if you only want to retrieve them.
Scopes are bound into the token when you authenticate onto the ID server.
Now, I need this user to be able to perform different operations on different "workspaces". Each workspace administrator can set which permissions each user have. This is, in fact, linked to the scopes that each user will have when operating on that particular workspace.
Right now we have implemented that, if you are trying to access a different workspace, the API layer will check:
if your bearer token is valid (by validating it on the ID server)
if you are authorized to access that workspace
changing associated claims by removing the original "scopes" (set into the token by the ID server) and overwriting with those assigned by the administrator of that workspace
This somehow works, but it stinks because I don't want my application layer (API) to have this kind of responsability and the opportunity to tamper with the token. I want the ID server to handle it and, after the user tries to enter into a different workspace, it generates a new crafted bearer token with correct claims (so the API will just need to trust it).
What's the best approach in doing that? I'm digging into the "custom grant type": may this be the right approach?
Scopes are fixed at design time and the same for all users. I like your use of products and products_read - that is very standard.
When you need dynamic behaviour, implement claims, which depend on who the user is. In your case I would use a workspaces array claim. Since this is a key vaue for authorization, it should be added to access tokens at the time of token issuance. Think in terms of your products scope being composed of claims.
It feels like workspaces and other permissions are part of your business data rather than your identity data. At the time of token issuance, IdentityServer should send identity attributes (eg subject claim) to an API endpoint you provide. which returns business attributes (workspaces). I believe in IdentityServer this is done via a custom profile service.
I'd try to avoid different tokens for different workspaces, since that will be awkward in terms of usability and code complexity. The standard way to do it would be to redirect the user each time.

What are the pros and cons of "super" access tokens with large numbers of scopes?

Context
We use Identity Server for identity and access control in our solution. Our scope names have the form of URLs so they are 40-60 characters long.
Some time ago we received a request to increase the max length for scopes in the request. The default value is set to 300 in InputLengthRestrictions class and it can be changed very easily. However, after some discussions, it turned out that for now it may be enough to increase the max value to 500 or 1000 but in the future, an even bigger limit may be needed in order to be able to request 10, 20 or more scopes.
Here comes the question. Is it a good practice to request an access token with such a large number of scopes? What are the pros and cons?
My thoughts
From my perspective, the main benefit of having one "super" access token has one main advantage i.e. it is convenient because it allows you to call all APIs.
On the other hand, I see some drawbacks and/or code smells:
The fact that a large number of scopes must be requested may mean
that scopes are too granular.
The fact that a large number of scopes must be requested may also suggest that scopes are used more as permissions. It is especially a problem in the case of long-lived tokens as they cannot be revoked easily.
Requesting a large number of scopes may suggest that you request
more than you actually need. However, it is recommended to "choose the most restrictive scopes possible".
Having a super access tokens expose a higher security risk if such a token is intercepted.
In implicit flow, a token is passed in URL so the large super token can exceed the maximum length of the URL.
Super tokens might be too big to store them in cookies (it is a
different topic if tokens should be stored in cookies).
Super tokens can be quite large so the network performance can be affected.
What do you think? Do you see any other pros/cons of super tokens? I'm not sure but maybe large super tokens can affect Identiy Server performance.
I don't have pros or cons for you, but perhaps this answer can help you.
Looking at IdentityServer you'll see three parts, the resource, the client and the user. IdentityServer has two main responsibilities, authorize the client and authenticate the user. User authorization is actually not the responsibility of IdentityServer. That's why they created PolicyServer.
Consider the following resource:
resource = CalendarApi
scope = Calendar.Read
scope = Calendar.Write
scope = Calendar.Event.Create
The resource is just a logical name. It can consist of one or seperate api's (as in projects), where an api can implement a single or multiple scopes. In the api a scope is an implementation of certain functionality.
Only a client can request a scope, because the client knows how to use the functionality.
Suppose I have two clients: Mvc1 and Mvc2. Mvc1 has a calender view and an admin page, while Mvc2 only shows the calendar.
My configuration:
Mvc1: scope = Calendar.Read Calendar.Write Calendar.Event.Create
Mvc2: scope = Calendar.Read
It has no use for Mvc2 to request all scopes, because it doesn't use the other functionality. It wouldn't make sense to request all scopes. And in case Mvc2 is a third party app, you shouldn't, because they could use it even when this was not the purpose.
Best practice here would be that a client only requests scopes that are allowed (as configured in IdentityServer) and may be implemented by the client.
So far the user was not involved, because there is no relation between scopes and users. However, the client needs the user (as resource owner) to actually access the resource.
It then comes to user authorization to determine whether the user can create events on the calendar. This 'permission' is not the scope.
The scope Calendar.Event.Create doesn't allow the user to create an event. It only allows the client to connect to the resource.
When combining the clients and users, then there is only one situation where a user can create an event: when a user with create permission uses the admin page in Mvc1.
Mvc2 can't access the resource, not even when the user has create permission.
Now getting to your question:
Is it a good practice to request an access token with such a large
number of scopes?
The access token should only contain the scopes that are needed, as described above. Only necessary scopes should be requested by the client.
Agree. The number of scopes should not be too detailed. Don't treat scopes as permissions, e.g. create, edit, read. Though I did as example, a better scope would be Calendar, where the user permissions define what the user is allowed to do (CRUD permissions).
Agree, should be investigated.
I would say yes, as argumented above.
It is still the user that has to be authorized. But you should limit the possibility for clients to use functionality that was not meant for that client.
/ 6. / 7. Hitting limits is a good indication that the architecture may need some redesign. In general you should not expose more than necessary and you should avoid hitting limits.
I suspect the problem is that scopes are used as permissions. Remove the 'CRUD' from the scopes and redesign user authorization. Don't set permissions in claims.
In my design there is no need for a super token, nor will I ever hit a limit. There are only few scopes, the access token only contains the sub claim and policy server tells me what the user is allowed to do.
I hope this helps you in any way. Please let me know if something is not clear.
You can implement Service Account flow for same. Using it you can get token of respective client with all allowed scopes to client.
By this way your token does not have included all scope but has scope allowed to client.
I don't have sample code right now but you can check how service account can be implemented

Add 'ROLE' to spring security / Auth0 authorization

In my Spring Boot application i'm working with Auth0 to manage access to my rest api.
In addition to Auth0's scope i would like to add a ROLE to each user which in turn will provide an additional layer of access control where specific API's won't be accessible to low privileged users.
I've been reading about custom rules and authorization extensions but couldn't quite understand what is the right implementation for me.
Here's my WebSecurityConfigurerAdapter code snippet:
So basically i want only 'ADMIN' for example to be able to access /test/**
#Override
protected void configure(HttpSecurity http) throws Exception {
JwtWebSecurityConfigurer
.forRS256(configBean.getAuth0ApiAudience(), configBean.getAuth0Issuer())
.configure(http)
.authorizeRequests()
.antMatchers(HttpMethod.GET, "/test/**").hasAuthority("read:test")
.anyRequest().authenticated();
}
Any help would be much appreciated!
You have a few options here (at least..).
1). You could conceivably use a Rule to do handle the decision logic on which "ROLES" are assigned to given user - and rather than tag this onto scope (which you could do too..), you may decide they belong instead as a custom claim on that access token. Body of Rule may contain something like
// lookup the permissions for given user somehow (secured webhook, static map etc) - here lets imagine we want ROLE_USER assigned
context.accessToken.scope = "ROLE_USER"
// or
context.accessToken['https://mydomain/roles'] = "ROLE_USER"
2). Simply use the fact that you have the auth0 userid available in the JWT Access token from Auth0 that you send to the API - you could use this knowledge to look up the finer grained permissions for that use "out of bands" of Auth0 (using your own database storage for permissions keyed on user Id etc or some other customer claim tagged on the access token - or by using auth0 if for example you tagged the ROLE information as metadata onto the Auth0 User profile. You could then do an Auth0 user profile lookup (management api) by user id and get details that way. See example here for an illustration in Java on getting the userId claim from the JWT access token if you like this approach.
3). Take a look at the Auth0 authorization extension which provides support for user authorization via Groups, Roles, and Permissions. You can define the expected behavior during the login process, and your configuration settings will be captured in a rule that's executed during runtime.
There is no hard and fast answer here, each of the above merits consideration, and what you need for your project. If you really want to leverage the existing declarative authorization as per your code above, then Option 1, and pegging the ROLES information to the scope is the easiest approach.
However, I would actually advocate option 2). above myself, for most "pragmatic" small to medium sized ventures. Here, you would require a little programmatic code inside your Controller endpoint to lookup the ROLES and then make a security decision that way. You could also push out the lookup code into a common Custom Filter that executes before the Controller code is reached, and does the necessary Spring Security manipulation that way - more of an advanced developer option - (I have written libraries in the past that supported this approach for Spring Boot / Security - and can therefore vouch it is a reasonable approach. See here for demonstration but again, sure you would prefer to get on with building your business logic and not detour into building a library, right?).
Option 3). is definitely worth exploring if you are building out a serious enterprise app, and need all the integrations - especially where integration with enterprise connections such as Active Directory are in play.
Leave me comments if you are still confused, but hopefully the above offers sufficient insights to explore further.
Quick update
Further to our discussions, here is a little Rule that gives you the idea you were asking about:
function addRoleScopesToAccessToken(user, context, callback) {
console.log("add-role-scopes-to-access-token rule");
user.app_metadata = user.app_metadata || {};
var roles = user.app_metadata.roles;
if (roles && roles.length > 0) {
context.accessToken.scope = roles.join(' ');
}
callback(null, user, context);
}
And this is how your "app_metadata" might look like:
{
"roles": [
"role1",
"role2"
]
}
You should end up with a JWT access token with the roles added to the scope. eg.

Understanding Claims

I'm trying to get up to speed with OpenId Connect, OAuth2.0, Security Token Service and Claims. Imagine a scenario with a large website with many areas and different functionality e.g. Customer, Order, Supplier, Delivery, Returns etc. My question is this – would I create Claims on the Token Server such as CanCreateCustomer, CanReadCustomer, CanUpdateCustomer, CanDeleteCustomer etc, i.e. effectively CRUD Claims for each main area/Business Object? This would lead to many tens but more likely hundreds of Claims. Or is my understanding coming up short?
So fixing terminology, you mean "scopes", not "claims". Scopes are identifiers used to specify what access privileges are being requested. Claims are name/value pairs that contain information about a user.
So an example of a good scope would be "read_only". Whilst an example of a claim would be "email": "john.smith#example.com".
You can send claims in the id token (or JWT), or/and have them available via the userinfo endpoint (if using the "openid" scope).
You can break scopes down per service, and have them as granule as you would like. Or have them as high level (read / write / admin). I would recommend having enough scopes to actively achieve the security principle of least privilege (basically: giving people what they need to do their job). You can use namespaces if you have a lot of scopes.
Your understanding is right, but you have a lot more flexibility in OAuth2.0 scopes (claims)
These scopes can be configured in any way for eg, in your case instead of creating individual scopes for each CRUD operation for each main area, you could create group scopes like
customer.read_write
order.read_write
Etc, you can even go one level higher , by creating functionality level scopes, like
webportal.full_access
adminportal.full_access
Then in your application, after authentication, the authorisation can be done like,
ValidScopesIn({Scopes.WEBPORTAL_FULL_ACCESS, Scopes.CUSTOMER_READ_WRITE})
public void createCustomer(Customer customer) {
// your creation logic
}
I think your understanding is largely correct. However, if I understand what you describe correctly it seems more of an authorization (OAuth) rather than an authentication (OIDC) problem, and as such you might have a look at how other OAuth resource providers define their scopes (not claims btw), for instance GitHub or Slack.
I would recommended that "scopes" be configured as URIs so that collisions do not occur.
As an example.
-jim

Using Spring Security authorization with context-specific authorities

We need to add access control to our application, making sure that every command is performed by a user who has the proper authorities for the given domain objects. We are already using Spring Security 4.0 for authentication and intend to use it for authorization as well.
What makes this complex is the way that authorities are granted to a given user. In our problem space, a User can found several Companies and hire other Users, making them Employees. Each User can be an Employee of several Companies. Some authorities can be granted to a User directly (e.g. canResetOtherUserPassword); other authorities can also be granted by a Company to an Employee based on their Role in the Company (e.g. canOpenProject, canRenameProject). When performing Company-independent commands, User-specific authorities must be checked by the service layer. When performing Company-specific commands (e.g. open a project for a company, rename an existing project), Employee-specific authorities must be checked.
Now let's consider these last two commands, which would have the following service signatures:
long openProject(long companyId, String title)
void renameProject(long projectId, String title)
To control access for the 1st method, the authorization component could retrieve the acting User through the thread-local SecurityContext.authentication, retrieve the Company using the companyId parameter, retrieve the Employee corresponding to the current User, then match Employee-specific authorities against the required canOpenProject authority.
To control access for the 2nd method, the authorization component could again retrieve the acting User through the Thread-local SecurityContext.authentication, retrieve the Project using the projectId, retrieve the owner Company through project.ownerCompanyId, retrieve the Employee corresponding to the current User, then match Employee-specific authorities against the required canRenameProject.
Clearly, this can be done using procedural code, as I just described. We would prefer to use a declarative approach similar to the #PreAuthorize interceptor that Spring Security already offers, and obviously to write as little code as possible. We just don't know where to start.
Any ideas?
Thanks in advance!
You can implement UserDetails (org.springframework.security.core.userdetails.UserDetails) or just extend a default implementation of UserDetails, like User (org.springframework.security.core.userdetails.User) ---> CustomUserDetails with additional attributes like company (with getters).
finally : use simply #PreAuthorize("principal.company.companyId == #companyId")
Reference : Spring Security 3.1 chapter 10 (you need to go back to chapter 3 for UserDetails implementation)
It was very useful for me !

Resources