I was trying to use the Role Hierarchy feature provided by Spring Security in a Spring Boot application and I found some problems with the java config.
In that application, I've the GlobalMethodSecurity enabled in order to use the #PreAuthorize annotations. Because of that, what I need to do in order to use the Role Hierarchy support is to create a new instance of a DefaultMethodSecurityExpressionHandler and set an instance of a RoleHierarchyImpl instance with the configuration that we want (the role hierarchy itself).
Although, if I try to do this using a WebSecurityConfigurerAdapter and the configure(HttpSecurity http) method, I'm not able to do that because the .expressionHandler() is expecting a SecurityExpressionHandler<FilterInvocation> and the DefaultMethodSecurityExpressionHandler is a SecurityExpressionHandler<MethodInvocation>.
In order to solve this problem, I found out that the solution is to create a subclass of GlobalMethodSecurityConfiguration and override the method that is creating the ExpressionHandler bean like it's described in the docs
GlobalMethodSecurityConfiguration - Spring Security Docs
By saying this, I'm wondering if the .expressionHandler() method shouldn't also allow to do this configuration. If not, maybe a reference in the javadoc pointing to the GlobalMethodSecurityConfiguration would be useful.
After this, I think that the idea of WebSecurityConfigurerAdapter and the .expressionHandler are just applied to the security that is applied based on a Filter of the http request and it isn't supposed to be applied at the method level, but opinions and advices are welcome to confirm that I'm doing as it's supposed.
Related
I'm working on a Spring web application (not Spring Boot) that uses Spring Security 5.3.3, Spring Security OAuth 2.5.0, and configures it like this:
http.authorizeRequests().
antMatchers(permitUrls).
permitAll().
anyRequest().
authenticated().
and().
oauth2ResourceServer().
jwt();
Our clients report occasional 401 responses which we can't find in our application logs, so we assume it's from the Spring Security itself. We would like to log authentication and authorization failures, but I'm confused as to what is the current preferred method to achieve that.
A quick search reveals 4 paths:
custom AuthenticationFailureHandler (seems like this one is only available in FormLoginConfigurer, which isn't our case)
custom AuthenticationEntryPoint (this one is available with JWT, but OAuth2AuthenticationEntryPoint which I was going to extend is deprecated with an unhelpful message). I could try using HttpStatusEntryPoint instead, but I'd like to avoid changing the current behavior of my app, just want to add logging.
custom Filter (probably, not the cleanest path)
AuditApplicationEvents — looks beautiful, but seems like it's for Spring Boot only.
Could anyone provide me with some guidance on this?
I suggest activating the logger of org.springframework.security by changing its log level to DEBUG.
Based on your log tools (log4j2, logback, ...) create a logger in your log configurations with name org.springframework.security and level DEBUG.
What is the difference between those two? When do I use one over the other?
In the Spring Security Documentation it says that, among other things, WebMvcConfigurer has the following feature:
Require authentication to every URL in your application
The WebSecurityConfigurerAdapter example shown in HttpSecurity says:
Ensures that any request to our application requires the user to be authenticated.
Isn't that the same?
EDIT
These two types of configs seem to serve different purposes, I just don't quite understand yet, when to use which: What are the two distinct scenarios for each of the config types?
In the introduction to the HttpSecuriy section, it says
How does Spring Security know that we want to require all users to be authenticated? How does Spring Security know we want to support form based authentication?
So right now I am thinking: the first one says what should happen when authenticating a user and the second says in what cases do users need to be authenticated. Is that correct?
E.g., the first config "Generate a login form for you" and the second determines, when that login form should be shown?
This does appear to be a documentation bug (https://github.com/spring-projects/spring-security/issues/6809):
This raises confusion about the role of WebMvcConfigurer in Spring Security and the use cases for WebMvcConfigurer vs WebSecurityConfigurerAdapter.
Most likely the intention in the example was:
#EnableWebSecurity
public class WebSecurityConfig implements WebSecurityConfigurerAdapter {
instead of
#EnableWebSecurity
public class WebSecurityConfig implements WebMvcConfigurer {
I own the role student in my Spring Security Core. The role student can edit your information. But if he wants to edit another user's information that's also possible.
#Secured(['ROLE_ADMIN','ROLE_STUDENT'])
#PreAuthorize('isAuthenticated() and principal?.id == #studentInstance.id')
def edit(Student studentInstance) {
respond studentInstance
}
I used the ACL plugin, but it did not work. You can still edit another student.
You can use #Secured in controllers because the core plugin looks for them and builds the corresponding access rule checks for you, but none of the other Spring Security annotations are supported in controllers.
Instead, annotate a service method and call it from the controller. Spring Security wraps annotated Spring beans (e.g. services) in proxies that perform the checks and only call the bean methods if the checks succeed.
I'm using latest version of both Spring LDAP and Spring security. Also, I'm using annotation based configuration and I have no XML configuration files.
What I'm trying to achieve is really basic, I want to be able to allow users to change their password from my web application.
I've found that I could execute that request through DirContext.modifyAttributes. This method requires two attributes, the first one is the current userDn, which I'm not sure how to easily get through Spring. I'm pretty sure that there's a functionality to get it.
Then using a password Attribute as modification item for the second argument. Now, how can I know the password encoding that needs to be applied to the password provided by the user?
I've never used Spring LDAP / Security and a small, simple example would be awesome. Right now, I'm testing against in-memory ldap, but I'll have to switch to a real LDAP at the end of the week.
Thanks!
You need to use an instance of org.springframework.security.ldap.userdetails.LdapUserDetailsManager, it implements UserDetailsManager and has methods for changing user passwords. To instantiate it in your non-XML configuration, do something like this:
#Bean
public UserDetailsService getUserDetailsService() {
return new LdapUserDetailsManager(); // TODO give it whatever constructor params it needs
}
I'm writing a pair of aspects. The first is to trap usernames when users successfully authenticate against my web app and the other is to trap when they explicitly logout. I'm having trouble finding Spring framework methods which are called only once and which will therefore let me capture this information.
We are using a basic Spring Security 3.0 configuration, with our only additions being to provide our own UserDetailsService implementation.
Can anyone help?
It turns out that this was completely the wrong way to do this. Spring has a set of baked-in ApplicationEvent classes which you can create ApplicationListeners to catch. Strangely, there seems to be no "LogoutEvent" but there are the very useful AuthenticationSuccessEvent, AbstractAuthenticationFailureEvent, HttpSessionCreationEvent and HttpSessionDestroyedEvent. Most interesting of all is the RequestHandledEvent.
To catch these I created my own bean which implemented
org.springframework.context.ApplicationListener;
and overrode
public void onApplicationEvent(ApplicationEvent appEvent)
In this I just if/else my way through the various appEvent types and take the appropriate actions to track users and sessions.