Add 'ROLE' to spring security / Auth0 authorization - spring-security

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.

Related

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.

How to implement multiple authentication methods in Spring WebFlux Security?

I'd like to provide two ways to authenticate in my application, one is basic auth (users), and the other is some kind of token based (technical users). I understand that I need a custom ReactiveAuthenticationManager but I can't find clues on the big picture. (Actually, there are a very few insights for MVC, and none for WebFlux.)
1) How do I populate the Authentication's name and credentials in the token based approach? If I configure Spring Security to use httpBasic it's already populated. Some kind of filter needed?
2) How do I distinguish in the authentication manager where the credentials are coming from? Do I have to lookup in the userRepository and (if not found) in the technicalUserRepository too?
3) Do I have to override the SecurityContextRepository? All the tutorials do it but I don't see any reason to do so. What is it exactly? This source states that "SecurityContextRepository is similar to userDetailsService provided in regular spring security that compares the username and password of the user." but I think he means ReactiveUserDetailsService (neither UserDetailsService nor ReactiveUserDetailsService does that by the way, it's just for user lookup).
Since i am decent at Webflux and i have worked a lot with oauth2 i'll try and answer some of your questions.
1) How do I populate the Authentication's name and credentials in the
token based approach? If I configure Spring Security to use httpBasic
it's already populated. Some kind of filter needed?
A token never contains credentials. A token is something you get issued after an authentication has been done. So usually you authenticate against an issuing service. After you have authenticated yourself against that service you will be issued a token.
If its an oauth2 token the token itself is just a random string. It contains no data about the user itself. When this token is sent (using the appropriate header) to a service using spring security. Spring security has a token filter that will basically check that the token is valid, usually by sending the token to the issuer and asking "is this token valid?".
If using a jwt, its different, the jwt must contain some information like issuer, scopes, subject etc. etc. but its basically the same thing, there is a built in filter that will validate the jwt by sending it to the issuer (or using a jwk that the service fetches from the issuer so it can verify the integrity of the jwt without doing an extra request).
2) How do I distinguish in the authentication manager where the credentials are coming from? Do I have to lookup in the userRepository and (if not found) in the technicalUserRepository too?
You don't You usually define multiple SecurityWebFilterChains for different url paths. I have not done this in Webflux Spring Security, but thats how you do it in regular Spring Applications, and i don't see any difference here. Unless you are doing something crazy custom.
3) Do I have to override the SecurityContextRepository? All the tutorials do it but I don't see any reason to do so. What is it exactly? This source states that "SecurityContextRepository is similar to userDetailsService provided in regular spring security that compares the username and password of the user." but I think he means ReactiveUserDetailsService (neither UserDetailsService nor ReactiveUserDetailsService does that by the way, it's just for user lookup).
The answer here is probably no. You see Spring security 4 had very bad support for oauth2 and especially JWT. So people got accustomed to writing their own JWT parsers. When spring Security 5 came, Spring implemented a jwt filter that you can configure and use built in. But there are a lot of outdated Spring Security tutorials out there and foremost there are a lot of developers that don't read the official documentation.
They mostly google tutorials and get the wrong information and then work on that.
But easy explained:
SecurityContextRepository
If you have session based authentication (server establishes a session with a client) it will store the SecurityContext (session) in ThreadLocal during a request. But as soon as the request ends, the session will go lost unless we store it somewhere. The SecurityContextPersistenceFilter will use the SecurityContextRepository to extract the session from ThreadLocal and store it, most common is to store it in the HttpSession.
AuthenticationManager
Override this if you want to do a custom authentication process. Example if you want to validate something, call a custom LDAP, database, etc etc. It\s here you perform you authentication. But remember, most standard logins (like ldap, sql-servers, basic login etc.) already have prebuilt configurable managers implemented, when you select what login type like .httpBasic() you will get a pre-implemented AuthenticationManager.
UserDetailsManager
You override this when you want create a custom UserDetails object (also usually called Principal) In the UserDetailsManager you do you database lookup and fetch the user and then build and return a UserDetails object.
Those two interfaces are the most regular custom implementations, and are used if you need to to basic authentication/session based authentication.
If you wish to do token, you have to think about, who is the token issuer? usually the issuer is separate and all services just get tokens and validate them against the issuer.
I hope this explains some of the questions. I have written this on the bus so some things are probably wrong and not 100% correct etc. etc.

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

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

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