Nullify some properties when getting the response from a method - Spring Security - spring

I have the bellow apis in my application. My application manages spring security and in the logic there are some rules like based on the user's role , the user might be able to see or not certain attributes.
So my requirement it is to make null some attributes of the CustomObject based on the user's role.
Is there a way to accomplish this based with Spring Security ? There is the #PostFilter annotation but I think it will be useful to discard objects in the method's response , but not to make some attributes of the object null
public List<CustomObject> getCustomObjects()
public CustomObject getCustomObject()
If this is not possible with only spring security, I am thinking to create a custom annotation , mixed with some AOP to do the work, what do you think ?

Related

Apply #PostFilter / #PostAuthorize for all endpoints

I have been able to use #PostFilter / #PostAuthorize successfully as follows:
#RestController
public class MyController{
#PostFilter("hasPermission(filterObject, 'blah')")
public List<MyObject> getIt();
}
However, what I would like to do is configure the hasPermission (or some similar) check on all endpoints in my application. In other words, doing something like a Spring Security Fitler but using the domain object prior to it being marshalled in the HttpServletResponse. I would prefer not to use a Filter because of the marshalling / unmarshalling aspect especially when doing filtering (#PostFilter) as it changes the result.
The idea is that I would like this filtering behavior to be a cross-cutting security concern and therefore not have to remember to add it to each endpoint as it is added. This would also allow me to do testing of this filtering once for the application instead of for each endpoint.

How can I retrieve io.swagger.models.Swagger object in a jersey+swagger-based system?

I want to get io.swagger.models.Swagger object in my system, which is a restful backend based on jersey and swagger.
I saw in class ApiListingResource there is such a statement
Swagger swagger = (Swagger) context.getAttribute("swagger");
, which can retrieve the swagger object from servlet context.
Can I do the same in my own code? This seems not a contract that the attribute name will always be "swagger". So I dare not.
Is there any reliable way to retrieve the object?
You can rely on the context (yes, it is set to the name swagger, or with your own logic by extending BeanConfig

Spring Security - JEE tag with user-service-ref attribute loses mapped roles

I'm pretty new to spring, let along spring security, and I've been looking at the Schema files and noticed a <jee> tag that appears under the <http> tag which acts like some sort of preauth filter magic. Using the mappable-roles attribute, I can get the role that I want but, when I specify a different user-service-ref attribute, specifying a UserDetailsService object, I lose the role.
My guess is because when I specify the UserDetailsService object, Spring assumes I don't need the role anymore... but I do!
Any ideas on this? Can I capture those details somehow? If not with this simple <jee> tag, what does the jee tag expand to for custom-filters and pre-auth, etc?
The <jee> tag creates (among others) a PreAuthenticatedAuthenticationProvider bean which delegates to a configured strategy for loading user details.
The default implementation of this strategy is PreAuthenticatedGrantedAuthoritiesUserDetailsService which will simply copy the roles it finds in the authentication token.
By overriding this default strategy with your custom UserDetailsService using the user-service-ref attribute you take the responsibility for assigning roles to the user. If you want to keep the default behavior regarding user roles, you can simply copy the related line from the above mentioned class, as the Java EE roles are still mapped, and are accessible in the auth token to your own code as well.

use existing domain classes with Spring Security plugin

I'm trying to convert a Stripes web app to Grails. The Stripes app uses Spring Security, but I would like the Grails app to use the Spring Security Grails plugin.
The app already has User and Role (Java) classes that I need to reuse, i.e. I cannot use the Grails domain classes that the s2-quickstart script generates.
The Spring Security plugin docs describe how to use an existing User domain class. The steps seem to be:
define a UserDetails implementation that reads from the existing User domain class
define a custom UserDetailsService implementation that returns instances of (1)
register an instance of (2) as a Spring bean named userDetailsService.
However the docs don't provide any information about how to use an existing Role class and the class that represents the many-to-many relationship between User and Role.
What other steps are necessary to use existing Role, User, and UserRole classes with the Grails Spring Security plugin? Is there any reason for me to run the s2-quickstart script if I don't want to generate any domain classes?
Follow-Up Questions to Burt's Answer
In the end, what you need is a new GrailsUser
Presumably GrailsUser here refers to the custom UserDetails implementation? In my case I'll probably just implement the interface directly. Does something like this seem reasonable?
class UserAdapter implements UserDetails {
private String password
private Collection<GrantedAuthority> springRoles
UserAdapter(User user) {
this.password = user.password
Collection<Role> roles = // load legacy Role objects
this.springRoles = roles.collect { new GrantedAuthorityImpl(it.authority) }
}
// If using password hashing, presumably this is the hashed password?
String getPassword() {
password
}
///////// other UserDetails methods omitted
Collection<GrantedAuthority> getAuthorities() {
springRoles
}
}
I'm not storing the whole User object within UserAdapter because of your warning about storing a potentially large object in the HTTP session.
what you need is.....and a List of GrantedAuthority instances (and the id if it's a GrailsUser)
If I use my own UserDetails implementation as above, then presumably I can ignore this comment about providing an id?
Finally, if I follow the approach outlined above, should I set these properties in Config.groovy and do I need to run the s2-quickstart script (or any others)?
Keep in mind that Spring Security doesn't care where the data comes from, it just needs a UserDetails instance when authenticating with the DAO auth provider and it can come from anywhere. It's convenient to use domain classes and database tables, but it's just one approach. Do what works for your data. In the end, what you need is a new GrailsUser (or some other impl) instance with the username and password set, the 3 booleans set, and a List of GrantedAuthority instances (and the id if it's a GrailsUser).
The simplest thing to do when you have legacy user and role data is to create a custom UserDetailsService. Use GORM, raw SQL queries, whatever you need to get the required data.
Another option is to write your own AuthenticationProvider like Glen did here: http://blogs.bytecode.com.au/glen/2010/01/15/hacking-custom-authentication-providers-with-grails-spring-security.html - although that's a larger solution that also involves a custom filter which you wouldn't need. The DAO provider uses a UserDetailsService but it's fine to create your own that combines the functionality into one class.
It's not a good idea to reuse your User domain class as the UserDetails though. Even if you implement the interface, you'd be storing a disconnected potentially large (if there are attached collections) object in the HTTP session. The POJO/POGO implementations (Spring Security's User class, the plugin's GrailsUser class, etc.) are very small and just a few Strings and booleans.
within the config.groovy file you have to specify your domain classes to use:
grails.plugins.springsecurity.userLookup.userDomainClassName = 'your.package.User'
grails.plugins.springsecurity.userLookup.authorityJoinClassName = 'your.package.UserRole'
grails.plugins.springsecurity.authority.className = 'your.package.Role'
i thinks it's not neccessary to implement your own userDetail service, because spring security uses
SpringSecurityUtils.securityConfig.userLookup
method to determine the domain class you configured before. your domain classes must provide the required fields and relations.

Can I use expressions in Apache Shiro security annotations?

I've been doing some comparisons between Apache Shiro and Spring Security - I'm really loving the security model that Shiro uses and believe it to be far cleaner that Spring Security.
However, one big nice-to-have would be to be able to reference method parameters from within the method-level security annotations. For example, right now I could so something like:
#RequiresPermissions("account:send:*")
public void sendEmail( EmailAccount account, String to, String subject, String message) { ... }
Within the context of this example, this means that the authenticated user must have the permission to send emails on email accounts.
However, this is not fine-grained enough, as I want instance level permissions! In this context, assume that users can have permissions on instances of email accounts. So, I'd like to write the previous code something like this:
#RequiresPermissions("account:send:${account.id}")
public void sendEmail( EmailAccount account, String to, String subject, String message) { ... }
In this way, the permission string is referencing a parameter passed into the method such that the method can be secured against a particular instance of EmailAccount.
I know I could easily do this from plain Java code within the method, but it would be great to achieve the same thing using annotations - I know Spring Security supports Spring EL expressions in its annotations.
Is this definitely not a feature of Shiro and thus will I have to write my own custom annotations?
Thanks,
Andrew
Look at the classes in http://shiro.apache.org/static/current/apidocs/org/apache/shiro/authz/aop/package-summary.html, especially PermissionAnnotationHandler. There you can see that all Shiro does when encountering the #RequiresPermissions annotation is call getSubject().isPermitted(permission) and does no substitution inside the annotation value at all. You would have to somehow override that handler if you wanted this kind of functionality.
So to answer your question: yes, this is definitely not a feature of Shiro and you have to either write your own annotation or somehow override that handler.
This feature is currently not supported by Shiro. Multiple people have requested this feature. Perhaps we can vote for the issue?
https://issues.apache.org/jira/browse/SHIRO-484
https://issues.apache.org/jira/browse/SHIRO-77
https://issues.apache.org/jira/browse/SHIRO-417
https://issues.apache.org/jira/browse/SHIRO-331

Resources