Make PublicKeyCredentialCreationOptions Serializable
Closes gh-16431 Signed-off-by: Mohammad Amin Pahlevani <pahlevani@live.com>
This commit is contained in:
committed by
Robert Winch
parent
4d0627e6c0
commit
9e5a425859
@@ -20,6 +20,7 @@ import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Field;
|
||||
import java.security.Principal;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
@@ -245,32 +246,11 @@ import org.springframework.security.web.savedrequest.SimpleSavedRequest;
|
||||
import org.springframework.security.web.server.firewall.ServerExchangeRejectedException;
|
||||
import org.springframework.security.web.session.HttpSessionCreatedEvent;
|
||||
import org.springframework.security.web.session.HttpSessionIdChangedEvent;
|
||||
import org.springframework.security.web.webauthn.api.AuthenticationExtensionsClientInputs;
|
||||
import org.springframework.security.web.webauthn.api.AuthenticationExtensionsClientOutputs;
|
||||
import org.springframework.security.web.webauthn.api.AuthenticatorAssertionResponse;
|
||||
import org.springframework.security.web.webauthn.api.AuthenticatorAttachment;
|
||||
import org.springframework.security.web.webauthn.api.AuthenticatorTransport;
|
||||
import org.springframework.security.web.webauthn.api.Bytes;
|
||||
import org.springframework.security.web.webauthn.api.CredProtectAuthenticationExtensionsClientInput;
|
||||
import org.springframework.security.web.webauthn.api.CredentialPropertiesOutput;
|
||||
import org.springframework.security.web.webauthn.api.ImmutableAuthenticationExtensionsClientInput;
|
||||
import org.springframework.security.web.webauthn.api.ImmutableAuthenticationExtensionsClientInputs;
|
||||
import org.springframework.security.web.webauthn.api.ImmutableAuthenticationExtensionsClientOutputs;
|
||||
import org.springframework.security.web.webauthn.api.ImmutablePublicKeyCredentialUserEntity;
|
||||
import org.springframework.security.web.webauthn.api.PublicKeyCredential;
|
||||
import org.springframework.security.web.webauthn.api.PublicKeyCredentialDescriptor;
|
||||
import org.springframework.security.web.webauthn.api.PublicKeyCredentialRequestOptions;
|
||||
import org.springframework.security.web.webauthn.api.PublicKeyCredentialType;
|
||||
import org.springframework.security.web.webauthn.api.PublicKeyCredentialUserEntity;
|
||||
import org.springframework.security.web.webauthn.api.TestAuthenticationAssertionResponses;
|
||||
import org.springframework.security.web.webauthn.api.TestBytes;
|
||||
import org.springframework.security.web.webauthn.api.TestPublicKeyCredentialRequestOptions;
|
||||
import org.springframework.security.web.webauthn.api.TestPublicKeyCredentialUserEntities;
|
||||
import org.springframework.security.web.webauthn.api.TestPublicKeyCredentials;
|
||||
import org.springframework.security.web.webauthn.api.UserVerificationRequirement;
|
||||
import org.springframework.security.web.webauthn.api.*;
|
||||
import org.springframework.security.web.webauthn.authentication.WebAuthnAuthentication;
|
||||
import org.springframework.security.web.webauthn.authentication.WebAuthnAuthenticationRequestToken;
|
||||
import org.springframework.security.web.webauthn.management.RelyingPartyAuthenticationRequest;
|
||||
import org.springframework.security.web.webauthn.management.TestPublicKeyCredentialRpEntities;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
final class SerializationSamples {
|
||||
@@ -879,6 +859,37 @@ final class SerializationSamples {
|
||||
generatorByClassName.put(CredentialPropertiesOutput.ExtensionOutput.class,
|
||||
(r) -> new CredentialPropertiesOutput(true).getOutput());
|
||||
|
||||
AttestationConveyancePreference attestationConveyancePreference = AttestationConveyancePreference.DIRECT;
|
||||
ResidentKeyRequirement residentKeyRequirement = ResidentKeyRequirement.REQUIRED;
|
||||
AuthenticatorSelectionCriteria authenticatorSelectionCriteria = AuthenticatorSelectionCriteria.builder()
|
||||
.authenticatorAttachment(AuthenticatorAttachment.PLATFORM)
|
||||
.residentKey(residentKeyRequirement)
|
||||
.userVerification(UserVerificationRequirement.REQUIRED)
|
||||
.build();
|
||||
PublicKeyCredentialParameters publicKeyCredentialParameters = PublicKeyCredentialParameters.RS256;
|
||||
PublicKeyCredentialRpEntity publicKeyCredentialRpEntity = TestPublicKeyCredentialRpEntities.createRpEntity().build();
|
||||
|
||||
generatorByClassName.put(AttestationConveyancePreference.class, (r) -> attestationConveyancePreference);
|
||||
generatorByClassName.put(ResidentKeyRequirement.class, (r) -> residentKeyRequirement);
|
||||
generatorByClassName.put(AuthenticatorSelectionCriteria.class, (r) -> authenticatorSelectionCriteria);
|
||||
generatorByClassName.put(COSEAlgorithmIdentifier.class, (r -> COSEAlgorithmIdentifier.RS256));
|
||||
generatorByClassName.put(PublicKeyCredentialParameters.class, (r) -> publicKeyCredentialParameters);
|
||||
generatorByClassName.put(PublicKeyCredentialRpEntity.class, (r) -> publicKeyCredentialRpEntity);
|
||||
generatorByClassName.put(PublicKeyCredentialCreationOptions.class, (o) -> TestPublicKeyCredentialCreationOptions.createPublicKeyCredentialCreationOptions()
|
||||
.extensions(inputs)
|
||||
.attestation(attestationConveyancePreference)
|
||||
.authenticatorSelection(authenticatorSelectionCriteria)
|
||||
.challenge(TestBytes.get())
|
||||
.excludeCredentials(List.of(descriptor))
|
||||
.rp(publicKeyCredentialRpEntity)
|
||||
.pubKeyCredParams(publicKeyCredentialParameters)
|
||||
.timeout(Duration.ofMinutes(5))
|
||||
.user(TestPublicKeyCredentialUserEntities.userEntity()
|
||||
.id(TestBytes.get())
|
||||
.build())
|
||||
.build()
|
||||
);
|
||||
|
||||
// One-Time Token
|
||||
DefaultOneTimeToken oneTimeToken = new DefaultOneTimeToken(UUID.randomUUID().toString(), "user",
|
||||
Instant.now().plusSeconds(300));
|
||||
|
||||
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
+7
-1
@@ -16,6 +16,9 @@
|
||||
|
||||
package org.springframework.security.web.webauthn.api;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* <a href="https://www.w3.org/TR/webauthn-3/#webauthn-relying-party">WebAuthn Relying
|
||||
* Parties</a> may use <a href=
|
||||
@@ -26,7 +29,10 @@ package org.springframework.security.web.webauthn.api;
|
||||
* @author Rob Winch
|
||||
* @since 6.4
|
||||
*/
|
||||
public final class AttestationConveyancePreference {
|
||||
public final class AttestationConveyancePreference implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = -4252430175801658788L;
|
||||
|
||||
/**
|
||||
* The <a href=
|
||||
|
||||
+7
-1
@@ -16,6 +16,9 @@
|
||||
|
||||
package org.springframework.security.web.webauthn.api;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
/**
|
||||
@@ -33,7 +36,10 @@ import org.jspecify.annotations.Nullable;
|
||||
* @since 6.4
|
||||
* @see PublicKeyCredentialCreationOptions#getAuthenticatorSelection()
|
||||
*/
|
||||
public final class AuthenticatorSelectionCriteria {
|
||||
public final class AuthenticatorSelectionCriteria implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = -5923595063546985635L;
|
||||
|
||||
private final @Nullable AuthenticatorAttachment authenticatorAttachment;
|
||||
|
||||
|
||||
+7
-1
@@ -16,6 +16,9 @@
|
||||
|
||||
package org.springframework.security.web.webauthn.api;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* <a href=
|
||||
* "https://www.w3.org/TR/webauthn-3/#sctn-alg-identifier">COSEAlgorithmIdentifier</a> is
|
||||
@@ -25,7 +28,10 @@ package org.springframework.security.web.webauthn.api;
|
||||
* @since 6.4
|
||||
* @see PublicKeyCredentialParameters#getAlg()
|
||||
*/
|
||||
public final class COSEAlgorithmIdentifier {
|
||||
public final class COSEAlgorithmIdentifier implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = -4907140472964185350L;
|
||||
|
||||
public static final COSEAlgorithmIdentifier EdDSA = new COSEAlgorithmIdentifier(-8);
|
||||
|
||||
|
||||
+6
-1
@@ -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;
|
||||
@@ -34,7 +36,10 @@ import org.jspecify.annotations.Nullable;
|
||||
* @author Rob Winch
|
||||
* @since 6.4
|
||||
*/
|
||||
public final class PublicKeyCredentialCreationOptions {
|
||||
public final class PublicKeyCredentialCreationOptions implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 800506727675279143L;
|
||||
|
||||
private final PublicKeyCredentialRpEntity rp;
|
||||
|
||||
|
||||
+7
-1
@@ -16,6 +16,9 @@
|
||||
|
||||
package org.springframework.security.web.webauthn.api;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* The <a href=
|
||||
* "https://www.w3.org/TR/webauthn-3/#dictdef-publickeycredentialparameters">PublicKeyCredentialParameters</a>
|
||||
@@ -25,7 +28,10 @@ package org.springframework.security.web.webauthn.api;
|
||||
* @since 6.4
|
||||
* @see PublicKeyCredentialCreationOptions#getPubKeyCredParams()
|
||||
*/
|
||||
public final class PublicKeyCredentialParameters {
|
||||
public final class PublicKeyCredentialParameters implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = -623985171385991L;
|
||||
|
||||
public static final PublicKeyCredentialParameters EdDSA = new PublicKeyCredentialParameters(
|
||||
COSEAlgorithmIdentifier.EdDSA);
|
||||
|
||||
+7
-1
@@ -16,6 +16,9 @@
|
||||
|
||||
package org.springframework.security.web.webauthn.api;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
@@ -29,7 +32,10 @@ import org.springframework.util.Assert;
|
||||
* @author Rob Winch
|
||||
* @since 6.4
|
||||
*/
|
||||
public final class PublicKeyCredentialRpEntity {
|
||||
public final class PublicKeyCredentialRpEntity implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = -2741017471467698174L;
|
||||
|
||||
private final String name;
|
||||
|
||||
|
||||
+7
-1
@@ -16,6 +16,9 @@
|
||||
|
||||
package org.springframework.security.web.webauthn.api;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* The <a href=
|
||||
* "https://www.w3.org/TR/webauthn-3/#enumdef-residentkeyrequirement">ResidentKeyRequirement</a>
|
||||
@@ -24,7 +27,10 @@ package org.springframework.security.web.webauthn.api;
|
||||
* @author Rob Winch
|
||||
* @since 6.4
|
||||
*/
|
||||
public final class ResidentKeyRequirement {
|
||||
public final class ResidentKeyRequirement implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1730700608982834858L;
|
||||
|
||||
/**
|
||||
* The <a href=
|
||||
|
||||
+2
-1
@@ -317,7 +317,8 @@ public class Webauthn4JRelyingPartyOperations implements WebAuthnRelyingPartyOpe
|
||||
|
||||
private com.webauthn4j.data.PublicKeyCredentialParameters convertParamToWebauthn4j(
|
||||
PublicKeyCredentialParameters parameter) {
|
||||
if (parameter.getType() != PublicKeyCredentialType.PUBLIC_KEY) {
|
||||
PublicKeyCredentialType credentialType = PublicKeyCredentialType.valueOf(parameter.getType().getValue());
|
||||
if (credentialType != PublicKeyCredentialType.PUBLIC_KEY) {
|
||||
throw new IllegalArgumentException(
|
||||
"Cannot convert unknown credential type " + parameter.getType() + " to webauthn4j");
|
||||
}
|
||||
|
||||
+33
@@ -16,6 +16,11 @@
|
||||
|
||||
package org.springframework.security.web.webauthn.management;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.time.Duration;
|
||||
import java.util.Arrays;
|
||||
@@ -77,6 +82,7 @@ import org.springframework.security.web.webauthn.api.UserVerificationRequirement
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
||||
import static org.assertj.core.api.Assertions.assertThatNoException;
|
||||
import static org.assertj.core.api.Assertions.assertThatRuntimeException;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
@@ -261,6 +267,33 @@ class Webauthn4jRelyingPartyOperationsTests {
|
||||
AuthenticatorTransport.HYBRID);
|
||||
}
|
||||
|
||||
@Test
|
||||
void registerCredentialWhenCreationOptionsAreJavaDeserializedThenDoesNotThrow()
|
||||
throws IOException, ClassNotFoundException {
|
||||
PublicKeyCredentialCreationOptions creationOptions = TestPublicKeyCredentialCreationOptions
|
||||
.createPublicKeyCredentialCreationOptions()
|
||||
.build();
|
||||
PublicKeyCredential<AuthenticatorAttestationResponse> publicKeyCredential = TestPublicKeyCredentials
|
||||
.createPublicKeyCredential()
|
||||
.build();
|
||||
RelyingPartyPublicKey rpPublicKey = new RelyingPartyPublicKey(publicKeyCredential, this.label);
|
||||
|
||||
try (ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
ObjectOutputStream objectOutputStream = new ObjectOutputStream(out)) {
|
||||
objectOutputStream.writeObject(creationOptions);
|
||||
objectOutputStream.flush();
|
||||
|
||||
try (ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
|
||||
ObjectInputStream objectInputStream = new ObjectInputStream(in)) {
|
||||
PublicKeyCredentialCreationOptions deserialized = (PublicKeyCredentialCreationOptions) objectInputStream
|
||||
.readObject();
|
||||
ImmutableRelyingPartyRegistrationRequest rpRegistrationRequest = new ImmutableRelyingPartyRegistrationRequest(
|
||||
deserialized, rpPublicKey);
|
||||
assertThatNoException().isThrownBy(() -> this.rpOperations.registerCredential(rpRegistrationRequest));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void registerCredentialWhenInternalTransportThenCredentialRecordHasTransport() {
|
||||
PublicKeyCredentialCreationOptions creationOptions = TestPublicKeyCredentialCreationOptions
|
||||
|
||||
Reference in New Issue
Block a user