Spring Security 6 form login while restricting every other request - spring

I am migrating an application from Spring 5 to Spring 6, including the security configuration.
My original setup involved calling .permitAll() for the loginPage url and the loginProcessingUrl and then calling .anyRequest().authenticated() which ensured every other request was redirected to the login page.
I have migrated the configuration and come up with
#Bean
public SecurityFilterChain defaultSecurityConfigurationFilterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests()
.requestMatchers("/LoginPage/").permitAll()
.requestMatchers("/ValidateLogin/").permitAll()
.and()
// setup login redirection and logic
.formLogin()
.loginPage("/LoginPage")
.loginProcessingUrl("/ValidateLogin")
.usernameParameter("loginName")
.passwordParameter("password")
.failureHandler(customAuthenticationFailureHandler())
.successHandler(customAuthenticationSuccessHandler())
.and()
// setup logout
.logout()
.logoutUrl("/Logout")
.logoutSuccessUrl("/LoginPage")
.invalidateHttpSession(true)
.permitAll()
.and()
.sessionManagement()
.invalidSessionUrl("/LoginPage")
.sessionFixation()
.migrateSession()
.and()
.csrf()
.and()
// add security headers
.headers()
.frameOptions()
.sameOrigin()
.contentSecurityPolicy(CONTENT_SECURITY_POLICY)
.and()
.and()
.authorizeHttpRequests()
.anyRequest()
.authenticated();
CharacterEncodingFilter filter = new CharacterEncodingFilter();
filter.setEncoding("UTF-8");
filter.setForceEncoding(true);
http.addFilterBefore(filter, CsrfFilter.class);
MultipartFilter multipartFilter = new MultipartFilter();
multipartFilter.setServletContext(SpringContext.getBean(ServletContext.class));
http.addFilterBefore(multipartFilter, CsrfFilter.class);
http.addFilterAfter(new SessionCookieFilter(), CsrfFilter.class);
return http.build();
}
However it seems that the anyRequest().authenticated() rule is used no matter which url I try to access resulting in an infinite redirect loop where I am served a 302 to /LoginPage.
Is there any way of creating the functionality in Spring 5 where anyRequest() would catch any requests that weren't already permitted?

Related

Spring Web Security Incorrect Configuration

