1. Configuration
+1.1. Applications integration
+1.1.1. Maven dependency
+Please add following to pom.xml to introduce WebAuthn4J Spring Security and its dependencies.
+<properties>
+ ...
+ <!-- Use the latest version whenever possible. -->
+ <webauthn4j-spring-security.version>0.7.6.RELEASE</webauthn4j-spring-security.version>
+ ...
+</properties>
+
+<dependency>
+ <groupId>com.webauthn4j</groupId>
+ <artifactId>webauthn4j-spring-security-core</artifactId>
+ <version>${webauthn4j-spring-security.version}</version>
+</dependency>
+1.1.2. Java Config
+WebAuthn4J Spring Security can be configured through the Spring Security Java Config DSL.
+Please define the SecurityFilterChain
bean as follows and apply the WebAuthnLoginConfigurer
to the HttpSecurity
bean.
+Through WebAuthnLoginConfigurer
, you can set various options of the WebAuthnProcessingFilter
, Attestation options endpoint, and Assertion options endpoint.
@Configuration
+public class WebSecurityConfig {
+
+ @Bean
+ public SecurityFilterChain filterChain(HttpSecurity http, AuthenticationManager authenticationManager) throws Exception {
+
+ http.authenticationManager(authenticationManager);
+ // WebAuthn Login
+ http.with(WebAuthnLoginConfigurer.webAuthnLogin(), (customizer) ->{
+ customizer
+ .loginPage("/login")
+ .usernameParameter("username")
+ .passwordParameter("password")
+ .credentialIdParameter("credentialId")
+ .clientDataJSONParameter("clientDataJSON")
+ .authenticatorDataParameter("authenticatorData")
+ .signatureParameter("signature")
+ .clientExtensionsJSONParameter("clientExtensionsJSON")
+ .loginProcessingUrl("/login")
+ .attestationOptionsEndpoint()
+ .rp()
+ .name("WebAuthn4J Spring Security Sample")
+ .and()
+ .pubKeyCredParams(
+ new PublicKeyCredentialParameters(PublicKeyCredentialType.PUBLIC_KEY, COSEAlgorithmIdentifier.RS256), // Windows Hello
+ new PublicKeyCredentialParameters(PublicKeyCredentialType.PUBLIC_KEY, COSEAlgorithmIdentifier.ES256) // FIDO U2F Key, etc
+ )
+ .extensions()
+ .credProps(true)
+ .and()
+ .assertionOptionsEndpoint()
+ .and()
+ .successHandler(authenticationSuccessHandler)
+ .failureHandler(authenticationFailureHandler);
+ });
+ }
+}
+Integrating WebAuthnAuthenticationProvider
+WebAuthnAuthenticationProvider
, an AuthenticationProvider
for Web Authentication, need to be defined as a Bean.
+If you set up two-step authentication combined with password authentication, you also need a Bean definition for DaoAuthenticationProvider
.
@Bean
+ public WebAuthnAuthenticationProvider webAuthnAuthenticationProvider(WebAuthnAuthenticatorService authenticatorService, WebAuthnManager webAuthnManager){
+ return new WebAuthnAuthenticationProvider(authenticatorService, webAuthnManager);
+ }
+
+ @Bean
+ public DaoAuthenticationProvider daoAuthenticationProvider(UserDetailsService userDetailsService){
+ DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider();
+ daoAuthenticationProvider.setUserDetailsService(userDetailsService);
+ daoAuthenticationProvider.setPasswordEncoder(new BCryptPasswordEncoder());
+ return daoAuthenticationProvider;
+ }
+
+ @Bean
+ public AuthenticationManager authenticationManager(List<AuthenticationProvider> providers){
+ return new ProviderManager(providers);
+ }
+1.1.3. Persistence layer integration
+WebAuthn4J Spring Security looks up an authenticator through the WebAuthnCredentialRecordService
interface.
+Please set a class implementing WebAuthnCredentialRecordService
to the WebAuthnAuthenticationProvider
.
+Speaking of Java Config, it can be set through a constructor of WebAuthnAuthenticationProviderConfigurer
.
1.2. Client interface
+W3C Web Authentication specification defines web browser JavaScript APIs only. It is up to implementation how to send a generated credential.
+1.2.1. WebAuthn authentication request processing
+Regarding WebAuthn4J Spring Security, WebAuthnProcessingFilter
retrieves credentialId
, clientData
, authenticatorData
, signature
, and clientExtensionsJSON
from the request sent to login processing url.
+credentialId
, clientData
, authenticatorData
and signature
are binary data, please send them as Base64 strings.
1.2.2. WebAuthn registration request processing
+In contrast to authentication request processing, Servlet filter is not provided for registration request processing +because in most cases, data other than WebAuthn like user’s first name, last name, or email address are sent at the same time.
+While it is basically application’s responsibility to handle an authenticator registration process, WebAuthn4J Spring Security provides converters and validators to examine the received credential.
+Base64StringToCollectedClientDataConverter
converts Base64 string to a CollectedClientData
.
+Base64StringToAttestationObjectConverter
converts Base64 string to a AttestationObject
.
WebAuthnRegistrationRequestValidator
validates an authenticator registration request.
1.2.3. Options endpoints
+Web Authentication needs to obtain a challenge from the server prior to registration and authentication.
+When using the FIDO-U2F token as an authentication device, the CredentialIds associated with the user identified by the first authentication factor also need to be obtained from the server.
+To retrieve these data, WebAuthn4J Spring Security offers AttestationOptionsEndpointFilter
and AssertionOptionsEndpointFilter
.
1.3. Customization
+1.3.1. WebAuthnProcessingFilter
+WebAuthnProcessingFilter
retrieves credentialId
, clientData
, authenticatorData
, signature
, and clientExtensionsJSON
from the request and build WebAuthnAssertionAuthenticationToken
.
+If credentialId
does not exist, it retrieves username
and password
to build UsernamePasswordAuthenticationToken
.
+To change request parameter names, configure properties of WebAuthnProcessingFilter
or corresponding Java Config method of WebAuthnLoginConfigurer
.
1.3.2. WebAuthnAuthenticationProvider
+WebAuthnAuthenticationProvider
is an AuthenticationProvider
implementation to process a WebAuthnAssertionAuthenticationToken
.
+For WebAuthn assertion verification, WebAuthnManager
is used. See WebAuthn4J reference for more details of WebAuthnManager
.
1.3.3. Attestation options endpoint, Assertion options endpoint
+WebAuthn4J Spring Security provides AttestationOptionsEndpointFilter
for WebAuthn JS Credential Creation API parameters serving, and AssertionOptionsEndpointFilter
for WebAuthn JS Credential Get API parameter serving.
+As these Parameters generation are delegated through AttestationOptionsProvider
and AssertionOptionsProvider
interfaces, they can be customized by implementing these interfaces.
These can be customized through Java Config. Method chains from WebAuthnLoginConfigurer
's attestationOptionsEndpoint
method or assertionOptionsEndpoint
method are configuration point for that.
@Configuration
+public class WebSecurityConfig {
+
+ @Bean
+ public SecurityFilterChain filterChain(HttpSecurity http, AuthenticationManager authenticationManager) throws Exception {
+ http.authenticationManager(authenticationManager);
+ // WebAuthn Login
+ http.with(WebAuthnLoginConfigurer.webAuthnLogin(), (customizer) ->{
+ customizer
+ .rpId("example.com")
+ .attestationOptionsEndpoint()
+ .attestationOptionsProvider(attestationOptionsProvider)
+ .processingUrl("/webauthn/attestation/options")
+ .rp()
+ .name("example")
+ .and()
+ .pubKeyCredParams(
+ new PublicKeyCredentialParameters(PublicKeyCredentialType.PUBLIC_KEY, COSEAlgorithmIdentifier.ES256),
+ new PublicKeyCredentialParameters(PublicKeyCredentialType.PUBLIC_KEY, COSEAlgorithmIdentifier.RS1)
+ )
+ .authenticatorSelection()
+ .authenticatorAttachment(AuthenticatorAttachment.CROSS_PLATFORM)
+ .residentKey(ResidentKeyRequirement.PREFERRED)
+ .userVerification(UserVerificationRequirement.PREFERRED)
+ .and()
+ .attestation(AttestationConveyancePreference.DIRECT)
+ .extensions()
+ .credProps(true)
+ .uvm(true)
+ .and()
+ .assertionOptionsEndpoint()
+ .assertionOptionsProvider(assertionOptionsProvider)
+ .processingUrl("/webauthn/assertion/options")
+ .rpId("example.com")
+ .userVerification(UserVerificationRequirement.PREFERRED)
+ .and();
+ });
+ }
+}
+Dynamic generation of PublicKeyCredentialUserEntity
+Attestation options endpoint can generate PublicKeyCredentialUserEntity
to be returned dynamically based on the Authentication
object associated with logged-in user.
+To generate PublicKeyCredentialUserEntity
, PublicKeyCredentialUserEntityProvider
is provided.
Speaking of Java Config, it can be set in this way:
+@Configuration +public class WebSecurityConfig { + + @Bean + public SecurityFilterChain filterChain(HttpSecurity http, AuthenticationManager authenticationManager) throws Exception { + + // WebAuthn Login + http.with(WebAuthnLoginConfigurer.webAuthnLogin(), (customizer) ->{ + customizer + .attestationOptionsEndpoint() + .attestationOptionsProvider(attestationOptionsProvider) + .processingUrl("/webauthn/attestation/options") + .processingUrl("/webauthn/attestation/options") + .user(new MyPublicKeyCredentialUserEntityProvider()); // put your PublicKeyCredentialUserEntityProvider implementation + }); + } +}+
If PublicKeyCredentialUserEntityProvider
is not set explicitly, WebAuthn4J Spring Security Java Config looks it up from Spring Application Context.
+Registering its bean to the application context is another way to set it.
1.3.4. Selecting authentication method
+WebAuthn4J Spring Security supports "Password-less multi-factor authentication with a user-verifying authenticator", "Multi-factor authentication with password and authenticator" and "Single-factor authentication like password". +If you put value on adoption, you may allow password authentication in your web system, or if you give greater importance to security, you may restrict password authentication.
+How to realize password authentication
+To realize "Multi-factor authentication with password and authenticator" and "Single-factor authentication like password", configure not only WebAuthnAuthenticationProvider
but also DaoAuthenticationProvider
to process UsernamePasswordAuthenticationToken
.
+"Multi-factor authentication with password and authenticator" can be realized by including additional authorization requirement to check a user is authenticated by WebAuthn.
Whether it is authenticated by WebAuthn can be checked with the WebAuthnSecurityExpression#isWebAuthnAuthenticated
method.
+Register a bean of WebAuthnSecurityExpression
instance and call it from JavaConfig. WebAuthn4J Spring Security Sample MPA is a good example for it.
1.4. Advanced topics
+1.4.1. Distinction of a user in the middle of multi-factor authentication
+In the case where it is needed to show a different view based on authentication level, one way is to switch the view based on the type of the current Authentication
instance.
@RequestMapping(value = "/login", method = RequestMethod.GET)
+public String login() {
+ Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
+ if (authenticationTrustResolver.isAnonymous(authentication)) {
+ return VIEW_LOGIN_LOGIN;
+ } else {
+ return VIEW_LOGIN_AUTHENTICATOR_LOGIN;
+ }
+}
+1.4.2. Configuring a credential scope (rpId)
+In Web Authentication specification, the scope of a creating credential can be configured through the parameter named "rpId" while creating the credential i.e. registering authenticator.
+"rpId" accepts effective domain.
+For example, in the case where the domain of the site is webauthn.example.com
, and webauthn.example.com
is set to
+rpId
, the credential is only available in webauthn.example.com
and its sub-domain, but if example.com
+is set to rpId
, the scope of the credential is relaxed to example.com
and its sub-domain.
WebAuthn4J Spring Security supports rpId
configuration through the rpId
property of ServerPropertyProviderImpl
, which can be configured through WebAuthnConfigurer
in JavaConfig.
+If you would like to change rpId
dynamically based on request, set RpIdProvider
.
1.4.3. Attestation statement verification
+Web Authentication specification allows the relying party to retrieve an attestation statement from an authenticator if it is requested during authenticator registration. +By verifying attestation statement, the relying party can exclude authenticators not conforming its security requirements. +It’s to be noted that the attestation statement contains information that can be used to track user across web sites, it is discouraged to request an attestation statement unnecessarily. +It is also to be noted that the browser shows an additional dialog to confirm the user consent, lowering usability. +Except for enterprise applications that require strict verification of authenticators, most sites should not request attestation statements.
+WebAuthnRegistrationContextValidator
from WebAuthn4J validates an authenticator registration request, and it delegates attestation statement signature and trustworthiness validation to WebAuthnManager
and
+CertPathTrustworthinessValidator
interface implementation respectively.
WebAuthnRegistrationContextValidator.createNonStrictRegistrationContextValidator
factory method can create the
+WebAuthnRegistrationContextValidator
instance that contains AttestationStatementValidator
and
+CertPathTrustworthinessValidator
configured for web sites not requiring strict attestation verification.
1.4.4. TrustAnchorProvider using Spring Resource
+While validating an authenticator attestation certificate path on registration,
+TrustAnchorCertPathTrustworthinessValidator
class uses TrustAnchor
retrieved through TrustAnchorProvider
interface implementation.
+WebAuthn4J Spring Security offers KeyStoreResourceTrustAnchorProvider
class, which retrieves a
+TrustAnchor
from a Java Key Store file loaded as Spring Resource
.