I'm currently working on a spring-boot 2.0 REST backend for a web-application. The spring-boot application receives OAuth2 AccessTokens for authentication with application specific roles for authorization. Now I want to secure various REST endpoints and methods based on the OAuth2 roles. I'm loking for a solution that does not couple my code directly to the roles, not like #PreAuthorize("hasRole('ADMIN')").
In addition to the authorization, the REST endpoints should also return customized results (e.g. if the request contains an valid OAuth2 token with the role 'company_A_internal', the response should contain a result-set filtered on 'company_A').
What I've already accomplished so far:
The authentication based on the OAuth2 token with the help of the spring-security
The mapping of the OAuth2 token roles to the spring-security GrantedAuthorities so that SecurityContextHolder.getContext().getAuthentication().getAuthorities() returns the former roles
What I'm looking for:
Based on the roles (now stored in the GrantedAuthorities) the REST endpoints should be secured by a separate mechanism. I did some research and came across a really interesting article.
I would like to implement something similar to this (e.g. as a separate roles_config.yml):
order_manager:
'/orders':
- 'GET'
- 'POST'
- 'PUT'
- 'DELETE'
order_editor:
'/orders':
- 'GET'
- 'POST'
- 'PUT'
order_inspector:
'/orders':
- 'GET'
Afterwards I'd only have to implement something like this in the spring-boot context:
#Secured
#RequestMapping("/orders")
public void updateOrder (Order order) {
Order updatedOrder = process(order);
return updatedOrder;
}
How will this work in the context of spring-security? Is there any possible way of implementing this on top of my current setup?
I appreciate any kind of recommendations and help and will gladly answer to comments and further questions.
You could try https://github.com/vsfexperts/rbac . You'll have to configure the mapping from role to privileges and annotate your endpoints with #Secured("some_privilege").
Just keep in mind that this is static and doesn't allow content based security e.g. access to /orders/5 won't be restricted to user x, who's the owner of 5. It will only be restricted by a role, which has the privilege annotated with /orders endpoint (e.g. #Secured("some_privilege")).
Related
I implemented a micro-services architecture. Before accessing each micro-service the request gets through a gateway that checks the authentication and in the process adds an X-User header containing the user id.
In each of my micro-services, I would like to be able to retrieve this user (X-User) in an elegant way: without adding the HttpRequest/#RequestHeader to all my Controllers and pass it to the services, etc.
Using something like "SecurityContextHolder.getContext().getAuthentication().getUserId();" would be perfect but as I don't manage the Authentication in my micro services it's not possible.
You should be able to:
implement a Servlet Filter (see this Baeldung article for details) that gets the userId from the ServletRequest and stores it in a ThreadLocal (see this Baeldung article for details)
retrieve that ThreadLocal from any class that would need the userId
Good luck!
I am trying to understand if there is a way to use spring security which helps my used case. Basically, I want to call spring security on each REST call in spring boot, rather than one time during the start of the application, and find the role of the user and further restrict endpoints based on the user roles.
I have 3 different rest controllers namely /admin1/*, /admin2/*, /admin3/*.
I have tried restricting endpoints manually as below.
http.authorizeRequests()
.antMatchers("/admin1/**").permitAll()
.and()
.authorizeRequests()
.antMatchers("/admin2/**").permitAll()
.anyRequest().authenticated();
This will actually allow /admin1/* and /admin2/* APIs to work and restrict /admin3/*. However, my used case is as below.
In each rest call, we pass the user id in the header. I would like to use spring security on each rest call, and use the user id from the header to find the user roles from the database.
If user has ADMIN 1 user role, we have to just enable /admin1/* endpoints and restrict /admin2/* and /admin3/*. Similarly, if user has ADMIN 2 user role, we have to just enable /admin2/* endpoints and restrict /admin1/* and /admin3/*. In the same way, if user has ADMIN 3 user role, we have to just enable /admin3/* endpoints and restrict /admin1/* and /admin2/*.
Is there a way to achieve this using spring security?
Thank you
AS far as I understood, you want to authenticate & authorize users on each call. True?
one way is tokenizing your REST APIs with JWT (JSON Web Token).
The example in https://dzone.com/articles/spring-boot-security-json-web-tokenjwt-hello-world would probably help.
I Also suggest that instead of using antMatchers In configure method to restrict URL access based on Roles, you use #PreAuthorize and #PostAuthorize annotations above the classes or methods you want to secure. This way gives you more flexibility on your restriction policies.
The example in https://www.baeldung.com/spring-security-method-security also may help you with that.
I have a REST service implemented using Spring MVC (RestControllers) with token based security (using Spring Security). How can i filter resources depending on user identity? Let's say user has some reports. How can I let authorized user by performing a call to /reports to see only his reports?
Obviously i can make userId to be a request parameter or path variable, but something tells me that this is a bad practice.
I assume i can achieve that using Spring Security features, but how exactly could i do that and, more important, where is the most appropriate place to apply such filtering? Should controllers perform calls to services passing user identity or should it be somehow retrieved at repositories level (I use Spring Data JPA)?
Thanks in advance
You have Authentication object whenever a user is successfully logged in.
It contains Object principal Object credentials and Set authorities.
All you need to do is override UserDetailsService to add new parameters for your authenticated user. Add your userId in authentication as shown in blog
Now when you do
SecurityContextHolder.getContext().getAuthentication().getPrincipal()
this will return you the User object of the spring security.
You can get the user id from here and use this in controller to do necessary actions.
Generally all rest based framework provide authenticate.
But are there any framework/lib/pattern that helps to secure rest endpoint with following capability
Only a authenticated user with following roles can access a end point with only particular params.
Basically i am trying to prevent two user(with same roles) to view each other data by passing each other id in request urls
Yeah you should look at Apache Shiro it offers really good support role base/permission based authorization.
An example of how you can annotate an endpoint would be:
#RequiresRoles(value = "admin")
I'd recommend you to check the Instance-Level Access Control of this document.
I would like to develop a portal which contains some modules
The portal and each module consume data provided by a webservice based on Jersey and secured with OAuth 1.0
For the moment I have almost implement the OAuth provider
A user can connect to the portal and access to a module
Each app or module has a specific access token to consume resource
What I want to do is to add a role implementation
For example for the module1, the user can have 2 roles (role1 and role2) but can't use the 2 roles in parallel
First the user uses the access (module1 / user1 / role1) and he will have a token and later the user uses the access (module1 / user1 / role2) and he will have an other token
Depending on the role, I would like to filter the request with a RolesAllowed annotation for example
I have read this article: http://objecthunter.congrace.de/tinybo/blog/articles/89
When the user is authenticated to the web service I could persist in a database the username, and the role used for the module and the RolesAllowedResourceFilterFactory could use the realm to check if the user is in the role and can access to the resource
But can I by-passed the auth method?
Anyway I really need your help to implement this role filter thing
I will try to give you more details if you need
Thanks
The Jersey oauth filter sets the security context based on what access token was used. You just have to make sure your custom implementation of the oauth provider assigns a token with the right return values from the isInRole() method when called with various roles. The role for a given token can be established during the token authorization flow (e.g. the client can request a particular role using a custom parameter that it passes to the server when requesting a request token (this gets passed in the parameters parameter to the provider.newRequestToken() method).
The security context that the oauth filter sets will delegate to the token isInRole() method when determining the roles - and the RolesAllowedResourceFilterFactory relies on the security context. So, everything should work as expected if OAuthToken.isInRole() returns the right value. Are you facing any issues?
I know it is an old post but I was facing similar issue. In my case I solved it exactly the same way as Martin described. During token authorisation I set allowed roles:
String verifier = provider.authorizeToken(token, sContext.getUserPrincipal(), roles);
where provider is #Context DefaultOAuthProvider, token is DefaultOAuthProvider.Token and roles is a Set of roles I want to allow the access by this token:
Set<String> roles = new HashSet<String>();
roles.add("someRole");
Then in my service I just use a #Context SecurityContext method isUserInRole("someRole") which gives me true in case the user is in specified role and false if not:
if (sContext.isUserInRole("someRole")) {
....
}
Hope it will help somebody.