How to exclude actuator from SecurityWebFilterChain authorization - spring

I have the WebSecurityConfiguration class which uses SecurityWebFilterChain to authorize access. Still, I want to exclude actuator from it so I have another bean for it but the endpoint still is not accessible w/o authorization.
#Configuration
public class WebSecurityConfiguration
{
#Order(Ordered.HIGHEST_PRECEDENCE)
#Bean
public SecurityWebFilterChain springSecurityFilterChainExcludeActuator(ServerHttpSecurity http) {
return http.securityMatcher(new NegatedServerWebExchangeMatcher(
ServerWebExchangeMatchers.pathMatchers("/actuator/health")))
.authorizeExchange()
.anyExchange().authenticated()
.and()
.csrf().disable()
.build();
}
#Bean
public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http)
{
http.csrf().disable()
.authorizeExchange()
.pathMatchers("/domains/**", "/address/**").permitAll()
.anyExchange().authenticated()
.and()
.httpBasic()
.and()
.formLogin().disable();
return http.build();
}
}
Any thoughts on what I have missed?
PS
Even the simple code below will require to provide authorization when I expect is not required for the actuator
http.authorizeExchange()
.pathMatchers("/actuator/**").permitAll()
.anyExchange().authenticated()
.and()
.httpBasic()
.and()
.formLogin()
.and()
.csrf()
.disable();
return http.build();

You can allow individual endpoints like this:
#Bean
SecurityFilterChain filterChain(final HttpSecurity http) throws Exception {
return http
.authorizeHttpRequests(authorize -> authorize
.requestMatchers(EndpointRequest.to(HealthEndpoint.class)).permitAll()
.anyRequest().authenticated())
.build();
}

Related

Multiple Spring's SecurityConfigs not working

I'm trying to configure two SecurityConfigs simultaneously. The SecurityConfig requires an Oauth authorization at Keycloak Auth Server (embedded in a separate Spring app). The OauthSecurityConfig requires an Oauth authorization at GoogleApi. Both configs DO work, when implemented separately (when I define just one config at a time).
Right now, only one of them works (the one annotated with #Order(1)). I'm trying to implementing them both in the following way:
#EnableWebSecurity
public class MultiSecurityConfig {
#Configuration
#Order(1)
public static class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.cors()
.and()
.authorizeRequests()
.antMatchers(HttpMethod.GET, "/auth/**")
.hasAnyAuthority("SCOPE_read", "SCOPE_write")
.anyRequest()
.permitAll()
.and()
.oauth2ResourceServer()
.jwt();
}
#Bean
CorsConfigurationSource corsConfigurationSource() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", new CorsConfiguration().applyPermitDefaultValues());
return source;
}
}
#Configuration
public static class OauthSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.cors()
.and()
.authorizeRequests()
.antMatchers(HttpMethod.GET, "/oauth/**")
.authenticated()
.anyRequest()
.permitAll()
.and()
.oauth2Login();
}
}
}
What am I doing wrong?
It turns out that for multiple SecurityConfigs to work you have to define '.antMatcher()` at each config, like so:
http.antMatcher("/auth/**").cors()
.and()
...

How to disable multiple logins for same user in spring security + spring boot