I am trying to enable basic http authentication for the actuator endpoints while keeping the jwt authentication for the api endpoints. I tried the following configuration for this:
#Override
public void configure(HttpSecurity http) throws Exception {
http.csrf()
.disable()
.anonymous()
.disable()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.antMatcher("/service/actuator/**")
.httpBasic()
.and()
.authorizeRequests()
.antMatchers("/service/api/**")
.authenticated()
.anyRequest()
.authenticated()
.and()
.exceptionHandling()
.authenticationEntryPoint(restAuthenticationEntryPoint);
http.addFilterBefore(jwtTokenFilter, UsernamePasswordAuthenticationFilter.class);
}
However, it appears that I can use the JWT token and basic auth as well for the actuator endpoints while no authentication also works for all the api endpoints.
Did I mess up the order? Is there a better way to do this?
the following worked for me
#Override
public void configure(HttpSecurity http) throws Exception {
http.csrf()
.disable()
.anonymous()
.disable()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/service/actuator/**")
.permitAll()
.and()
.httpBasic()
.and()
.authorizeRequests()
.antMatchers("/service/api/**")
.authenticated()
.anyRequest()
.authenticated()
.and()
.exceptionHandling()
.authenticationEntryPoint(restAuthenticationEntryPoint);
http.addFilterBefore(jwtTokenFilter, UsernamePasswordAuthenticationFilter.class);
}

When I call logout it changes the jsessionid, but still allows me to access other paths without having to log in

I'm attempting to logout using Spring Security, but any time I call the logout url it changes the jsessionid, but I can still access urls that should be restricted and ask for me to log back in.
public void configure(HttpSecurity httpSecurity) throws Exception{
httpSecurity.httpBasic();
httpSecurity.authorizeRequests()
.mvcMatchers(HttpMethod.GET, "/privateEvent").hasAuthority("REGISTERED_USER")
.mvcMatchers(HttpMethod.DELETE, "/privateEvent/*").hasAuthority("RSVP_ADMIN")
.mvcMatchers("/registerPrivateEvent").hasAuthority("REGISTERED_USER")
.mvcMatchers("/guestList").hasAuthority("EVENT_PUBLISHER")
.mvcMatchers("/eventPublishersList").hasAuthority("RSVP_ADMIN")
.anyRequest().permitAll()
.and()
.logout()
.invalidateHttpSession(true)
.deleteCookies("JSESSIONID")
.deleteCookies("XSRF-TOKEN")
.clearAuthentication(true)
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.logoutSuccessUrl("/allDone")
.permitAll()
.and()
.csrf().disable();
}

Spring Security HTTP FormLogin

I have a problem with my Spring Security
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private UsuarioService usuarioService;
#Autowired
private PasswordEncoder passwordEncoder;
#Override
protected void configure(HttpSecurity http) throws Exception {
// #formatter:off
http
.authorizeRequests()
.antMatchers(
"/",
"/index/**",
"/register",
"/doregister",
"/login",
"/dologin",
"/logout-success",
"/confirmregister",
"/invaliduser",
"/expiredtoken",
"/userstatuslog",
"/verifyemail")
.permitAll()
.anyRequest()
.authenticated()
.and()
.authorizeRequests()
.antMatchers(
"/login",
"logout")
.permitAll()
.and()
.authorizeRequests()
.antMatchers(
"/static/css/**",
"/css/custom.css",
"/js/**",
"/images/**"
)
.permitAll()
.and()
.authorizeRequests()
.antMatchers(
"/forbidden",
"/edit-profile-about",
"/doeditprofileabout",
"/profile"
)
.hasRole("USER")
.and()
.authorizeRequests()
.antMatchers(
"/controlpanel",
"/forbidden",
"/edit-profile-about",
"/doeditprofileabout",
"/profile"
)
.hasRole("ADMIN")
.and()
.formLogin()
.loginPage("/login")
.defaultSuccessUrl("/")
.permitAll()
.and()
.logout()
.deleteCookies("remove")
.invalidateHttpSession(true)
.logoutUrl("/logout")
.logoutSuccessUrl("/logout-success")
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"));
// #formatter:on
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(usuarioService).passwordEncoder(passwordEncoder);
}
Everytime, I do login it sends me to the bootstrap file...
localhost:8080/css/bootstrap-3.3.7-dist/css/bootstrap.min.css
or...
localhost:8080/css/custom.css
or...
localhost:8080/js/jquery-2.1.4.min.js
but not to the same one (it seems random! :-)
Then sometimes the CSS works and sometimes not. In the login form it has no styles, but only sometimes, because when I run the app, it has the styles. And when I do login too, but not when I logout or try to login again. So when the user is correctly logged in, it has styles again.
And when I tried to access "/controlpanel" with a user (with ROLE_USER) it allows access (and it should not), but when I do it with a user (Role_ADMIN) it works fine.
It happens when your static resources are filtered by Spring Security.
Try to ignore these resources at all:
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/path/**");
}
define patterns to meet all your locations.
The problem is that your css files is not accessible by guest. So after logging in, you will be redirected back to it. Sometime css in login page works because of browser caching.
Try to change your configuration to
http
.authorizeRequests()
.antMatchers(
"/",
"/index/**",
"/register",
...).permitAll()
.antMatchers(
"/login",
"logout").permitAll()
.antMatchers( // You need to add all css file here
"/static/css/**",
"/css/custom.css",
"/css/bootstrap-3.3.7-dist/css/bootstrap.min.cs‌​‌​‌​s",
"/js/**",
"/images/**").permitAll()
.antMatchers(
"/forbidden",
"/edit-profile-about",
"/doeditprofileabout",
"/profile").hasRole("USER")
.antMatchers(
"/controlpanel",
"/forbidden",
"/edit-profile-about",
"/doeditprofileabout",
"/profile").hasRole("ADMIN")
.anyRequest().authenticated()
.and()
...

Spring security - how come I can only access pages as ROLE_ADMIN and not ROLE_USER?

In my application, I have a SecurityConfiguration class that has the following method:
protected void configure(HttpSecurity http) throws Exception {
CharacterEncodingFilter filter = new CharacterEncodingFilter();
http.addFilterBefore(filter,CsrfFilter.class);
http
.formLogin()
.loginPage("/login")
.usernameParameter("ssoId")
.passwordParameter("password")
.and()
.authorizeRequests()
// I admit that this section needs some work
.antMatchers("/", "/home/**", "/alert/*", "/scheduler/*", "/agent/*", "/ftp/*", "/smtp/*", "/sql/*").access("hasRole('USER')")
.antMatchers("/benefit/transport/*", "/contract/*").access("hasRole('ADMIN')")
.antMatchers("/", "/home/*", "/alert/*", "/scheduler/*", "/agent/*", "/ftp/*", "/smtp/*", "/sql/*").access("hasRole('ADMIN')")
.antMatchers("/benefit/transport/*", "/contract/*").access("hasRole('ADMIN')")
.antMatchers("/admin/**").access("hasRole('ADMIN')")
.antMatchers("/db/**").access("hasRole('ADMIN') and hasRole('DBA')")
.and()
.rememberMe().rememberMeParameter("remember-me").tokenRepository(persistentTokenRepository()).tokenValiditySeconds(86400)
.and()
.csrf()
.and()
.exceptionHandling().accessDeniedPage("/accessDenied");
}
But as stated on the question, I my user has the ROLE_ADMIN privilege, access is normal throughout the application. But if he has only ROLE_USER, no pages are displayed.
What am I not seeing here?
What are you trying to achive with these lines?
.antMatchers("/", "/home/**", "/alert/*", "/scheduler/*", "/agent/*", "/ftp/*", "/smtp/*", "/sql/*").access("hasRole('USER')")
.antMatchers("/", "/home/*", "/alert/*", "/scheduler/*", "/agent/*", "/ftp/*", "/smtp/*", "/sql/*").access("hasRole('ADMIN')")
Seems to me that you are overwriting your configuration here.. So the ADMIN role would overwrite the USER role here.

Spring security not blocking all requests

I'm using Spring security 3.2 and have this configuration:
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.headers()
.addHeaderWriter(new XFrameOptionsHeaderWriter(XFrameOptionsMode.SAMEORIGIN))
.and()
.exceptionHandling()
.authenticationEntryPoint(authenticationEntryPoint)
.and()
.rememberMe()
.rememberMeServices(rememberMeServices())
.key(env.getProperty("security.rememberme.key"))
.and()
.formLogin()
.loginProcessingUrl("/app/authentication")
.successHandler(ajaxAuthenticationSuccessHandler)
.failureHandler(ajaxAuthenticationFailureHandler)
.usernameParameter("j_username")
.passwordParameter("j_password")
.permitAll()
.and()
.logout()
.logoutUrl("/app/logout")
.logoutSuccessHandler(ajaxLogoutSuccessHandler)
.deleteCookies("JSESSIONID")
.permitAll()
.and()
.addFilter(basicAuthenticationFilter(basicAuthenticationEntryPoint(), authenticationManager()))
.csrf()
.disable()
.authorizeRequests()
.antMatchers("/login/**").permitAll()
.antMatchers("/logout/**").permitAll()
.antMatchers("/super_admin/**").hasRole("ADMIN")
.antMatchers("/administration/**").hasRole("ADMIN")
.antMatchers("/*").permitAll()
.antMatchers("/app/**").authenticated();
When I'm logged as user with role ADMIN and I'm accessing http://mydomain:8080/super_admin and http://mydomain:8080/#/administration this is not being blocked. (Works fine)
But when I log in as user without role ADMIN this is being blocked http://mydomain:8080/super_admin, but I can still access http://mydomain:8080/#/administration.
Is there a problem with #?
How I can block http://mydomain:8080/#/administration
Thank you for any feedback.
Values after the # are not send to the server. You have to use some JavaScript to check if it's ok for the user to access the page.
Evgeni is correct, the values after the # is called the fragment or anchor part of the URL, and is used by web browsers not the server.
Example of a fragment URL http://en.wikipedia.org/wiki/Hurricane_Ginger#Impact. This link will take you to Hurricane_Ginger heading Impact

Resources