diff --git a/web/src/main/java/org/springframework/security/web/webauthn/api/AttestationConveyancePreference.java b/web/src/main/java/org/springframework/security/web/webauthn/api/AttestationConveyancePreference.java index 41164faf491..fa65ae1dced 100644 --- a/web/src/main/java/org/springframework/security/web/webauthn/api/AttestationConveyancePreference.java +++ b/web/src/main/java/org/springframework/security/web/webauthn/api/AttestationConveyancePreference.java @@ -16,6 +16,9 @@ package org.springframework.security.web.webauthn.api; +import java.io.Serial; +import java.io.Serializable; + /** * WebAuthn Relying * Parties may use client extension * input entry in the {@link AuthenticationExtensionsClientInputs}. @@ -25,7 +27,7 @@ * @since 6.4 * @see ImmutableAuthenticationExtensionsClientInput */ -public interface AuthenticationExtensionsClientInput { +public interface AuthenticationExtensionsClientInput extends Serializable { /** * Gets the extension diff --git a/web/src/main/java/org/springframework/security/web/webauthn/api/AuthenticationExtensionsClientInputs.java b/web/src/main/java/org/springframework/security/web/webauthn/api/AuthenticationExtensionsClientInputs.java index 44a26a41c12..acd9513af18 100644 --- a/web/src/main/java/org/springframework/security/web/webauthn/api/AuthenticationExtensionsClientInputs.java +++ b/web/src/main/java/org/springframework/security/web/webauthn/api/AuthenticationExtensionsClientInputs.java @@ -16,6 +16,7 @@ package org.springframework.security.web.webauthn.api; +import java.io.Serializable; import java.util.List; /** @@ -31,7 +32,7 @@ * @since 6.4 * @see PublicKeyCredentialCreationOptions#getExtensions() */ -public interface AuthenticationExtensionsClientInputs { +public interface AuthenticationExtensionsClientInputs extends Serializable { /** * Gets all of the {@link AuthenticationExtensionsClientInput}. diff --git a/web/src/main/java/org/springframework/security/web/webauthn/api/AuthenticatorSelectionCriteria.java b/web/src/main/java/org/springframework/security/web/webauthn/api/AuthenticatorSelectionCriteria.java index 6ff7c98600e..46b4b35da9a 100644 --- a/web/src/main/java/org/springframework/security/web/webauthn/api/AuthenticatorSelectionCriteria.java +++ b/web/src/main/java/org/springframework/security/web/webauthn/api/AuthenticatorSelectionCriteria.java @@ -16,6 +16,9 @@ package org.springframework.security.web.webauthn.api; +import java.io.Serial; +import java.io.Serializable; + /** * AuthenticatorAttachment @@ -31,7 +34,10 @@ * @since 6.4 * @see PublicKeyCredentialCreationOptions#getAuthenticatorSelection() */ -public final class AuthenticatorSelectionCriteria { +public final class AuthenticatorSelectionCriteria implements Serializable { + + @Serial + private static final long serialVersionUID = 6295924992300524641L; private final AuthenticatorAttachment authenticatorAttachment; diff --git a/web/src/main/java/org/springframework/security/web/webauthn/api/Bytes.java b/web/src/main/java/org/springframework/security/web/webauthn/api/Bytes.java index 6fbcc3596c6..b8270577e46 100644 --- a/web/src/main/java/org/springframework/security/web/webauthn/api/Bytes.java +++ b/web/src/main/java/org/springframework/security/web/webauthn/api/Bytes.java @@ -16,6 +16,8 @@ package org.springframework.security.web.webauthn.api; +import java.io.Serial; +import java.io.Serializable; import java.security.SecureRandom; import java.util.Arrays; import java.util.Base64; @@ -28,7 +30,10 @@ * @author Rob Winch * @since 6.4 */ -public final class Bytes { +public final class Bytes implements Serializable { + + @Serial + private static final long serialVersionUID = -3278138671365709777L; private static final SecureRandom RANDOM = new SecureRandom(); diff --git a/web/src/main/java/org/springframework/security/web/webauthn/api/COSEAlgorithmIdentifier.java b/web/src/main/java/org/springframework/security/web/webauthn/api/COSEAlgorithmIdentifier.java index 0cafd9309bd..49847fa4f56 100644 --- a/web/src/main/java/org/springframework/security/web/webauthn/api/COSEAlgorithmIdentifier.java +++ b/web/src/main/java/org/springframework/security/web/webauthn/api/COSEAlgorithmIdentifier.java @@ -16,6 +16,9 @@ package org.springframework.security.web.webauthn.api; +import java.io.Serial; +import java.io.Serializable; + /** * COSEAlgorithmIdentifier is @@ -25,7 +28,10 @@ * @since 6.4 * @see PublicKeyCredentialParameters#getAlg() */ -public final class COSEAlgorithmIdentifier { +public final class COSEAlgorithmIdentifier implements Serializable { + + @Serial + private static final long serialVersionUID = -7174114312834239069L; public static final COSEAlgorithmIdentifier EdDSA = new COSEAlgorithmIdentifier(-8); diff --git a/web/src/main/java/org/springframework/security/web/webauthn/api/CredProtectAuthenticationExtensionsClientInput.java b/web/src/main/java/org/springframework/security/web/webauthn/api/CredProtectAuthenticationExtensionsClientInput.java index 22372717595..d315281ab6a 100644 --- a/web/src/main/java/org/springframework/security/web/webauthn/api/CredProtectAuthenticationExtensionsClientInput.java +++ b/web/src/main/java/org/springframework/security/web/webauthn/api/CredProtectAuthenticationExtensionsClientInput.java @@ -16,6 +16,9 @@ package org.springframework.security.web.webauthn.api; +import java.io.Serial; +import java.io.Serializable; + /** * Implements @@ -27,6 +30,9 @@ public class CredProtectAuthenticationExtensionsClientInput implements AuthenticationExtensionsClientInput { + @Serial + private static final long serialVersionUID = -6418175591005843455L; + private final CredProtect input; public CredProtectAuthenticationExtensionsClientInput(CredProtect input) { diff --git a/web/src/main/java/org/springframework/security/web/webauthn/api/ImmutableAuthenticationExtensionsClientInput.java b/web/src/main/java/org/springframework/security/web/webauthn/api/ImmutableAuthenticationExtensionsClientInput.java index eb656c3cdfb..0a28258703f 100644 --- a/web/src/main/java/org/springframework/security/web/webauthn/api/ImmutableAuthenticationExtensionsClientInput.java +++ b/web/src/main/java/org/springframework/security/web/webauthn/api/ImmutableAuthenticationExtensionsClientInput.java @@ -16,6 +16,8 @@ package org.springframework.security.web.webauthn.api; +import java.io.Serial; + /** * An immutable {@link AuthenticationExtensionsClientInput}. * @@ -26,6 +28,9 @@ */ public class ImmutableAuthenticationExtensionsClientInput implements AuthenticationExtensionsClientInput { + @Serial + private static final long serialVersionUID = -1738152485672656808L; + /** * https://www.w3.org/TR/webauthn-3/#sctn-authenticator-credential-properties-extension */ diff --git a/web/src/main/java/org/springframework/security/web/webauthn/api/ImmutableAuthenticationExtensionsClientInputs.java b/web/src/main/java/org/springframework/security/web/webauthn/api/ImmutableAuthenticationExtensionsClientInputs.java index cef29f378a5..1482beee579 100644 --- a/web/src/main/java/org/springframework/security/web/webauthn/api/ImmutableAuthenticationExtensionsClientInputs.java +++ b/web/src/main/java/org/springframework/security/web/webauthn/api/ImmutableAuthenticationExtensionsClientInputs.java @@ -16,6 +16,7 @@ package org.springframework.security.web.webauthn.api; +import java.io.Serial; import java.util.Arrays; import java.util.List; @@ -27,6 +28,9 @@ */ public class ImmutableAuthenticationExtensionsClientInputs implements AuthenticationExtensionsClientInputs { + @Serial + private static final long serialVersionUID = 4277817521578485720L; + private final List inputs; public ImmutableAuthenticationExtensionsClientInputs(List inputs) { diff --git a/web/src/main/java/org/springframework/security/web/webauthn/api/ImmutablePublicKeyCredentialUserEntity.java b/web/src/main/java/org/springframework/security/web/webauthn/api/ImmutablePublicKeyCredentialUserEntity.java index 7374f8fd6e9..c5ffdbcbd00 100644 --- a/web/src/main/java/org/springframework/security/web/webauthn/api/ImmutablePublicKeyCredentialUserEntity.java +++ b/web/src/main/java/org/springframework/security/web/webauthn/api/ImmutablePublicKeyCredentialUserEntity.java @@ -16,6 +16,8 @@ package org.springframework.security.web.webauthn.api; +import java.io.Serial; + /** * PublicKeyCredentialUserEntity @@ -28,6 +30,9 @@ */ public final class ImmutablePublicKeyCredentialUserEntity implements PublicKeyCredentialUserEntity { + @Serial + private static final long serialVersionUID = -3438693960347279759L; + /** * When inherited by PublicKeyCredentialUserEntity, it is a human-palatable identifier * for a user account. It is intended only for display, i.e., aiding the user in diff --git a/web/src/main/java/org/springframework/security/web/webauthn/api/PublicKeyCredentialCreationOptions.java b/web/src/main/java/org/springframework/security/web/webauthn/api/PublicKeyCredentialCreationOptions.java index 2bbdcb9b2b0..1ad47bdee27 100644 --- a/web/src/main/java/org/springframework/security/web/webauthn/api/PublicKeyCredentialCreationOptions.java +++ b/web/src/main/java/org/springframework/security/web/webauthn/api/PublicKeyCredentialCreationOptions.java @@ -16,6 +16,8 @@ package org.springframework.security.web.webauthn.api; +import java.io.Serial; +import java.io.Serializable; import java.time.Duration; import java.util.ArrayList; import java.util.Arrays; @@ -32,7 +34,10 @@ * @author Rob Winch * @since 6.4 */ -public final class PublicKeyCredentialCreationOptions { +public final class PublicKeyCredentialCreationOptions implements Serializable { + + @Serial + private static final long serialVersionUID = -8805501645775760774L; private final PublicKeyCredentialRpEntity rp; diff --git a/web/src/main/java/org/springframework/security/web/webauthn/api/PublicKeyCredentialDescriptor.java b/web/src/main/java/org/springframework/security/web/webauthn/api/PublicKeyCredentialDescriptor.java index ad454814b0f..d4bb1a87dcf 100644 --- a/web/src/main/java/org/springframework/security/web/webauthn/api/PublicKeyCredentialDescriptor.java +++ b/web/src/main/java/org/springframework/security/web/webauthn/api/PublicKeyCredentialDescriptor.java @@ -16,6 +16,8 @@ package org.springframework.security.web.webauthn.api; +import java.io.Serial; +import java.io.Serializable; import java.util.Set; /** @@ -29,7 +31,10 @@ * @author Rob Winch * @since 6.4 */ -public final class PublicKeyCredentialDescriptor { +public final class PublicKeyCredentialDescriptor implements Serializable { + + @Serial + private static final long serialVersionUID = 8793385059692676240L; private final PublicKeyCredentialType type; diff --git a/web/src/main/java/org/springframework/security/web/webauthn/api/PublicKeyCredentialParameters.java b/web/src/main/java/org/springframework/security/web/webauthn/api/PublicKeyCredentialParameters.java index abb8c028330..8e7f3241ad0 100644 --- a/web/src/main/java/org/springframework/security/web/webauthn/api/PublicKeyCredentialParameters.java +++ b/web/src/main/java/org/springframework/security/web/webauthn/api/PublicKeyCredentialParameters.java @@ -16,6 +16,9 @@ package org.springframework.security.web.webauthn.api; +import java.io.Serial; +import java.io.Serializable; + /** * The PublicKeyCredentialParameters @@ -25,7 +28,10 @@ * @since 6.4 * @see PublicKeyCredentialCreationOptions#getPubKeyCredParams() */ -public final class PublicKeyCredentialParameters { +public final class PublicKeyCredentialParameters implements Serializable { + + @Serial + private static final long serialVersionUID = 8471974877710173696L; public static final PublicKeyCredentialParameters EdDSA = new PublicKeyCredentialParameters( COSEAlgorithmIdentifier.EdDSA); diff --git a/web/src/main/java/org/springframework/security/web/webauthn/api/PublicKeyCredentialRpEntity.java b/web/src/main/java/org/springframework/security/web/webauthn/api/PublicKeyCredentialRpEntity.java index d8e7de80141..65723385163 100644 --- a/web/src/main/java/org/springframework/security/web/webauthn/api/PublicKeyCredentialRpEntity.java +++ b/web/src/main/java/org/springframework/security/web/webauthn/api/PublicKeyCredentialRpEntity.java @@ -16,6 +16,9 @@ package org.springframework.security.web.webauthn.api; +import java.io.Serial; +import java.io.Serializable; + /** * The PublicKeyCredentialRpEntity @@ -25,7 +28,10 @@ * @author Rob Winch * @since 6.4 */ -public final class PublicKeyCredentialRpEntity { +public final class PublicKeyCredentialRpEntity implements Serializable { + + @Serial + private static final long serialVersionUID = -5219081524858472915L; private final String name; diff --git a/web/src/main/java/org/springframework/security/web/webauthn/api/PublicKeyCredentialType.java b/web/src/main/java/org/springframework/security/web/webauthn/api/PublicKeyCredentialType.java index 57f1c6ec463..1efcb45254d 100644 --- a/web/src/main/java/org/springframework/security/web/webauthn/api/PublicKeyCredentialType.java +++ b/web/src/main/java/org/springframework/security/web/webauthn/api/PublicKeyCredentialType.java @@ -16,6 +16,9 @@ package org.springframework.security.web.webauthn.api; +import java.io.Serial; +import java.io.Serializable; + /** * The PublicKeyCredentialType @@ -24,7 +27,10 @@ * @author Rob Winch * @since 6.4 */ -public final class PublicKeyCredentialType { +public final class PublicKeyCredentialType implements Serializable { + + @Serial + private static final long serialVersionUID = 7025333122210061679L; /** * The only credential type that currently exists. diff --git a/web/src/main/java/org/springframework/security/web/webauthn/api/PublicKeyCredentialUserEntity.java b/web/src/main/java/org/springframework/security/web/webauthn/api/PublicKeyCredentialUserEntity.java index f5da998fd83..cade3a009c8 100644 --- a/web/src/main/java/org/springframework/security/web/webauthn/api/PublicKeyCredentialUserEntity.java +++ b/web/src/main/java/org/springframework/security/web/webauthn/api/PublicKeyCredentialUserEntity.java @@ -19,6 +19,8 @@ import org.springframework.security.web.webauthn.management.RelyingPartyAuthenticationRequest; import org.springframework.security.web.webauthn.management.WebAuthnRelyingPartyOperations; +import java.io.Serializable; + /** * PublicKeyCredentialUserEntity @@ -30,7 +32,7 @@ * @since 6.4 * @see WebAuthnRelyingPartyOperations#authenticate(RelyingPartyAuthenticationRequest) */ -public interface PublicKeyCredentialUserEntity { +public interface PublicKeyCredentialUserEntity extends Serializable { /** * The ResidentKeyRequirement @@ -24,7 +27,10 @@ * @author Rob Winch * @since 6.4 */ -public final class ResidentKeyRequirement { +public final class ResidentKeyRequirement implements Serializable { + + @Serial + private static final long serialVersionUID = 2047716518193458797L; /** * The UserVerificationRequirement @@ -24,7 +27,10 @@ * @author Rob Winch * @since 6.4 */ -public final class UserVerificationRequirement { +public final class UserVerificationRequirement implements Serializable { + + @Serial + private static final long serialVersionUID = -2801001231345540040L; /** * The { + @Serial + private static final long serialVersionUID = -5579815774497047153L; + /** * Creates a new instance. */ diff --git a/web/src/main/java/org/springframework/security/web/webauthn/management/Webauthn4JRelyingPartyOperations.java b/web/src/main/java/org/springframework/security/web/webauthn/management/Webauthn4JRelyingPartyOperations.java index e1983079fc9..a7c368ec279 100644 --- a/web/src/main/java/org/springframework/security/web/webauthn/management/Webauthn4JRelyingPartyOperations.java +++ b/web/src/main/java/org/springframework/security/web/webauthn/management/Webauthn4JRelyingPartyOperations.java @@ -290,7 +290,7 @@ private List convertCredentia private com.webauthn4j.data.PublicKeyCredentialParameters convertParamToWebauthn4j( PublicKeyCredentialParameters parameter) { - if (parameter.getType() != PublicKeyCredentialType.PUBLIC_KEY) { + if (!PublicKeyCredentialType.PUBLIC_KEY.getValue().equals(parameter.getType().getValue())) { throw new IllegalArgumentException( "Cannot convert unknown credential type " + parameter.getType() + " to webauthn4j"); } diff --git a/web/src/test/java/org/springframework/security/web/webauthn/management/Webauthn4jRelyingPartyOperationsTests.java b/web/src/test/java/org/springframework/security/web/webauthn/management/Webauthn4jRelyingPartyOperationsTests.java index dc597918354..25f6aa2a111 100644 --- a/web/src/test/java/org/springframework/security/web/webauthn/management/Webauthn4jRelyingPartyOperationsTests.java +++ b/web/src/test/java/org/springframework/security/web/webauthn/management/Webauthn4jRelyingPartyOperationsTests.java @@ -16,6 +16,10 @@ package org.springframework.security.web.webauthn.management; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; import java.nio.charset.StandardCharsets; import java.time.Duration; import java.util.Arrays; @@ -60,6 +64,7 @@ import org.springframework.security.web.webauthn.api.TestPublicKeyCredentialCreationOptions; import org.springframework.security.web.webauthn.api.TestPublicKeyCredentialUserEntity; import org.springframework.security.web.webauthn.api.UserVerificationRequirement; +import org.springframework.util.SerializationUtils; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; @@ -494,6 +499,30 @@ void createCredentialRequestOptionsThenUserVerificationSameAsCreation() { .isEqualTo(creationOptions.getAuthenticatorSelection().getUserVerification()); } + @Test + void convertParamToWebauthn4jPublicKeyComparison() throws Exception { + + PublicKeyCredentialCreationOptions options = TestPublicKeyCredentialCreationOptions + .createPublicKeyCredentialCreationOptions() + .build(); + + // Simulate storage into external session storage: serialize/deserialize of the creation options + ByteArrayOutputStream bo = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(bo); + oos.writeObject(options); + + ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bo.toByteArray())); + PublicKeyCredentialCreationOptions copiedOptions = (PublicKeyCredentialCreationOptions)ois.readObject() ; + + // Check that the deep copied options are still valid + PublicKeyCredential publicKey = TestPublicKeyCredential.createPublicKeyCredential().build(); + ImmutableRelyingPartyRegistrationRequest registrationRequest = new ImmutableRelyingPartyRegistrationRequest( + copiedOptions, new RelyingPartyPublicKey(publicKey, this.label)); + + // Should not throw an exception + this.rpOperations.registerCredential(registrationRequest); + } + private static AuthenticatorAttestationResponse setFlag(byte... flags) throws Exception { AuthenticatorAttestationResponseBuilder authAttResponseBldr = TestAuthenticatorAttestationResponse .createAuthenticatorAttestationResponse();