1

I have a Spring Boot application which has some endpoints:

  • /.wellknown which does not require any authentication and open to public
  • /callback which requires mTLS (only cert authentication).

For the above requirement, I cannot find a exact implementation. Most of the implementation

  1. find enables mTLS at server level - meaning all APIs are mTLS enabled.
  2. with X.509 Certificate check which checks for certificate and user data (In my case there is no user data involved - its only server to server mTLS).

Found below code:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
 
    /*
     * Enables x509 client authentication.
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // @formatter:off
        http
                .authorizeRequests()
                    .anyRequest()
                        .authenticated()
                .and()
                    .x509()
                .and()
                    .sessionManagement()
                        .sessionCreationPolicy(SessionCreationPolicy.NEVER)
                .and()
                    .csrf()
                        .disable();
        // @formatter:on
    }
 
    /*
     * Create an in-memory authentication manager. We create 1 user (localhost which
     * is the CN of the client certificate) which has a role of USER.
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication().withUser("localhost").password("none").roles("USER");
    }
}

Please help on how to implement the same

  1. /callback - check if the client gives the cert and is available in trust-store
  2. /.well-known/ No mTLS check respond without any check
2
  • One way could be to use only HTTP for /.well-known/, so you could enable mTLS in server configuration. Commented Jan 5, 2022 at 17:29
  • See also stackoverflow.com/questions/33808603/… Commented Jan 5, 2022 at 17:34

1 Answer 1

3

First, I recommend you use the newest approach to configure Spring Security since the WebSecurityConfigurerAdapter will be deprecated soon.

The way I would implement your scenario is by having 2 SecurityFilterChain, one for the /.well-known path, and the other one for the rest, using requestMatchers, like so:

@EnableWebSecurity
public class SecurityConfig {

    @Bean
    @Order(Ordered.HIGHEST_PRECEDENCE)
    public SecurityFilterChain wellKnownSecurity(HttpSecurity http) throws Exception {
        // @formatter:off
        http
                .requestMatchers((requests) -> requests
                    .antMatchers("/.well-known")
                )
                .authorizeHttpRequests((authorize) -> authorize
                        .anyRequest().permitAll()
                );
        // @formatter:on
        return http.build();
    }

    @Bean
    public SecurityFilterChain defaultSecurity(HttpSecurity http) throws Exception {
        http
            .authorizeRequests((authorize) -> authorize
                .anyRequest().authenticated()
            )
            .x509(Customizer.withDefaults())
            .sessionManagement((session) -> session
                 .sessionCreationPolicy(SessionCreationPolicy.NEVER)
            )
            .csrf(CsrfConfigurer::disable);
        // @formatter:on
        return http.build();
    }

    @Bean
    public UserDetailsService userDetailsService() {
        UserDetails user = User.withDefaultPasswordEncoder()
                .username("user")
                .password("password")
                .roles("USER")
                .build();
        return new InMemoryUserDetailsManager(user);
    }

}

This way, the wellKnownSecurity chain will be applied to the /.well-known endpoint, permitting all requests, and the defaultSecurity chain will be applied to every other request, requiring x509.

Sign up to request clarification or add additional context in comments.

3 Comments

Your solution isn't solving OP's problem. You are using .x509(Customizer.withDefaults()), which authenticates an user, but OP has no user at all.
I've replicated the user code with a solution that will permit access to the /.well-known endpoint, as well as having a totally separate configuration to the other endpoints.
@MarcusHertdaCoregio is this mutual TLS? this seems like one-way TLS

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.