Skip to content

Commit 0923635

Browse files
eleftheriaskostya05983
authored andcommitted
Allow configuration of x509 through nested builder
Issue: spring-projectsgh-5557
1 parent 38bc40d commit 0923635

File tree

2 files changed

+100
-0
lines changed

2 files changed

+100
-0
lines changed

config/src/main/java/org/springframework/security/config/annotation/web/builders/HttpSecurity.java

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -861,6 +861,42 @@ public X509Configurer<HttpSecurity> x509() throws Exception {
861861
return getOrApply(new X509Configurer<>());
862862
}
863863

864+
/**
865+
* Configures X509 based pre authentication.
866+
*
867+
* <h2>Example Configuration</h2>
868+
*
869+
* The following configuration will attempt to extract the username from the X509
870+
* certificate. Remember that the Servlet Container will need to be configured to
871+
* request client certificates in order for this to work.
872+
*
873+
* <pre>
874+
* &#064;Configuration
875+
* &#064;EnableWebSecurity
876+
* public class X509SecurityConfig extends WebSecurityConfigurerAdapter {
877+
*
878+
* &#064;Override
879+
* protected void configure(HttpSecurity http) throws Exception {
880+
* http
881+
* .authorizeRequests()
882+
* .antMatchers(&quot;/**&quot;)
883+
* .hasRole(&quot;USER&quot;)
884+
* .and()
885+
* .x509(withDefaults());
886+
* }
887+
* }
888+
* </pre>
889+
*
890+
* @param x509Customizer the {@link Customizer} to provide more options for
891+
* the {@link X509Configurer}
892+
* @return the {@link HttpSecurity} for further customizations
893+
* @throws Exception
894+
*/
895+
public HttpSecurity x509(Customizer<X509Configurer<HttpSecurity>> x509Customizer) throws Exception {
896+
x509Customizer.customize(getOrApply(new X509Configurer<>()));
897+
return HttpSecurity.this;
898+
}
899+
864900
/**
865901
* Allows configuring of Remember Me authentication.
866902
*

config/src/test/java/org/springframework/security/config/annotation/web/configurers/X509ConfigurerTests.java

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
import static org.mockito.ArgumentMatchers.any;
3939
import static org.mockito.Mockito.spy;
4040
import static org.mockito.Mockito.verify;
41+
import static org.springframework.security.config.Customizer.withDefaults;
4142
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.x509;
4243
import static org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.authenticated;
4344
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
@@ -122,6 +123,69 @@ protected void configure(AuthenticationManagerBuilder auth) throws Exception {
122123
}
123124
}
124125

126+
@Test
127+
public void x509WhenConfiguredInLambdaThenUsesDefaults() throws Exception {
128+
this.spring.register(DefaultsInLambdaConfig.class).autowire();
129+
X509Certificate certificate = loadCert("rod.cer");
130+
131+
this.mvc.perform(get("/")
132+
.with(x509(certificate)))
133+
.andExpect(authenticated().withUsername("rod"));
134+
}
135+
136+
@EnableWebSecurity
137+
static class DefaultsInLambdaConfig extends WebSecurityConfigurerAdapter {
138+
@Override
139+
protected void configure(HttpSecurity http) throws Exception {
140+
// @formatter:off
141+
http
142+
.x509(withDefaults());
143+
// @formatter:on
144+
}
145+
146+
@Override
147+
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
148+
// @formatter:off
149+
auth
150+
.inMemoryAuthentication()
151+
.withUser("rod").password("password").roles("USER", "ADMIN");
152+
// @formatter:on
153+
}
154+
}
155+
156+
@Test
157+
public void x509WhenSubjectPrincipalRegexInLambdaThenUsesRegexToExtractPrincipal() throws Exception {
158+
this.spring.register(SubjectPrincipalRegexInLambdaConfig.class).autowire();
159+
X509Certificate certificate = loadCert("rodatexampledotcom.cer");
160+
161+
this.mvc.perform(get("/")
162+
.with(x509(certificate)))
163+
.andExpect(authenticated().withUsername("rod"));
164+
}
165+
166+
@EnableWebSecurity
167+
static class SubjectPrincipalRegexInLambdaConfig extends WebSecurityConfigurerAdapter {
168+
@Override
169+
protected void configure(HttpSecurity http) throws Exception {
170+
// @formatter:off
171+
http
172+
.x509(x509 ->
173+
x509
174+
.subjectPrincipalRegex("CN=(.*?)@example.com(?:,|$)")
175+
);
176+
// @formatter:on
177+
}
178+
179+
@Override
180+
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
181+
// @formatter:off
182+
auth
183+
.inMemoryAuthentication()
184+
.withUser("rod").password("password").roles("USER", "ADMIN");
185+
// @formatter:on
186+
}
187+
}
188+
125189
private <T extends Certificate> T loadCert(String location) {
126190
try (InputStream is = new ClassPathResource(location).getInputStream()) {
127191
CertificateFactory certFactory = CertificateFactory.getInstance("X.509");

0 commit comments

Comments
 (0)