I have the below spring configuration :-
#Override
protected void configure(HttpSecurity http) throws Exception
{
http
.csrf().disable()
.exceptionHandling()
.authenticationEntryPoint((request, response,
authException) ->
response.sendError(HttpServletResponse.SC_UNAUTHORIZED))
.and()
.authorizeRequests()
.antMatchers(HttpMethod.OPTIONS,
"/api/v2/customers/**").permitAll()
.antMatchers(HttpMethod.OPTIONS,
"/oauth/**").permitAll()
.antMatchers(HttpMethod.GET, "/saml/**").permitAll()
.antMatchers(HttpMethod.GET,
"/api/internal/v2/**").permitAll()
.antMatchers("/**").authenticated()
.antMatchers("/api/admin/**").authenticated()
.and()
.httpBasic()
.and()
.sessionManagement()
.maximumSessions(1)
.maxSessionsPreventsLogin(true)
.sessionRegistry(SR);
}
I was expecting sessionManagement().maximumSessions(1) to disable multiple login for the same user. It is working, but first user logout the application, so i am trying login in another browser but it showing This account is already using by someone.
Try this. you are not clearing/ closing the previous session properly.
#EnableWebMvcSecurity
#Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/expired").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.and()
.sessionManagement()
.maximumSessions(1)
.expiredUrl("/expired")
.maxSessionsPreventsLogin(true)
.sessionRegistry(sessionRegistry());
}
#Bean
public SessionRegistry sessionRegistry() {
SessionRegistry sessionRegistry = new SessionRegistryImpl();
return sessionRegistry;
}
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER");
}
// Register HttpSessionEventPublisher
#Bean
public static ServletListenerRegistrationBean httpSessionEventPublisher() {
return new ServletListenerRegistrationBean(new HttpSessionEventPublisher());
}
}
Missing is .expiredUrl("/expired").maxSessionsPreventsLogin(true)
.sessionRegistry(sessionRegistry());

Configure Spring Security for multiple login pages in a Spring Boot application

#Configuration
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private AccessDeniedHandler accessDeniedHandler;
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/", "/home", "/about").permitAll()
.antMatchers("/admin/**").hasAnyRole("ADMIN")
.antMatchers("/user/**").hasAnyRole("USER")
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.permitAll()
.and()
.exceptionHandling().accessDeniedHandler(accessDeniedHandler);
}
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("user").password("password").roles("USER")
.and()
.withUser("admin").password("password").roles("ADMIN");
}
}
The Security Configuration is working fine as expected. Now I am trying to implement 2 login forms each for Admin and User. I tried separating the configuration using #Order but landed on the issue mentioned here Spring boot and spring security multiple login pages
Any better approach to implement the same?
In order to configure two different http elements, let’s create two static classes annotated with #Configuration that extend the WebSecurityConfigurerAdapter. Try configuring something like this:
#Configuration
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private AccessDeniedHandler accessDeniedHandler;
#Override
protected void configure(HttpSecurity http) throws Exception {
http.antMatcher("/admin*")
.authorizeRequests()
.anyRequest()
.hasRole("ADMIN")
.and()
.formLogin()
.loginPage("/loginAdmin")
.loginProcessingUrl("/admin_login")
.failureUrl("/loginAdmin?error=loginError")
.defaultSuccessUrl("/adminPage")
.and()
.logout()
.logoutUrl("/admin_logout")
.logoutSuccessUrl("/protectedLinks")
.deleteCookies("JSESSIONID")
.and()
.exceptionHandling()
.accessDeniedPage("/403")
.and()
.csrf().disable();
}
}
And, for normal users:
#Configuration
#Order(2)
public static class SpringSecurityConfig2 extends WebSecurityConfigurerAdapter {
protected void configure(HttpSecurity http) throws Exception {
http.antMatcher("/user*")
.authorizeRequests()
.anyRequest()
.hasRole("USER")
.and()
.formLogin()
.loginPage("/loginUser")
.loginProcessingUrl("/user_login")
.failureUrl("/loginUser?error=loginError")
.defaultSuccessUrl("/userPage")
.and()
.logout()
.logoutUrl("/user_logout")
.logoutSuccessUrl("/protectedLinks")
.and()
.exceptionHandling()
.accessDeniedPage("/403")
.and()
.csrf().disable();
}
}
Refer http://www.baeldung.com/spring-security-two-login-pages

spring websocket no spring security

