Skip to content

Commit e06d60a

Browse files
committed
Address Spring Security 6.0 changes
1 parent 6f02f56 commit e06d60a

File tree

7 files changed

+193
-166
lines changed

7 files changed

+193
-166
lines changed

samples/fido-server-conformance-test-app/src/main/java/com/webauthn4j/springframework/security/webauthn/sample/app/config/WebSecurityConfig.java

Lines changed: 36 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -113,23 +113,25 @@ public WebSecurityCustomizer webSecurityCustomizer() {
113113
@Bean
114114
public SecurityFilterChain filterChain(HttpSecurity http, AuthenticationManager authenticationManager) throws Exception {
115115
// WebAuthn Config
116-
http.apply(WebAuthnLoginConfigurer.webAuthnLogin())
117-
.attestationOptionsEndpoint()
118-
.rp()
119-
.name("WebAuthn4J Spring Security Sample")
120-
.and()
121-
.pubKeyCredParams(
122-
new PublicKeyCredentialParameters(PublicKeyCredentialType.PUBLIC_KEY, COSEAlgorithmIdentifier.ES256),
123-
new PublicKeyCredentialParameters(PublicKeyCredentialType.PUBLIC_KEY, COSEAlgorithmIdentifier.RS1),
124-
new PublicKeyCredentialParameters(PublicKeyCredentialType.PUBLIC_KEY, COSEAlgorithmIdentifier.EdDSA)
125-
)
126-
.extensions()
127-
.entry("example.extension", "test")
128-
.and()
129-
.assertionOptionsEndpoint()
130-
.extensions()
131-
.entry("example.extension", "test")
132-
.and();
116+
http.with(WebAuthnLoginConfigurer.webAuthnLogin(), (customizer)->{
117+
customizer
118+
.attestationOptionsEndpoint()
119+
.rp()
120+
.name("WebAuthn4J Spring Security Sample")
121+
.and()
122+
.pubKeyCredParams(
123+
new PublicKeyCredentialParameters(PublicKeyCredentialType.PUBLIC_KEY, COSEAlgorithmIdentifier.ES256),
124+
new PublicKeyCredentialParameters(PublicKeyCredentialType.PUBLIC_KEY, COSEAlgorithmIdentifier.RS1),
125+
new PublicKeyCredentialParameters(PublicKeyCredentialType.PUBLIC_KEY, COSEAlgorithmIdentifier.EdDSA)
126+
)
127+
.extensions()
128+
.entry("example.extension", "test")
129+
.and()
130+
.assertionOptionsEndpoint()
131+
.extensions()
132+
.entry("example.extension", "test")
133+
.and();
134+
});
133135

134136
FidoServerAttestationOptionsEndpointFilter fidoServerAttestationOptionsEndpointFilter = new FidoServerAttestationOptionsEndpointFilter(objectConverter, attestationOptionsProvider, challengeRepository);
135137
FidoServerAttestationResultEndpointFilter fidoServerAttestationResultEndpointFilter = new FidoServerAttestationResultEndpointFilter(objectConverter, userDetailsManager, webAuthnAuthenticatorManager, webAuthnRegistrationRequestValidator);
@@ -144,21 +146,25 @@ public SecurityFilterChain filterChain(HttpSecurity http, AuthenticationManager
144146
http.addFilterAfter(fidoServerAssertionResultEndpointFilter, SessionManagementFilter.class);
145147

146148
// Authorization
147-
http.authorizeHttpRequests()
148-
.requestMatchers("/").permitAll()
149-
.requestMatchers("/api/auth/status").permitAll()
150-
.requestMatchers(HttpMethod.GET, "/login").permitAll()
151-
.requestMatchers(HttpMethod.POST, "/api/profile").permitAll()
152-
.requestMatchers("/health/**").permitAll()
153-
.requestMatchers("/info/**").permitAll()
154-
.requestMatchers("/h2-console/**").denyAll()
155-
.requestMatchers("/api/admin/**").hasRole(ADMIN_ROLE)
156-
.anyRequest().fullyAuthenticated();
149+
http.authorizeHttpRequests(customizer -> {
150+
customizer
151+
.requestMatchers("/").permitAll()
152+
.requestMatchers("/api/auth/status").permitAll()
153+
.requestMatchers(HttpMethod.GET, "/login").permitAll()
154+
.requestMatchers(HttpMethod.POST, "/api/profile").permitAll()
155+
.requestMatchers("/health/**").permitAll()
156+
.requestMatchers("/info/**").permitAll()
157+
.requestMatchers("/h2-console/**").denyAll()
158+
.requestMatchers("/api/admin/**").hasRole(ADMIN_ROLE)
159+
.anyRequest().fullyAuthenticated();
160+
});
157161

158-
//TODO:
159-
http.csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
160162

161-
http.csrf().ignoringRequestMatchers("/webauthn/**");
163+
//TODO:
164+
http.csrf(customizer -> {
165+
customizer.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
166+
customizer.ignoringRequestMatchers("/webauthn/**");
167+
});
162168

163169
http.authenticationManager(authenticationManager);
164170

samples/mpa/src/main/java/com/webauthn4j/springframework/security/webauthn/sample/app/config/WebSecurityConfig.java

Lines changed: 32 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
3838
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
3939
import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer;
40+
import org.springframework.security.config.annotation.web.configurers.HeadersConfigurer;
4041
import org.springframework.security.core.userdetails.UserDetailsService;
4142
import org.springframework.security.crypto.password.PasswordEncoder;
4243
import org.springframework.security.web.SecurityFilterChain;
@@ -86,32 +87,34 @@ public WebSecurityCustomizer webSecurityCustomizer() {
8687
@Bean
8788
public SecurityFilterChain filterChain(HttpSecurity http, AuthenticationManager authenticationManager) throws Exception {
8889
// WebAuthn Login
89-
http.apply(WebAuthnLoginConfigurer.webAuthnLogin())
90-
.defaultSuccessUrl("/", true)
91-
.failureUrl("/login")
92-
.attestationOptionsEndpoint()
93-
.rp()
94-
.name("WebAuthn4J Spring Security Sample")
95-
.and()
96-
.pubKeyCredParams(
97-
new PublicKeyCredentialParameters(PublicKeyCredentialType.PUBLIC_KEY, COSEAlgorithmIdentifier.ES256),
98-
new PublicKeyCredentialParameters(PublicKeyCredentialType.PUBLIC_KEY, COSEAlgorithmIdentifier.RS1)
99-
)
100-
.attestation(AttestationConveyancePreference.NONE)
101-
.extensions()
102-
.uvm(true)
103-
.credProps(true)
104-
.extensionProviders()
105-
.and()
106-
.assertionOptionsEndpoint()
107-
.extensions()
108-
.extensionProviders();
90+
http.with(WebAuthnLoginConfigurer.webAuthnLogin(), (customizer)-> {
91+
customizer
92+
.defaultSuccessUrl("/", true)
93+
.failureUrl("/login")
94+
.attestationOptionsEndpoint()
95+
.rp()
96+
.name("WebAuthn4J Spring Security Sample")
97+
.and()
98+
.pubKeyCredParams(
99+
new PublicKeyCredentialParameters(PublicKeyCredentialType.PUBLIC_KEY, COSEAlgorithmIdentifier.ES256),
100+
new PublicKeyCredentialParameters(PublicKeyCredentialType.PUBLIC_KEY, COSEAlgorithmIdentifier.RS1)
101+
)
102+
.attestation(AttestationConveyancePreference.NONE)
103+
.extensions()
104+
.uvm(true)
105+
.credProps(true)
106+
.extensionProviders()
107+
.and()
108+
.assertionOptionsEndpoint()
109+
.extensions()
110+
.extensionProviders();
111+
});
109112

110113
http.headers(headers -> {
111114
// 'publickey-credentials-get *' allows getting WebAuthn credentials to all nested browsing contexts (iframes) regardless of their origin.
112115
headers.permissionsPolicy(config -> config.policy("publickey-credentials-get *"));
113116
// Disable "X-Frame-Options" to allow cross-origin iframe access
114-
headers.frameOptions().disable();
117+
headers.frameOptions(HeadersConfigurer.FrameOptionsConfig::disable);
115118
});
116119

117120

@@ -123,14 +126,18 @@ public SecurityFilterChain filterChain(HttpSecurity http, AuthenticationManager
123126
.anyRequest().access(getWebExpressionAuthorizationManager("@webAuthnSecurityExpression.isWebAuthnAuthenticated(authentication) || hasAuthority('SINGLE_FACTOR_AUTHN_ALLOWED')"))
124127
);
125128

126-
http.exceptionHandling()
127-
.accessDeniedHandler((request, response, accessDeniedException) -> response.sendRedirect("/login"));
129+
http.exceptionHandling(customizer -> {
130+
customizer.accessDeniedHandler((request, response, accessDeniedException) -> response.sendRedirect("/login"));
131+
});
132+
128133

129134
http.authenticationManager(authenticationManager);
130135

131136
// As WebAuthn has its own CSRF protection mechanism (challenge), CSRF token is disabled here
132-
http.csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
133-
http.csrf().ignoringRequestMatchers("/webauthn/**");
137+
http.csrf(customizer -> {
138+
customizer.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
139+
customizer.ignoringRequestMatchers("/webauthn/**");
140+
});
134141

135142
return http.build();
136143

samples/spa/src/main/java/com/webauthn4j/springframework/security/webauthn/sample/app/config/WebSecurityConfig.java

Lines changed: 44 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
3636
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
3737
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
38+
import org.springframework.security.config.annotation.web.configurers.HeadersConfigurer;
3839
import org.springframework.security.core.userdetails.UserDetailsService;
3940
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
4041
import org.springframework.security.web.AuthenticationEntryPoint;
@@ -97,39 +98,41 @@ public AuthenticationManager authenticationManager(List<AuthenticationProvider>
9798

9899
@Bean
99100
public SecurityFilterChain filterChain(HttpSecurity http, AuthenticationManager authenticationManager) throws Exception {
101+
102+
http.authenticationManager(authenticationManager);
100103
// WebAuthn Login
101-
http.apply(WebAuthnLoginConfigurer.webAuthnLogin())
102-
.usernameParameter("username")
103-
.passwordParameter("password")
104-
.credentialIdParameter("credentialId")
105-
.clientDataJSONParameter("clientDataJSON")
106-
.authenticatorDataParameter("authenticatorData")
107-
.signatureParameter("signature")
108-
.clientExtensionsJSONParameter("clientExtensionsJSON")
109-
.loginProcessingUrl("/login")
110-
.attestationOptionsEndpoint()
111-
.rp()
112-
.name("WebAuthn4J Spring Security Sample")
113-
.and()
114-
.pubKeyCredParams(
115-
new PublicKeyCredentialParameters(PublicKeyCredentialType.PUBLIC_KEY, COSEAlgorithmIdentifier.RS256), // Windows Hello
116-
new PublicKeyCredentialParameters(PublicKeyCredentialType.PUBLIC_KEY, COSEAlgorithmIdentifier.ES256) // FIDO U2F Key, etc
117-
)
118-
.extensions()
119-
.credProps(true)
120-
.and()
121-
.assertionOptionsEndpoint()
122-
.and()
123-
.successHandler(authenticationSuccessHandler)
124-
.failureHandler(authenticationFailureHandler)
125-
.and()
126-
.authenticationManager(authenticationManager);
104+
http.with(WebAuthnLoginConfigurer.webAuthnLogin(), (customizer) ->{
105+
customizer
106+
.usernameParameter("username")
107+
.passwordParameter("password")
108+
.credentialIdParameter("credentialId")
109+
.clientDataJSONParameter("clientDataJSON")
110+
.authenticatorDataParameter("authenticatorData")
111+
.signatureParameter("signature")
112+
.clientExtensionsJSONParameter("clientExtensionsJSON")
113+
.loginProcessingUrl("/login")
114+
.attestationOptionsEndpoint()
115+
.rp()
116+
.name("WebAuthn4J Spring Security Sample")
117+
.and()
118+
.pubKeyCredParams(
119+
new PublicKeyCredentialParameters(PublicKeyCredentialType.PUBLIC_KEY, COSEAlgorithmIdentifier.RS256), // Windows Hello
120+
new PublicKeyCredentialParameters(PublicKeyCredentialType.PUBLIC_KEY, COSEAlgorithmIdentifier.ES256) // FIDO U2F Key, etc
121+
)
122+
.extensions()
123+
.credProps(true)
124+
.and()
125+
.assertionOptionsEndpoint()
126+
.and()
127+
.successHandler(authenticationSuccessHandler)
128+
.failureHandler(authenticationFailureHandler);
129+
});
127130

128131
http.headers(headers -> {
129132
// 'publickey-credentials-get *' allows getting WebAuthn credentials to all nested browsing contexts (iframes) regardless of their origin.
130133
headers.permissionsPolicy(config -> config.policy("publickey-credentials-get *"));
131134
// Disable "X-Frame-Options" to allow cross-origin iframe access
132-
headers.frameOptions().disable();
135+
headers.frameOptions(HeadersConfigurer.FrameOptionsConfig::disable);
133136
});
134137

135138
// Authorization
@@ -151,23 +154,26 @@ public SecurityFilterChain filterChain(HttpSecurity http, AuthenticationManager
151154
);
152155

153156
// Logout
154-
http.logout()
155-
.logoutUrl("/logout")
156-
.logoutSuccessHandler(logoutSuccessHandler);
157+
http.logout(customizer -> {
158+
customizer.logoutUrl("/logout");
159+
customizer.logoutSuccessHandler(logoutSuccessHandler);
160+
});
157161

158-
http.sessionManagement()
159-
.sessionAuthenticationFailureHandler(authenticationFailureHandler);
162+
http.sessionManagement(customizer -> customizer.sessionAuthenticationFailureHandler(authenticationFailureHandler));
160163

161-
http.exceptionHandling()
162-
.authenticationEntryPoint(authenticationEntryPoint)
163-
.accessDeniedHandler(accessDeniedHandler);
164+
http.exceptionHandling(customizer -> {
165+
customizer.authenticationEntryPoint(authenticationEntryPoint);
166+
customizer.accessDeniedHandler(accessDeniedHandler);
167+
});
164168

165169
// As WebAuthn has its own CSRF protection mechanism (challenge), CSRF token is disabled here
166170
CsrfTokenRequestAttributeHandler csrfTokenRequestAttributeHandler = new CsrfTokenRequestAttributeHandler();
167171
csrfTokenRequestAttributeHandler.setCsrfRequestAttributeName(null);
168-
http.csrf().csrfTokenRequestHandler(csrfTokenRequestAttributeHandler);
169-
http.csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
170-
http.csrf().ignoringRequestMatchers("/webauthn/**");
172+
http.csrf(customizer ->{
173+
customizer.csrfTokenRequestHandler(csrfTokenRequestAttributeHandler);
174+
customizer.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
175+
customizer.ignoringRequestMatchers("/webauthn/**");
176+
});
171177

172178
return http.build();
173179
}

webauthn4j-spring-security-core/src/test/java/com/webauthn4j/springframework/security/config/configurers/WebAuthnAuthenticationProviderConfigurerSpringTest.java

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -86,12 +86,15 @@ public ServerPropertyProvider serverPropertyProvider(RpIdProvider rpIdProvider,
8686
@Bean
8787
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
8888
// Authentication
89-
http.apply(WebAuthnLoginConfigurer.webAuthnLogin());
89+
http.with(WebAuthnLoginConfigurer.webAuthnLogin(), (customizer)->{
90+
});
9091

9192
// Authorization
92-
http.authorizeHttpRequests()
93-
.requestMatchers("/login").permitAll()
94-
.anyRequest().authenticated();
93+
http.authorizeHttpRequests((authorizeHttpRequestsCustomizer)->{
94+
authorizeHttpRequestsCustomizer.requestMatchers("/login").permitAll();
95+
authorizeHttpRequestsCustomizer.anyRequest().authenticated();
96+
});
97+
9598

9699
return http.build();
97100
}

webauthn4j-spring-security-core/src/test/java/com/webauthn4j/springframework/security/config/configurers/WebAuthnLoginConfigurerAnotherSpringTest.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -81,12 +81,14 @@ static class Config {
8181

8282
@Bean
8383
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
84-
http.apply(WebAuthnLoginConfigurer.webAuthnLogin());
84+
http.with(WebAuthnLoginConfigurer.webAuthnLogin(), (customizer)->{
85+
});
8586

8687
// Authorization
87-
http.authorizeHttpRequests()
88-
.requestMatchers("/login").permitAll()
89-
.anyRequest().authenticated();
88+
http.authorizeHttpRequests(authorizeHttpRequestsCustomizer->{
89+
authorizeHttpRequestsCustomizer.requestMatchers("/login").permitAll();
90+
authorizeHttpRequestsCustomizer.anyRequest().authenticated();
91+
});
9092

9193
return http.build();
9294
}

webauthn4j-spring-security-core/src/test/java/com/webauthn4j/springframework/security/config/configurers/WebAuthnLoginConfigurerMinimalConfigSpringTest.java

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -68,12 +68,13 @@ static class Config {
6868
@Bean
6969
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
7070

71-
http.apply(WebAuthnLoginConfigurer.webAuthnLogin());
72-
71+
http.with(WebAuthnLoginConfigurer.webAuthnLogin(), (customizer)->{});
7372
// Authorization
74-
http.authorizeHttpRequests()
75-
.requestMatchers("/login").permitAll()
76-
.anyRequest().authenticated();
73+
http.authorizeHttpRequests(authorizeHttpRequestsCustomizer->{
74+
authorizeHttpRequestsCustomizer.requestMatchers("/login").permitAll();
75+
authorizeHttpRequestsCustomizer.anyRequest().authenticated();
76+
});
77+
7778

7879
return http.build();
7980
}

0 commit comments

Comments
 (0)