How does #Secured know what role a user is from database? - java

I understand what #Secured DOES but not really sure HOW it does it.
Can someone explain how #Secured grabs the roles? Is it getting it from the authorities-by-username-query? Can I put any String in the params as long as it's in the database?

User's roles are stored in SecurityContext, or to be more specific in Authentication object that is stored in the SecurityContext. When you authenticate, the authentication information is loaded and stored in the security context. The roles can originate from database, depending on your configuration. In your case they are loaded using authorities-by-username-query query.
When the security interceptor processes the authorization (for instance method-level authorization using #Secured annotation) it determines whether the user should be able to access it based on the Authentication stored in the context.
To better understand what happens under the hood, you should look at the Spring Security Filter chain and Architecture section of the reference guide.

SpringSecurity provides and awesome AOP way of securing methods in
Java Application by using #Secured. Spring logically ORs the roles
listed in #Secured annotation. The collection of GrantedAuthorities is obtained from SecurityContextHolder.getContext().getAuthentication().getAuthorities()
AbstractSecurityInterceptor is the abstract class that implements
security interception for secure objects.
Obtain the Authentication object from the SecurityContextHolder.
Determine if the request relates to a secured or public invocation
by looking up the secure object request against the SecurityMetadataSource.
For an invocation that is secured (there is a list of
ConfigAttributes for the secure object invocation):
If either the Authentication.isAuthenticated() returns false, or the alwaysReauthenticate is true, authenticate the request against the configured AuthenticationManager. When authenticated, replace the Authentication object on the SecurityContextHolder with the returned value.
Authorize the request against the configured AccessDecisionManager.
Perform any run-as replacement via the configured RunAsManager.
Pass control back to the concrete subclass, which will actually proceed with executing the object. A InterceptorStatusToken is returned so that after the subclass has finished proceeding with execution of the object, its finally clause can ensure the AbstractSecurityInterceptor is re-called and tidies up correctly using finallyInvocation(InterceptorStatusToken).
The concrete subclass will re-call the AbstractSecurityInterceptor via the afterInvocation (InterceptorStatusToken, Object) method.
If the RunAsManager replaced the Authentication object, return the SecurityContextHolder to the object that existed after the call to AuthenticationManager.
If an AfterInvocationManager is defined, invoke the invocation manager and allow it to replace the object due to be returned to the caller.
Look at the source code for more understanding.
AccessDecisionManager is the interface which is implemented as AffirmativeBased, ConsensusBased or UnanimousBased orchestrates the voters and asks each in turn whether the requesting user should be let through the #Secured annotation or denied.

Related

Spring Security Authentication Provider autenticate()'s reason for returning null

Lately, I was studying Spring security's Authentication provider.
In the authenticate() method the docs say, "May return null if the AuthenticationProvider is unable to support authentication of the passed Authentication object. In such a case, the next AuthenticationProvider that supports the presented Authentication class will be tried."
We have another method supports() that indicates that if this provider supports the type of authentication or not.
As far as I know "AuthenticationManager" first calls supports() to check if the provider supports this type or not. Then the authenticate() method is called. So, from my understanding authenticate is only called when the provider supports it.
So, My question is " If the provider supports this type of auth, then why should it return null from authenticating ()? and why do the docs say "May return null if the AuthenticationProvider is unable to support authentication of the passed Authentication object" ??? Should it not always support it? (Because we checked its compatibility via supports().)
Can you give an example where the provider needs to return null?
Thanks in advance.
quote from Spring Security in Action by Laurentiu Spilca
The second method in the AuthenticationProvider interface is supports-
(Class<?> authentication). You can implement this method to return
true if the current AuthenticationProvider supports the type provided
as an Authentication object. Observe that even if this method returns
true for an object, there is still a chance that the authenticate()
method rejects the request by returning null. Spring Security is
designed like this to be more flexible and to allow you to implement
an AuthenticationProvider that can reject an authentication request
based on the request’s details, not only by its type.
and its analogy I think clear things up.
An analogy of how the authentication manager and authentication
provider work together to validate or invalidate an authentication
request is having a more complex lock for your door. You can open this
lock either by using a card or an old fashioned physical key
. The lock itself is the authentication manager that decides whether to open the door. To make that decision, it delegates to the
two authentication providers: one that knows how to validate the card
or the other that knows how to verify the physical key. If you present
a card to open the door, the authentication provider that works only with physical keys complains that it doesn’t know this kind of authentication.
But the other provider supports this kind of authentication and verifies whether the
card is valid for the door. This is actually the purpose of the supports() methods.
Besides testing the authentication type, Spring Security adds one more layer for
flexibility. The door’s lock can recognize multiple kinds of cards. In this case, when
you present a card, one of the authentication providers could say, “I understand this
as being a card. But it isn’t the type of card I can validate!” This happens when supports() returns true but authenticate() returns null.

REST service to return only current user-related resources

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.

Custom PermissionEvaluator for authorizing resource access for each REST Resource

I have implemented a REST application with some complicated authorization requirements.
Here's a summary
My customers purchase a proxy device called Collector that enables their home automation control to be centralized. My customers also purchase multiple home automation devices (let's call them HADevices) that report their metrics through the collector to my REST application.
An admin(who is my customer service rep), with role ROLE_ADMIN, should be able to look at any data from any Collector or HADevice. A customer, with role ROLE_USER role, should only be able to view data about the Collector or an HADevice that s/he owns.
The Collector, with role ROLE_COLLECTOR is the only role authorized to insert data i.e. create or update a resource in my REST service. Let's call this url /deviceMetrics (POST). A Collector can insert metrics for any HADevice associated with the customer. HADevices have no role and do not interact with my REST application. A Collector can only insert records to HADevices that have the same customer as the Collector.
I am using spring security 4.0 for authentication and #Secured annotation for authorization. However, I find that my code is cluttered with repetitive permission validations which take up a majority of my logic. The basic insertions and retrievals are pretty straightforward.
I want to use a PermissionEvaluator to centralize Access Control. I have to secure the following urls
GET /collectors/{id}/deviceMetrics - I retrieve the user from the
Principal and verify that the Collector with id={id} in my spring
data repository belongs to the Principal and if not I send a 403
GET/hadevices/{id}/deviceMetrics - I retrieve the user from the
Principal and verify that the HADevice with id={id} in my spring data
repository belongs to the Principal and if not I send a 403.
POST /collectors/{id}/deviceMetrics - I retrieve the Collector uniqueId
from the Principal and make sure that the Collector's id matches the
{id} in the URL
POST /hadevice/{id}/deviceMetrics - I retrieve the
Collector uniqueId from the Principal and the associated Customer. I
also pull the Customer associated with HADevice with id={id} and
compare the two. If they are unequal, I send a 403.
My application is littered with such complex authorization requirements for each REST resource, and I want to use a custom org.springframework.security.access.PermissionEvaluator, specifically by implementing the following method.
boolean hasPermission(Authentication authentication, Serializable targetId, String targetType, Object permission)
I'm planning to use a combination of targetType and request.getUrl() to get a specialized Evaluator for each url and resource.
Is there a better way to do this?
Your question is quite broad, but I think you can get away with quite simple logic for most cases.
GET /collectors/{id}/deviceMetrics
Given that you have a DeviceMetrics class with suitable properties, you can annotate your data repository with something like:
#PostAuthorize("hasRole('ROLE_ADMIN') or (hasRole('ROLE_USER') and returnObject.collector.owner = authentication.name)")
public DeviceMetrics getDeviceMetrics(long deviceId);
(This assumes that DeviceMetrics class has a property collector which has a property owner which is the username.)
That doesn't need a PermissionEvaluator at all. Maybe you need one for more complex cases:
POST /collectors/{id}/deviceMetrics
#PreAuthorize("hasRole('ROLE_COLLECTOR') and hasPermission(#collectorId, 'com.example.Collector', 'WRITE')")
public void saveDeviceMetrics(long collectorId, DeviceMetrics deviceMetrics);
You only need one PermissionEvaluator since you get all the information you need as method arguments.
For those who are wondering what my solution looks like, I borrowed from this example.
It's old and it's based on xml configuration which I am not particularly fond of. But the idea is to create a Map and initialize the custom PermissionValidator and to store the authorization logic in the Permission interface implementations.
The biggest pain point was injecting an autowired HashMap of tuples, but that's an implementation detail that reasonably experienced spring users can figure out.

What means this Spring Security diagram?

I am studying for the Spring Core certification and I have some dobut related the meaning of this Spring Security diagram finding into the documentation:
It explain what is the architecture of the Spring Security projects and the interaction between its components but what exactly mean?
It show an Authentication Manager component, reading on the documentation I found that it handles authentication requests from other parts of the framework so I think that it provide something like an interface with some methods to perform the autherntication operations and that this interface it will be implemented by a specific authentitication providerd (according to the authentication technology choose)
What means that the Authentication Manager populates the Security Context. What exactly is the *Security Context** in Spring? Is it a "place" where are stored the information related to the Principal (for example an user authenticated on a web application) and the list of the authorizations of this principal on the secured resources? (for example the logged user and what operations this user can perform on the secured resources?) Is it right or am I missing something?
Then there is a Security Interceptor that I think have to be a proxied class that use something like a before advice AOP mechanism that perform a security advice befeore some specific joint point. Thee jointpoint are the operations on the secured resource (for example the method execution on a secured bean).
Looking at the picture I think that the proxy obtain this information from the Security Context that contains the principal (the logged user) and its authorizations (what operations can do this logged user) so it can create the before advices to check this operations. Is it right or am I missing something?
What represents the AccessDecision Manager component? and what are the voters showed into the picture?
Tnx
The security-context contains the security information about the current user (name, login, privileges...). It is bounded to the current thread and session https://stackoverflow.com/a/6408377/280244
The Authentication Manger will put ( poulate ) the security information about the user when he login into the security context.
The Security interceptor (Method or Http Request) will intercept the invocations before they invoke an protected/secured resource. It obtain the information about the current user from the security context. What the requies rules to allow the invocation are, are obtained form some configuration (xml, annotations, ...). The decision about that the current user matches the required rules are delegated to the Access Decision Manger
The Access Decision Manger does not implements the desision rules by its own, instead it uses (different) Voters that vote for access granted, access denied (or abstain).
#See: Spring Security Reference: Chapter 13 Authorization Architecture

Spring Session Management

I'm using Spring for my web app. I have used several SimpleFormControllers. I've created a session in the first SimpleFormController for the login page using:
HttpSession session = request.getSession(true);
How can I protect other SimpleFormControllers using Sessions, i.e. so that other controllers won't load if the user is not loged in.
Thank you
You probably want to use Spring Security.
It's flexible and allows restrictions based on roles.
Without it, you will need to manually check in every controller whether the user logged in or not. Or you'll have to "reinvent" a security framework by adding filter to the webapp.
If you only want to protect the operation of getting the session, you need to write a filter that wraps the original request and overrides the getSession methods. There you can check for login data using the original request's getSession().
BTW, getSession() is equivalent to getSession(true)
To protect the Controller from access outside of the intended Session, you may want to compare the Scoping rules you need with this clearly written Guide.
How to get Session Object In Spring MVC
The author gives an example of creating a Controller annotated with #Scope("session")

Categories