Spring Security don't allow resouce - spring-security

I have configuration
http.csrf().disable();
http.authorizeRequests()
.antMatchers("/**").authenticated()
.antMatchers("/shutdown").permitAll()
.and().formLogin().passwordParameter("password").usernameParameter("username")
.and().formLogin().loginPage("/authentication.html").permitAll()
.and().formLogin().loginProcessingUrl("/login")
.and().formLogin().failureUrl("/authentication.html")
.and().formLogin().defaultSuccessUrl("/",false);
Authentication works perfectly but I don't have access to /shutdown without authentication. What could be the reason of this?
/shutdown - Shutdown hook of spring boot.

As already mentioned "/**" means any request and only the first pattern that is matched will be used. One thing to note is that you can cleanup your configuration quite a bit. See the cleaner version below:
http
.csrf().disable()
.authorizeRequests()
.antMatchers("/shutdown").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/authentication.html")
.loginProcessingUrl("/login")
.failureUrl("/authentication.html")
.permitAll();
Highlights of the changes:
You should not ever need to type http twice. You can do this of course, but it is not required and it saves you typing
.antMatchers("/**") has an alias of .anyRequest() which reads a lot nicer
when specifying properties for .formLogin() you only need to specify .formLogin() once. Like, http, you can state it multiple times, but it is a lot more concise not to do this
defaultSuccessUrl does not need the false parameter (it is the equivalent of omitting the parameter all together). For example, instead of .defaultSuccessUrl("/", false), you can state .defaultSuccessUrl("/"). Furthermore, the default value for .defaultSuccessUrl is already "/". This means you can remove it all together.
You will notice that I follow an exact formatting for the JavaConfig that is outlined in this blog

It's normal. Spring tries patterns in sequence and stops at the first that matches. As your first pattern is /** it catches all and next patterns are not even analyzed. You should always put the catchall as last pattern :
http.csrf().disable();
http.authorizeRequests()
.antMatchers("/shutdown").permitAll()
.antMatchers("/**").authenticated()
.and().formLogin().passwordParameter("password").usernameParameter("username")
.and().formLogin().loginPage("/authentication.html").permitAll()
.and().formLogin().loginProcessingUrl("/login")
.and().formLogin().failureUrl("/authentication.html")
.and().formLogin().defaultSuccessUrl("/",false);

It is intentionally designed that way. See the Actuator endpoints description in Spring Boot Guide. And for a good reason. It's a bad idea to leave the shutdown hook open without any security. Anyone who knows the url could shutdown your application.

Related

Using 2 different rules (like a or()) for the same url in Spring Security

I need to secure url so there are 2 possible ways to access:
the client has a specific ip
or the client needs to be logged in
So, I need to give two rule for a single URL, using something like the or method below:
.antMatchers("/url/**").authenticated().or().hasIpAddress("192.bla.bla")
Is there a way to accomplish that?
You can combine them using SPEL.
String expression = "hasIpAddress('127.0.0.1') or hasRole('ROLE_USER')";
http
.authorizeRequests()
.antMatchers("/home").access(expression)

Exclude one url from web security

I have the following in my spring web security
http
.headers()
.and()
.sessionManagement()
.and()
.authorizeRequests()
.antMatchers("/api/info").permitAll()
.antMatchers("/api/**").authenticated();
Which works fine except for I have one url which I want to allow a permitAll on e.g. /api/state/???
I have tried a few things which do not work (authentication fails) e.g.
.antMatchers("/api/**").authenticated();
.antMatchers("/api/state/**").permitAll();
What I am looking for is a way to add an exclude to the following
.antMatchers("/api/**").authenticated();
I want to avoid listing all urls under api and setting them to authenticated
Looks like the problem is in order of rules. You should first declare permitAll rules:
.antMatchers("/api/state/**").permitAll()
.antMatchers("/api/**").authenticated();

Grails Spring Security url intercept exclude one url from pattern restriction

Using grails spring security plugin, how do I make an exception to an intercept rule.
I want to lock down most urls in a directory with a couple of exceptions.
grails.plugin.springsecurity.interceptUrlMap = [
//allow low level users to view
"/projects/list":["IS_AUTHENTICATED_FULLY","ROLE_CASUAL"],
//lock down all others
"/projects/**":["IS_AUTHENTICATED_FULLY","ROLE_MANAGER"]
]
The wild card overrides the exception to the rule.
Reversing the order doesn't work either.

Vaadin + SpringBoot integration and SecurityContextHolder.getContext() is null

I'm using VAADIN with SpringBoot based on https://vaadin.com/spring . Things are working fine except of authentication. I'm using SpringBoot based SpringSecurity java config which works fine and SecurityContextHolder.getContext().getAuthentication() returns current user for me in VaadinUI. My config is pretty straighforward here:
http.authorizeRequests()
.antMatchers("/*").authenticated().and().httpBasic()
The problem is that SecurityContextHolder.getContext().getAuthentication() returns correct value only for the first request when VaadinUI is displayed. Then any subsequent Vaadin request (e.g. button click) returns null for SecurityContextHolder.getContext().getAuthentication() . Any idea how to make it work as expected?
This is because of the way Vaadin handles the requests. It does not use DispatcherServlet, and you probably need to use RequestContextListener (or RequestContextFilter) to enable request and session scopes.
Have a look discussion about a related topic here.
Make sure that your #Configuration class that extends WebSecurityConfigurerAdapter is annotated with #EnableWebSecurity.

Unable to redirect to LoginUI using #SpringUI(/login) when using Spring Security

I have a project where I've integrated Vaadin with Spring Boot. One of the dependency that I use is spring-boot-starter-security.
When I invoke the url http://localhost:8080/appXYZ/ it redirects me to http://localhost:8080/appXYZ/login. I'm expecting it to go to my LoginUI class with has the annotation #SpringUI("/login"). It does not, I'm redirected to some other page which has a username/password form.
pom.xml: https://gist.github.com/anonymous/4cc27b3d9e59f67839bf
Application.java (which starts the Spring Boot app): https://gist.github.com/anonymous/6748b81d26b486dc617c
LoginUI (where I'm trying to go): https://gist.github.com/anonymous/a98f5099d5daa27fb391
Just did a quick experiment where I commented out all the Spring Security stuff.
When I tried the url http://localhost:8080/appXYZ/login, I did get to the LoginUI page.
Just have to fix the issues with Spring Security. But the #SpringUI("/login") redirect is working.
You need to also overwrite the configure(HttpSecurity http) method in your MySecurityConfigurer and specify a login page for Spring to redirect to when the user is not authenticated and is trying to access for example the /authorized path, while allowing access for all users to /login and other adjacent resources (/VAADIN, /UIDL, etc).
The following snippet is extracted from my answer to your other question as they are in close relation:
I changed a bit the ApplicationSecurity.configure(HttpSecurity http) method to http.csrf().disable().authorizeRequests().anyRequest().permitAll(); and I was able to proceed to the second screen. Now this may not be that safe from what I gathered, but it should give you a starting point.
Note: You may already know this but if you don't and it saves you some time I'm glad to share this as well, because it took me a while to figure it out. Depending on how you will setup your app security you may end up changing that method to something like below.
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable().
exceptionHandling().authenticationEntryPoint(new LoginUrlAuthenticationEntryPoint("/login")).accessDeniedPage("/accessDenied")
.and().authorizeRequests()
.antMatchers("/VAADIN/**", "/PUSH/**", "/UIDL/**","/login", "/login/**", "/error/**", "/accessDenied/**").permitAll()
.antMatchers("/authorized", "/**").fullyAuthenticated();
}

Resources