@ -1,5 +1,5 @@
@@ -1,5 +1,5 @@
/ *
* Copyright 2002 - 2025 the original author or authors .
* Copyright 2002 - 2023 the original author or authors .
*
* Licensed under the Apache License , Version 2 . 0 ( the "License" ) ;
* you may not use this file except in compliance with the License .
@ -43,7 +43,9 @@ import org.springframework.security.core.userdetails.UserDetailsService;
@@ -43,7 +43,9 @@ import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.provisioning.InMemoryUserDetailsManager ;
import org.springframework.security.web.SecurityFilterChain ;
import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken ;
import org.springframework.security.web.authentication.preauth.x509.SubjectX500PrincipalExtractor ;
import org.springframework.security.web.authentication.preauth.x509.X509AuthenticationFilter ;
import org.springframework.security.web.authentication.preauth.x509.X509TestUtils ;
import org.springframework.test.web.servlet.MockMvc ;
import static org.assertj.core.api.Assertions.assertThat ;
@ -123,16 +125,6 @@ public class X509ConfigurerTests {
@@ -123,16 +125,6 @@ public class X509ConfigurerTests {
// @formatter:on
}
@Test
public void x509WhenExtractPrincipalNameFromEmailIsTrueThenUsesEmailAddressToExtractPrincipal ( ) throws Exception {
this . spring . register ( EmailPrincipalConfig . class ) . autowire ( ) ;
X509Certificate certificate = loadCert ( "max.cer" ) ;
// @formatter:off
this . mvc . perform ( get ( "/" ) . with ( x509 ( certificate ) ) )
. andExpect ( authenticated ( ) . withUsername ( "maxbatischev@gmail.com" ) ) ;
// @formatter:on
}
@Test
public void x509WhenUserDetailsServiceNotConfiguredThenUsesBean ( ) throws Exception {
this . spring . register ( UserDetailsServiceBeanConfig . class ) . autowire ( ) ;
@ -165,6 +157,28 @@ public class X509ConfigurerTests {
@@ -165,6 +157,28 @@ public class X509ConfigurerTests {
// @formatter:on
}
@Test
public void x509WhenSubjectX500PrincipalExtractor ( ) throws Exception {
this . spring . register ( SubjectX500PrincipalExtractorConfig . class ) . autowire ( ) ;
X509Certificate certificate = loadCert ( "rod.cer" ) ;
// @formatter:off
this . mvc . perform ( get ( "/" ) . with ( x509 ( certificate ) ) )
. andExpect ( ( result ) - > assertThat ( result . getRequest ( ) . getSession ( false ) ) . isNull ( ) )
. andExpect ( authenticated ( ) . withUsername ( "rod" ) ) ;
// @formatter:on
}
@Test
public void x509WhenSubjectX500PrincipalExtractorBean ( ) throws Exception {
this . spring . register ( SubjectX500PrincipalExtractorEmailConfig . class ) . autowire ( ) ;
X509Certificate certificate = X509TestUtils . buildTestCertificate ( ) ;
// @formatter:off
this . mvc . perform ( get ( "/" ) . with ( x509 ( certificate ) ) )
. andExpect ( ( result ) - > assertThat ( result . getRequest ( ) . getSession ( false ) ) . isNull ( ) )
. andExpect ( authenticated ( ) . withUsername ( "luke@monkeymachine" ) ) ;
// @formatter:on
}
private < T extends Certificate > T loadCert ( String location ) {
try ( InputStream is = new ClassPathResource ( location ) . getInputStream ( ) ) {
CertificateFactory certFactory = CertificateFactory . getInstance ( "X.509" ) ;
@ -287,33 +301,6 @@ public class X509ConfigurerTests {
@@ -287,33 +301,6 @@ public class X509ConfigurerTests {
}
@Configuration
@EnableWebSecurity
static class EmailPrincipalConfig {
@Bean
SecurityFilterChain filterChain ( HttpSecurity http ) throws Exception {
// @formatter:off
http
. x509 ( ( x509 ) - >
x509 . extractPrincipalNameFromEmail ( true )
) ;
// @formatter:on
return http . build ( ) ;
}
@Bean
UserDetailsService userDetailsService ( ) {
UserDetails user = User . withDefaultPasswordEncoder ( )
. username ( "maxbatischev@gmail.com" )
. password ( "password" )
. roles ( "USER" , "ADMIN" )
. build ( ) ;
return new InMemoryUserDetailsManager ( user ) ;
}
}
@Configuration
@EnableWebSecurity
static class UserDetailsServiceBeanConfig {
@ -397,4 +384,60 @@ public class X509ConfigurerTests {
@@ -397,4 +384,60 @@ public class X509ConfigurerTests {
}
@Configuration
@EnableWebSecurity
static class SubjectX500PrincipalExtractorConfig {
@Bean
SecurityFilterChain securityFilterChain ( HttpSecurity http ) throws Exception {
// @formatter:off
http
. x509 ( ( x509 ) - > x509
. x509PrincipalExtractor ( new SubjectX500PrincipalExtractor ( ) )
) ;
// @formatter:on
return http . build ( ) ;
}
@Bean
UserDetailsService userDetailsService ( ) {
UserDetails user = User . withDefaultPasswordEncoder ( )
. username ( "rod" )
. password ( "password" )
. roles ( "USER" , "ADMIN" )
. build ( ) ;
return new InMemoryUserDetailsManager ( user ) ;
}
}
@Configuration
@EnableWebSecurity
static class SubjectX500PrincipalExtractorEmailConfig {
@Bean
SecurityFilterChain securityFilterChain ( HttpSecurity http ) throws Exception {
SubjectX500PrincipalExtractor principalExtractor = new SubjectX500PrincipalExtractor ( ) ;
principalExtractor . setExtractPrincipalNameFromEmail ( true ) ;
// @formatter:off
http
. x509 ( ( x509 ) - > x509
. x509PrincipalExtractor ( principalExtractor )
) ;
// @formatter:on
return http . build ( ) ;
}
@Bean
UserDetailsService userDetailsService ( ) {
UserDetails user = User . withDefaultPasswordEncoder ( )
. username ( "luke@monkeymachine" )
. password ( "password" )
. roles ( "USER" , "ADMIN" )
. build ( ) ;
return new InMemoryUserDetailsManager ( user ) ;
}
}
}