I used spring websocket by stomp and spring message.
I don't like using spring security.
When I use:
SimpMessageSendingOperations.convertAndSendToUser(username,"");
I must :
#EnableWebSecurity
#Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable() // Refactor login form
// See https://jira.springsource.org/browse/SPR-11496
.headers().addHeaderWriter(
new XFrameOptionsHeaderWriter(
XFrameOptionsHeaderWriter.XFrameOptionsMode.SAMEORIGIN)).and()
.formLogin()
.defaultSuccessUrl("/index.html")
.loginPage("/login.html")
.failureUrl("/login.html?error")
.permitAll()
.and()
.logout()
.logoutSuccessUrl("/")
.logoutUrl("/logout.html")
.permitAll()
.and()
.authorizeRequests()
.antMatchers("/static/**").permitAll()
.antMatchers("/webjars/**").permitAll()
.anyRequest().authenticated()
.and();
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("lihui").password("1234").roles("USER").and()
.withUser("paulson").password("bond").roles("ADMIN","USER");
}
}
So, what can I do? Please help.
//when i not useing spring security.i can used
simpMessageSendingOperations.convertAndSendTo(usename,"queue/"+usename+"/greating",object);
//and client like this:
stompClient.subscribe('/queue/'++usename+'greetings', function (greeting) {
showGreeting(JSON.parse(greeting.body).content);
});

Spring security: Redirect unauthorised url

#PreAuthorize("hasPermission(#id,'Integer','write')")
#RequestMapping(value="events/{id}/edit",method=RequestMethod.GET)
public String edit(Model model,#PathVariable("id") int id) {
model.addAttribute("event", eventService.getEvent(id));
return "events/edit";
}
Security config
public class SecurityConfig extends WebSecurityConfigurerAdapter{
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers(HttpMethod.GET, "/", "/index", "/register", "/regitrationConfirm", "/forgotPassword", "/accountRecovery", "/passwordReset", "/public/**").permitAll()
.antMatchers(HttpMethod.POST, "/register", "/accountRecovery","/passwordReset").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.loginPage("/login?error")
.permitAll()
.failureHandler(authFailureHandler)
.and()
.rememberMe()
.tokenValiditySeconds(3600)
.key("rememberTracker")
.and()
.logout()
.permitAll()
.logoutUrl("/logout")
.logoutSuccessUrl("/")
.and()
.sessionManagement()
.maximumSessions(1)
.expiredUrl("/login?expired");
}
}
i want to redirect or show a custom page to the user if authorization fails. Is there a way to that?
updated with spring security code.
Thanks
I updated you SecurityConfig to add a failureUrl and successHandler
public class SecurityConfig extends WebSecurityConfigurerAdapter{
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers(HttpMethod.GET, "/", "/index", "/register", "/regitrationConfirm", "/forgotPassword", "/accountRecovery", "/passwordReset", "/public/**").permitAll()
.antMatchers(HttpMethod.POST, "/register", "/accountRecovery","/passwordReset").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.loginPage("/login?error")
.permitAll()
.failureUrl("/your-unsuccessful-authentication-url-here")
.successHandler(yourSuccesshandler) //create your success handler to redirect the user to different places depending on his role
//.failureHandler(authFailureHandler) I deleted this line, we just need a redirect
.and()
.rememberMe()
.tokenValiditySeconds(3600)
.key("rememberTracker")
.and()
.logout()
.permitAll()
.logoutUrl("/logout")
.logoutSuccessUrl("/")
.and()
.sessionManagement()
.maximumSessions(1)
.expiredUrl("/login?expired");
}
}
The success Handler
public class SuccessAuthenticationHandler implements AuthenticationSuccessHandler{
public SuccessAuthenticationHandler(){
}
#Override
public void onAuthenticationSuccess(HttpServletRequest request,
HttpServletResponse response, Authentication auth) throws IOException, ServletException {
HttpSession session = request.getSession();
User user = (User)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
String redirect = "";
if(user != null){
session.setAttribute("username", user.getUsername());
if(user.getAuthorities().contains(new SimpleGrantedAuthority("ROLE_ADMIN"))
|| user.getAuthorities().contains(new SimpleGrantedAuthority("ROLE_SUPER_ADMIN")))
redirect = "admin/";
else if(user.getAuthorities().contains(new SimpleGrantedAuthority("ROLE_YOUR_ROLE")))
redirect = "yourrole/";
}
if(redirect.isEmpty())
redirect = "signin";
response.sendRedirect(redirect);
}
}

Resources