DEV Community

iron_man
iron_man

Posted on

SecurityConfiguration

package com.hardening;

import java.util.ArrayList;
import java.util.List;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.SecurityFilterChain;

@Configuration
@EnableWebSecurity
public class SecurityConfiguration {

@Bean
PasswordEncoder passwordEncoder() {
    return PasswordEncoderFactories.createDelegatingPasswordEncoder();
}

@Bean
UserDetailsService userDetailsService(Settings settings) {
    String adminPassword = settings.adminPassword();

    if (adminPassword == null || adminPassword.length() < 12) {
        throw new IllegalArgumentException(
                "hardening.admin-password must contain at least 12 characters"
        );
    }

    PasswordEncoder encoder = passwordEncoder();
    List<UserDetails> users = new ArrayList<>();

    users.add(
            User.withUsername("admin")
                    .password(encoder.encode(adminPassword))
                    .roles("ADMIN", "USER")
                    .build()
    );

    // Old optional operator account. Target Oracle access will not use this.
    if (!settings.demo()
            && settings.userPassword() != null
            && !settings.userPassword().isBlank()) {

        users.add(
                User.withUsername("operator")
                        .password(encoder.encode(settings.userPassword()))
                        .roles("USER")
                        .build()
        );
    }

    return new InMemoryUserDetailsManager(users);
}

@Bean
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    http
            .csrf(csrf -> csrf.ignoringRequestMatchers("/api/**"))
            .authorizeHttpRequests(auth -> auth
                    .requestMatchers(
                            "/",
                            "/index.html",
                            "/assets/**",
                            "/favicon.svg",
                            "/error"
                    ).permitAll()
                    .requestMatchers("/api/login").permitAll()
                    .requestMatchers("/api/admin/**").hasRole("ADMIN")
                    .requestMatchers("/api/**").hasAnyRole("ADMIN", "USER")
                    .anyRequest().authenticated()
            )
            .formLogin(login -> login
                    .loginProcessingUrl("/api/login")
                    .successHandler((request, response, authentication) -> {
                        response.setContentType(MediaType.APPLICATION_JSON_VALUE);
                        response.getWriter().write("{\"message\":\"ok\"}");
                    })
                    .failureHandler((request, response, exception) -> {
                        response.setStatus(401);
                        response.setContentType(MediaType.APPLICATION_JSON_VALUE);
                        response.getWriter().write(
                                "{\"message\":\"Sign-in failed. Check the configured application account.\"}"
                        );
                    })
                    .permitAll()
            )
            .httpBasic(basic -> basic.disable());

    return http.build();
}
Enter fullscreen mode Exit fullscreen mode

}

Top comments (0)