Understanding Claims - oauth-2.0

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

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.

How to return specific scope according to given user role in 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.

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.

Authorization strategy on a per-client basis

I have a Rails 4 application. I use devise for authentication and opro for providing oauth2 with my API. All requests are authorized with pundit policies and until now, this setup was totally fine.
Currently, my authorization is always done on a per-user basis. This makes sense, as usually every request is done on behalf of a particular user who is either authenticated in a session or by providing the oauth-token.
The new challenge is: I have certain API-consumers (let me call them devices from now on), whose requests cannot be seen as requests from a particular user. One is an Asterisk Server that can exchange information with the API, another is a GPS Tracking Box that continuously pushes trackpoints to the API.
Thus, I need to authorize certain API-operations on a per-device basis, meaning there is not necessarily a current_user available. Having no current_user however screws up my authorization concept.
I have already considered several approaches to the problem:
creating dedicated users for each device and authorizing them to do the specific action
pro: does not screw up my authorization scheme
contra: would mean to rethink the User-Model, as currently I only have "natural users" that require name, birthday, email, etc
creating dedicated controllers with adapted authorization scheme
pro: high flexibility
contra:
authentication for devices required
extra API endpoints required, does not feel very DRY
I am searching for a best-practice approach for such a situation. I believe this is not an extra-ordinary problem and there must be good solutions for this out there.
You need a separate layer that does the authorization check as well as global attributes called caller_id and caller_type (these are just examples).
You then want to implement a logic e.g.:
if caller_type == device and caller_id == ... then
if caller_type == user and caller_id == ... then
To do that you can just custom-code your own little class. Alternatively you could use XACML to define your authorization logic. See this blog post which applies XACML to servlets. The same principle could be done for your Rails application.
HTH,
David.

Resources