[java-idp-plugin-webauthn] branch main updated: JWEBAUTHN-26 - Allow metadata to be attached to registrations retroactively
Phil Smart
philip.smart at jisc.ac.uk
Wed Sep 11 14:59:22 UTC 2024
This is an automated email from the git hooks/post-receive script.
philsmart pushed a commit to branch main
in repository java-idp-plugin-webauthn.
View the commit online:
http://git.shibboleth.net/view/?p=java-idp-plugin-webauthn.git;a=commit;h=69e921e617cdb474c43d8d2fdb7b02ab437819c8
The following commit(s) were added to refs/heads/main by this push:
new 69e921e JWEBAUTHN-26 - Allow metadata to be attached to registrations retroactively
69e921e is described below
commit 69e921e617cdb474c43d8d2fdb7b02ab437819c8
Author: Phil Smart <philip.smart at jisc.ac.uk>
AuthorDate: Wed Sep 11 15:59:20 2024 +0100
JWEBAUTHN-26 - Allow metadata to be attached to registrations
retroactively
- Remove the metadata entry from the storage record
- Add an enhanced credential registration wrapper, for storing the
credential and authenticator metadata
- Add metadata lookup (if the metadata service is configured) during
the credential lookup action of the authn, registration, and management
flows
https://shibboleth.atlassian.net/browse/JWEBAUTHN-26
---
.../webauthn/context/BaseWebAuthnContext.java | 10 +-
.../context/WebAuthnManagementContext.java | 10 +-
.../webauthn/storage/CredentialRegistration.java | 90 +--------
.../storage/EnhancedCredentialRegistration.java | 207 +++++++++++++++++++++
.../CreatePublicKeyCredentialCreationOptions.java | 2 +-
...a => ExtractKeyInformationFromFormRequest.java} | 10 +-
.../admin/impl/LookupCredentialsForUser.java | 20 +-
.../admin/impl/StorePublicKeyCredential.java | 28 ---
.../webauthn/impl/AbstractWebAuthnAction.java | 30 +++
.../CreatePublicKeyCredentialRequestOptions.java | 5 +-
.../webauthn/impl/LookupRegisteredCredentials.java | 18 +-
.../authn/webauthn/impl/WebAuthnEncoder.java | 16 +-
.../webauthn-management-beans.xml | 2 +-
.../webauthn-management-flow.xml | 14 +-
.../webauthn-registration-beans.xml | 4 +-
.../webauthn-registration-flow.xml | 2 +-
.../authn/WebAuthn/webauthn-abstract-beans.xml | 3 +-
.../idp/plugin/authn/webauthn/messages.properties | 2 +
.../authn/webauthn/views/webauthn-management.vm | 22 ++-
.../authn/webauthn/views/webauthn-register.vm | 10 +-
...eatePublicKeyCredentialCreationOptionsTest.java | 4 +-
...ctKeyRemovalInformationFromFormRequestTest.java | 10 +-
.../YubicoWebauthnAuthenticationClientTest.java | 5 -
.../webauthn/flow/AbstractWebAuthnFlowTest.java | 2 -
.../webauthn/flow/TestAdminManagementFlow.java | 4 +-
.../authn/webauthn/flow/TestRegistrationFlow.java | 6 +-
.../authn/webauthn/impl/AbstractWebAuthnTest.java | 1 -
...kupRegisteredCredentialsFromUserHandleTest.java | 3 -
.../impl/LookupRegisteredCredentialsTest.java | 2 -
.../impl/CredentialRegistrationSerializerTest.java | 1 -
...IdPStorageServiceCredentialRespositoryTest.java | 2 -
31 files changed, 359 insertions(+), 186 deletions(-)
diff --git a/webauthn-api/src/main/java/net/shibboleth/idp/plugin/authn/webauthn/context/BaseWebAuthnContext.java b/webauthn-api/src/main/java/net/shibboleth/idp/plugin/authn/webauthn/context/BaseWebAuthnContext.java
index d4c21f9..adb2db3 100644
--- a/webauthn-api/src/main/java/net/shibboleth/idp/plugin/authn/webauthn/context/BaseWebAuthnContext.java
+++ b/webauthn-api/src/main/java/net/shibboleth/idp/plugin/authn/webauthn/context/BaseWebAuthnContext.java
@@ -23,7 +23,7 @@ import org.opensaml.messaging.context.BaseContext;
import com.yubico.webauthn.data.UserVerificationRequirement;
-import net.shibboleth.idp.plugin.authn.webauthn.storage.CredentialRegistration;
+import net.shibboleth.idp.plugin.authn.webauthn.storage.EnhancedCredentialRegistration;
import net.shibboleth.shared.annotation.constraint.NotLive;
import net.shibboleth.shared.annotation.constraint.Unmodifiable;
import net.shibboleth.shared.collection.CollectionSupport;
@@ -44,7 +44,7 @@ public class BaseWebAuthnContext extends BaseContext {
* Credentials that have already been registered with the IdP. The authenticator should use these to avoid creating
* duplicate credentials during registration, or to tell the browser which credentials to use during authentication.
*/
- @Nullable private Collection<CredentialRegistration> existingCredentials;
+ @Nullable private Collection<EnhancedCredentialRegistration> existingCredentials;
/** The challenge sent to the authenticator in both registration and authentication ceremonies.*/
@Nullable private byte[] serverChallenge;
@@ -96,7 +96,7 @@ public class BaseWebAuthnContext extends BaseContext {
* @return this context
*/
@Nonnull public BaseWebAuthnContext setExistingCredentials(
- @Nullable final Collection<CredentialRegistration> credentials) {
+ @Nullable final Collection<EnhancedCredentialRegistration> credentials) {
existingCredentials = credentials;
return this;
}
@@ -106,8 +106,8 @@ public class BaseWebAuthnContext extends BaseContext {
*
* @return the existing credentials.
*/
- @Nonnull @Unmodifiable @NotLive public Collection<CredentialRegistration> getExistingCredentials() {
- final Collection<CredentialRegistration> localExistingCredentials = existingCredentials;
+ @Nonnull @Unmodifiable @NotLive public Collection<EnhancedCredentialRegistration> getExistingCredentials() {
+ final Collection<EnhancedCredentialRegistration> localExistingCredentials = existingCredentials;
if (localExistingCredentials == null) {
return CollectionSupport.emptyList();
}
diff --git a/webauthn-api/src/main/java/net/shibboleth/idp/plugin/authn/webauthn/context/WebAuthnManagementContext.java b/webauthn-api/src/main/java/net/shibboleth/idp/plugin/authn/webauthn/context/WebAuthnManagementContext.java
index bf5a969..7b8ddaf 100644
--- a/webauthn-api/src/main/java/net/shibboleth/idp/plugin/authn/webauthn/context/WebAuthnManagementContext.java
+++ b/webauthn-api/src/main/java/net/shibboleth/idp/plugin/authn/webauthn/context/WebAuthnManagementContext.java
@@ -21,7 +21,7 @@ import javax.annotation.Nullable;
import org.opensaml.messaging.context.BaseContext;
-import net.shibboleth.idp.plugin.authn.webauthn.storage.CredentialRegistration;
+import net.shibboleth.idp.plugin.authn.webauthn.storage.EnhancedCredentialRegistration;
import net.shibboleth.shared.annotation.constraint.NotLive;
import net.shibboleth.shared.annotation.constraint.Unmodifiable;
import net.shibboleth.shared.collection.CollectionSupport;
@@ -38,7 +38,7 @@ public class WebAuthnManagementContext extends BaseContext {
@Nullable private String searchUsername;
/** The located set of credentials registered for the given searchUsername.*/
- @Nullable @Unmodifiable @NotLive private Collection<CredentialRegistration> foundCredentials;
+ @Nullable @Unmodifiable @NotLive private Collection<EnhancedCredentialRegistration> foundCredentials;
/** The ID of a credential that is going to be removed.*/
@Nullable private byte[] credentialIdToRemove;
@@ -95,7 +95,7 @@ public class WebAuthnManagementContext extends BaseContext {
* @return this context
*/
@Nonnull public WebAuthnManagementContext setFoundCredentials(
- @Nullable final Collection<CredentialRegistration> credentials) {
+ @Nullable final Collection<EnhancedCredentialRegistration> credentials) {
if (credentials == null) {
foundCredentials = CollectionSupport.emptyList();
} else {
@@ -109,8 +109,8 @@ public class WebAuthnManagementContext extends BaseContext {
*
* @return the credentials.
*/
- @Nonnull @Unmodifiable @NotLive public Collection<CredentialRegistration> getFoundCredentials() {
- final Collection<CredentialRegistration> localFoundCredentials = foundCredentials;
+ @Nonnull @Unmodifiable @NotLive public Collection<EnhancedCredentialRegistration> getFoundCredentials() {
+ final Collection<EnhancedCredentialRegistration> localFoundCredentials = foundCredentials;
if (localFoundCredentials == null) {
return CollectionSupport.emptyList();
}
diff --git a/webauthn-api/src/main/java/net/shibboleth/idp/plugin/authn/webauthn/storage/CredentialRegistration.java b/webauthn-api/src/main/java/net/shibboleth/idp/plugin/authn/webauthn/storage/CredentialRegistration.java
index 94bbc5b..dd69865 100644
--- a/webauthn-api/src/main/java/net/shibboleth/idp/plugin/authn/webauthn/storage/CredentialRegistration.java
+++ b/webauthn-api/src/main/java/net/shibboleth/idp/plugin/authn/webauthn/storage/CredentialRegistration.java
@@ -18,7 +18,6 @@ import java.time.Instant;
import java.util.Collections;
import java.util.Objects;
import java.util.Optional;
-import java.util.Set;
import java.util.SortedSet;
import javax.annotation.Nonnull;
@@ -31,7 +30,6 @@ import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;
-import com.yubico.fido.metadata.MetadataBLOBPayloadEntry;
import com.yubico.webauthn.RegisteredCredential;
import com.yubico.webauthn.data.AuthenticatorTransport;
import com.yubico.webauthn.data.PublicKeyCredentialDescriptor;
@@ -39,7 +37,6 @@ import com.yubico.webauthn.data.UserIdentity;
import net.shibboleth.shared.annotation.constraint.NonnullElements;
import net.shibboleth.shared.annotation.constraint.Unmodifiable;
-import net.shibboleth.shared.collection.CollectionSupport;
import net.shibboleth.shared.logic.Constraint;
/**
@@ -72,9 +69,6 @@ public final class CredentialRegistration {
/** The credential to register. */
@Nonnull @Unmodifiable @NonnullElements private final RegisteredCredential credential;
-
- /** Optional attestation metadata about the authenticator. Will be an empty set if not used. */
- @Nonnull @Unmodifiable @NonnullElements private final Set<MetadataBLOBPayloadEntry> attestationMetadata;
/** The AAGUID of the authenticator.*/
@Nullable private final byte[] aaguid;
@@ -95,7 +89,6 @@ public final class CredentialRegistration {
this.credential = builder.credential;
this.credentialNickname = builder.credentialNickname;
this.discoverable = builder.discoverable;
- this.attestationMetadata = builder.attestationMetadata;
this.userVerified = builder.userVerified;
this.aaguid = builder.aaguid;
@@ -184,17 +177,6 @@ public final class CredentialRegistration {
return transports;
}
- /**
- * Get metadata about an authenticators attestation.
- *
- * @return the metadata about an authenticators attestation
- */
- @JsonGetter("attestationMetadata")
- @Nonnull @Unmodifiable @NonnullElements public Set<MetadataBLOBPayloadEntry> getAttestationMetadata(){
- return attestationMetadata;
-
- }
-
/**
* Get the AAGUID of the authenticator that created this credential. This is optional, for example if attestation
* is not requested.
@@ -216,53 +198,6 @@ public final class CredentialRegistration {
return credential.getCredentialId().getBase64Url();
}
- /**
- * Get the human-readable, short description of the authenticator (in English) iff the attestation metadata exist.
- *
- * <p>If there is more than one metadata entry, it picks the first it can find with a description.</p>
- *
- * @return the human-readable, short description of the authenticator (in English), or <code>null</code>.
- */
- @JsonIgnore
- @Nullable public String getAuthenticatorDescription() {
- if (!attestationMetadata.isEmpty()) {
- final Optional<Optional<String>> descriptionFound = attestationMetadata.stream()
- .filter(mtd -> mtd.getMetadataStatement().isPresent())
- .map(mtd -> mtd.getMetadataStatement().get().getDescription()).findFirst();
-
- if (descriptionFound.isEmpty() || descriptionFound.get().isEmpty() ||
- descriptionFound.get().get().isEmpty()) {
- return null;
- }
- return descriptionFound.get().get();
- }
- return null;
- }
-
- /**
- * Get a <code>data:</code> URL encoded PNG icon for the authenticator.
- *
- * <p>If there is more than one metadata entry, it picks the first it can find with an icon.</p>
- *
- * @return the icon encoded as a PNG <code>data:</code> URL
- */
- @JsonIgnore
- @Nullable public String getIcon() {
- if (!attestationMetadata.isEmpty()) {
- final Optional<Optional<String>> iconFound = attestationMetadata.stream()
- .filter(mtd -> mtd.getMetadataStatement().isPresent())
- .map(mtd -> mtd.getMetadataStatement().get().getIcon()).findFirst();
-
- if (iconFound.isEmpty() || iconFound.get().isEmpty() ||
- iconFound.get().get().isEmpty()) {
- return null;
- }
- return iconFound.get().get();
- }
- return null;
-
- }
-
/**
* Convert the credential registration into a {@link PublicKeyCredentialDescriptor}.
*
@@ -300,9 +235,9 @@ public final class CredentialRegistration {
final CredentialRegistration other = (CredentialRegistration) obj;
return Objects.equals(credential, other.credential);
}
-
+
/**
- * Copy this instance into a new credential registration instance replacing the registered credential with that
+ * Copy this instance into a new credential registration instance replacing he registered credential with that
* given.
*
* @param newRegisteredCred the new credential
@@ -317,7 +252,6 @@ public final class CredentialRegistration {
.withRegistrationTime(registrationTime)
// The credential here is the new one
.withCredential(newRegisteredCred)
- .withAttestationMetadata(attestationMetadata)
.withAaguid(aaguid)
.withCredentialNickname(credentialNickname)
.withDiscoverable(discoverable)
@@ -394,15 +328,6 @@ public final class CredentialRegistration {
*/
@Nonnull public IBuildStage withDiscoverable(@Nonnull final Optional<Boolean> discoverable);
- /**
- * Set the optional attestation metadata about the authenticator.
- *
- * @param attestationMetadata the metadata
- * @return the next builder stage
- */
- @Nonnull public IBuildStage withAttestationMetadata(
- @Nonnull final Set<MetadataBLOBPayloadEntry> attestationMetadata);
-
/**
* Was the user verified during registration?
*
@@ -442,8 +367,6 @@ public final class CredentialRegistration {
@Nullable private String credentialNickname;
/** Is the credential a discoverable type.*/
@Nonnull private Optional<Boolean> discoverable;
- /** Attestation metadata.*/
- @Nonnull private Set<MetadataBLOBPayloadEntry> attestationMetadata;
/** has the user been verified.*/
private boolean userVerified;
/** The AAGUID of the authenticator.*/
@@ -456,7 +379,6 @@ public final class CredentialRegistration {
discoverable = Optional.empty();
userVerified = false;
transports = Collections.emptySortedSet();
- attestationMetadata = CollectionSupport.emptySet();
}
@Override
@@ -506,14 +428,6 @@ public final class CredentialRegistration {
return this;
}
- @Override
- @JsonProperty("attestationMetadata")
- @Nonnull public IBuildStage withAttestationMetadata(
- @Nonnull final Set<MetadataBLOBPayloadEntry> attestationMtd) {
- attestationMetadata = attestationMtd;
- return this;
- }
-
@Override
@JsonProperty("userVerified")
@Nonnull public IBuildStage withUserVerified(final boolean isUserVerified) {
diff --git a/webauthn-api/src/main/java/net/shibboleth/idp/plugin/authn/webauthn/storage/EnhancedCredentialRegistration.java b/webauthn-api/src/main/java/net/shibboleth/idp/plugin/authn/webauthn/storage/EnhancedCredentialRegistration.java
new file mode 100644
index 0000000..e6f6edf
--- /dev/null
+++ b/webauthn-api/src/main/java/net/shibboleth/idp/plugin/authn/webauthn/storage/EnhancedCredentialRegistration.java
@@ -0,0 +1,207 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.shibboleth.idp.plugin.authn.webauthn.storage;
+
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import com.yubico.fido.metadata.MetadataBLOBPayloadEntry;
+
+import net.shibboleth.shared.annotation.constraint.NonnullAfterInit;
+import net.shibboleth.shared.annotation.constraint.NonnullElements;
+import net.shibboleth.shared.annotation.constraint.NotLive;
+import net.shibboleth.shared.annotation.constraint.Unmodifiable;
+import net.shibboleth.shared.collection.CollectionSupport;
+import net.shibboleth.shared.logic.Constraint;
+
+/**
+ * An ephemeral wrapper class that holds a {@link CredentialRegistration} and any associated metadata. Created and
+ * used during registration or authentication and then discarded. This is not meant to be serialised or stored.
+ */
+public class EnhancedCredentialRegistration {
+
+ /** The wrapped credential registration.*/
+ @Nonnull private final CredentialRegistration credentialRegistration;
+
+ /** Optional metadata about the authenticator. Will be an empty set if not used. */
+ @Nonnull @Unmodifiable @NonnullElements @NotLive private final Set<MetadataBLOBPayloadEntry> authenticatorMetadata;
+
+ /**
+ *
+ * Constructor.
+ *
+ * @param builder the builder to construct this instance from
+ */
+ private EnhancedCredentialRegistration(final Builder builder) {
+ this.credentialRegistration = builder.credentialRegistration;
+ this.authenticatorMetadata = builder.authenticatorMetadata;
+ }
+
+ /**
+ * Get the wrapped credential registration.
+ *
+ * @return the wrapped credentialRegistration.
+ */
+ public CredentialRegistration getCredentialRegistration() {
+ return credentialRegistration;
+ }
+
+ /**
+ * Get the authenticator metadata.
+ *
+ * @return Returns the attestationMetadata.
+ */
+ @Nonnull @Unmodifiable @NonnullElements @NotLive
+ public synchronized Set<MetadataBLOBPayloadEntry> getAuthenticatorMetadata() {
+ return authenticatorMetadata;
+ }
+
+ /**
+ * Get the human-readable, short description of the authenticator (in English) iff the attestation metadata exist.
+ *
+ * <p>If there is more than one metadata entry, it picks the first it can find with a description.</p>
+ *
+ * @return the human-readable, short description of the authenticator (in English), or <code>null</code>.
+ */
+ @Nullable public String getAuthenticatorDescription() {
+ if (!authenticatorMetadata.isEmpty()) {
+ final Optional<Optional<String>> descriptionFound = authenticatorMetadata.stream()
+ .filter(mtd -> mtd.getMetadataStatement().isPresent())
+ .map(mtd -> mtd.getMetadataStatement().get().getDescription()).findFirst();
+
+ if (descriptionFound.isEmpty() || descriptionFound.get().isEmpty() ||
+ descriptionFound.get().get().isEmpty()) {
+ return null;
+ }
+ return descriptionFound.get().get();
+ }
+ return null;
+ }
+
+ /**
+ * Get a <code>data:</code> URL encoded PNG icon for the authenticator.
+ *
+ * <p>If there is more than one metadata entry, it picks the first it can find with an icon.</p>
+ *
+ * @return the icon encoded as a PNG <code>data:</code> URL
+ */
+ @Nullable public String getIcon() {
+ if (!authenticatorMetadata.isEmpty()) {
+ final Optional<Optional<String>> iconFound = authenticatorMetadata.stream()
+ .filter(mtd -> mtd.getMetadataStatement().isPresent())
+ .map(mtd -> mtd.getMetadataStatement().get().getIcon()).findFirst();
+
+ if (iconFound.isEmpty() || iconFound.get().isEmpty() ||
+ iconFound.get().get().isEmpty()) {
+ return null;
+ }
+ return iconFound.get().get();
+ }
+ return null;
+
+ }
+
+ /**
+ * The builder.
+ *
+ * @return the next stage
+ */
+ public static ICredentialRegistrationStage builder() {
+ return new Builder();
+ }
+
+ /**
+ * A builder stage.
+ */
+ public interface ICredentialRegistrationStage {
+ /**
+ * Set the credential registration.
+ *
+ * @param credentialRegistration the registration
+ *
+ * @return the next stage
+ */
+ public IBuildStage withCredentialRegistration(@Nonnull final CredentialRegistration credentialRegistration);
+ }
+
+ /**
+ * A builder stage.
+ */
+ public interface IBuildStage {
+ /**
+ * Set the metadata for the authenticator that created the credential.
+ *
+ * @param authenticatorMetadata the metadata
+ *
+ * @return the next stage
+ */
+ public IBuildStage withAuthenticatorMetadata(
+ @Nullable final Set<MetadataBLOBPayloadEntry> authenticatorMetadata);
+
+ /**
+ * Build this object.
+ *
+ * @return an instance of this object
+ */
+ public EnhancedCredentialRegistration build();
+ }
+
+ /**
+ * The builder.
+ */
+ public static final class Builder implements ICredentialRegistrationStage, IBuildStage {
+ /** The wrapped credential registration.*/
+ @NonnullAfterInit private CredentialRegistration credentialRegistration;
+ /** Optional metadata about the authenticator. Will be an empty set if not used. */
+ @Nonnull @Unmodifiable @NonnullElements @NotLive
+ private Set<MetadataBLOBPayloadEntry> authenticatorMetadata;
+
+ /** Constructor.*/
+ private Builder() {
+ authenticatorMetadata = CollectionSupport.emptySet();
+ }
+
+ @Override
+ public IBuildStage withCredentialRegistration(
+ @Nonnull final CredentialRegistration registration) {
+ credentialRegistration = Constraint.isNotNull(registration, "Registration can not be null");
+ return this;
+ }
+
+ @Override
+ public IBuildStage withAuthenticatorMetadata(@Nullable final Set<MetadataBLOBPayloadEntry> metadata) {
+ if (metadata != null) {
+ authenticatorMetadata = CollectionSupport.copyToSet(metadata.stream().filter(Objects::nonNull)
+ .collect(CollectionSupport.nonnullCollector(Collectors.toSet())).get());
+ }
+ return this;
+ }
+
+ @Override
+ public EnhancedCredentialRegistration build() {
+ return new EnhancedCredentialRegistration(this);
+ }
+ }
+
+
+
+
+
+}
diff --git a/webauthn-impl/src/main/java/net/shibboleth/idp/plugin/authn/webauthn/admin/impl/CreatePublicKeyCredentialCreationOptions.java b/webauthn-impl/src/main/java/net/shibboleth/idp/plugin/authn/webauthn/admin/impl/CreatePublicKeyCredentialCreationOptions.java
index 4c720e5..805c60e 100644
--- a/webauthn-impl/src/main/java/net/shibboleth/idp/plugin/authn/webauthn/admin/impl/CreatePublicKeyCredentialCreationOptions.java
+++ b/webauthn-impl/src/main/java/net/shibboleth/idp/plugin/authn/webauthn/admin/impl/CreatePublicKeyCredentialCreationOptions.java
@@ -111,7 +111,7 @@ public class CreatePublicKeyCredentialCreationOptions extends AbstractWebAuthnAc
try {
final Set<PublicKeyCredentialDescriptor> existingCredentialDescriptors = context.getExistingCredentials()
- .stream()
+ .stream().map(cred -> cred.getCredentialRegistration())
.map(cred -> cred.toPublicKeyCredentialDescriptor())
.filter(Objects::nonNull)
.collect(Collectors.toSet());
diff --git a/webauthn-impl/src/main/java/net/shibboleth/idp/plugin/authn/webauthn/admin/impl/ExtractKeyRemovalInformationFromFormRequest.java b/webauthn-impl/src/main/java/net/shibboleth/idp/plugin/authn/webauthn/admin/impl/ExtractKeyInformationFromFormRequest.java
similarity index 92%
rename from webauthn-impl/src/main/java/net/shibboleth/idp/plugin/authn/webauthn/admin/impl/ExtractKeyRemovalInformationFromFormRequest.java
rename to webauthn-impl/src/main/java/net/shibboleth/idp/plugin/authn/webauthn/admin/impl/ExtractKeyInformationFromFormRequest.java
index 859f9dd..3eb6fa6 100644
--- a/webauthn-impl/src/main/java/net/shibboleth/idp/plugin/authn/webauthn/admin/impl/ExtractKeyRemovalInformationFromFormRequest.java
+++ b/webauthn-impl/src/main/java/net/shibboleth/idp/plugin/authn/webauthn/admin/impl/ExtractKeyInformationFromFormRequest.java
@@ -37,20 +37,20 @@ import net.shibboleth.shared.primitive.StringSupport;
/**
- * An action that extracts the credential ID for removal from the incoming HTTP request and uses a {@link BiConsumer}
+ * An action that extracts the credential ID for from the incoming HTTP request and uses a {@link BiConsumer}
* to set that back onto an appropriate context.
*
* @event {WebAuthnRegistrationEventIds#INVALID_ADMIN_ACTION}
* @event {EventIds#INVALID_PROFILE_CTX}
* @post add credential ID to remove to the context
*/
-public class ExtractKeyRemovalInformationFromFormRequest extends AbstractProfileAction {
+public class ExtractKeyInformationFromFormRequest extends AbstractProfileAction {
/** Default credential Id parameter name. */
@Nonnull @NotEmpty public static final String DEFAULT_PARAMETER_NAME = "credentialId";
/** Class logger. */
- @Nonnull private final Logger log = LoggerFactory.getLogger(ExtractKeyRemovalInformationFromFormRequest.class);
+ @Nonnull private final Logger log = LoggerFactory.getLogger(ExtractKeyInformationFromFormRequest.class);
/** Name of credential Id parameter. */
@Nonnull @NotEmpty private String credentialIdParameterName;
@@ -59,7 +59,7 @@ public class ExtractKeyRemovalInformationFromFormRequest extends AbstractProfile
@NonnullAfterInit private BiConsumer<ProfileRequestContext, byte[]> contextSettingConsumer;
/** Constructor. */
- public ExtractKeyRemovalInformationFromFormRequest() {
+ public ExtractKeyInformationFromFormRequest() {
credentialIdParameterName = DEFAULT_PARAMETER_NAME;
}
@@ -117,7 +117,7 @@ public class ExtractKeyRemovalInformationFromFormRequest extends AbstractProfile
contextSettingConsumer.accept(profileRequestContext, credentialIdAsBytes);
log.trace("{} Credential to remove '{}'",getLogPrefix(),credentialId);
} catch (final DecodingException e) {
- log.debug("{} Unable to base64 decode credentialID, can not remove credential", getLogPrefix());
+ log.debug("{} Unable to base64 decode credentialID, can not set credential", getLogPrefix());
ActionSupport.buildEvent(profileRequestContext, WebAuthnRegistrationEventIds.INVALID_ADMIN_ACTION);
return;
}
diff --git a/webauthn-impl/src/main/java/net/shibboleth/idp/plugin/authn/webauthn/admin/impl/LookupCredentialsForUser.java b/webauthn-impl/src/main/java/net/shibboleth/idp/plugin/authn/webauthn/admin/impl/LookupCredentialsForUser.java
index a9d4dab..f207f24 100644
--- a/webauthn-impl/src/main/java/net/shibboleth/idp/plugin/authn/webauthn/admin/impl/LookupCredentialsForUser.java
+++ b/webauthn-impl/src/main/java/net/shibboleth/idp/plugin/authn/webauthn/admin/impl/LookupCredentialsForUser.java
@@ -15,6 +15,8 @@
package net.shibboleth.idp.plugin.authn.webauthn.admin.impl;
import java.util.Collection;
+import java.util.HashSet;
+import java.util.Objects;
import javax.annotation.Nonnull;
@@ -22,10 +24,14 @@ import org.opensaml.messaging.context.navigate.ChildContextLookup;
import org.opensaml.profile.context.ProfileRequestContext;
import org.slf4j.Logger;
+import com.yubico.webauthn.data.ByteArray;
+
import net.shibboleth.idp.authn.AuthnEventIds;
import net.shibboleth.idp.plugin.authn.webauthn.context.WebAuthnManagementContext;
import net.shibboleth.idp.plugin.authn.webauthn.impl.AbstractWebAuthnAction;
import net.shibboleth.idp.plugin.authn.webauthn.storage.CredentialRegistration;
+import net.shibboleth.idp.plugin.authn.webauthn.storage.EnhancedCredentialRegistration;
+import net.shibboleth.idp.plugin.authn.webauthn.storage.EnhancedCredentialRegistration.IBuildStage;
import net.shibboleth.idp.plugin.authn.webauthn.storage.WebAuthnCredentialRepository;
import net.shibboleth.shared.annotation.constraint.NonnullAfterInit;
import net.shibboleth.shared.collection.CollectionSupport;
@@ -79,7 +85,19 @@ public class LookupCredentialsForUser extends AbstractWebAuthnAction<WebAuthnMan
final Collection<CredentialRegistration> credentials =
repository.getRegistrationsByUsername(userToSearchFor);
log.debug("{} Found '{}' credentials", getLogPrefix(), credentials.size());
- context.setFoundCredentials(credentials);
+
+ final Collection<EnhancedCredentialRegistration> enhancedCredentialRegistrations =
+ new HashSet<>(credentials.size());
+
+ credentials.stream().filter(Objects::nonNull).forEach(cred -> {
+ final IBuildStage builder = EnhancedCredentialRegistration.builder().withCredentialRegistration(cred);
+ if (cred.getAaguid() != null) {
+ builder.withAuthenticatorMetadata(getAuthenticatorMetadata(new ByteArray(cred.getAaguid())));
+ }
+ enhancedCredentialRegistrations.add(builder.build());
+ });
+
+ context.setFoundCredentials(enhancedCredentialRegistrations);
}
}
diff --git a/webauthn-impl/src/main/java/net/shibboleth/idp/plugin/authn/webauthn/admin/impl/StorePublicKeyCredential.java b/webauthn-impl/src/main/java/net/shibboleth/idp/plugin/authn/webauthn/admin/impl/StorePublicKeyCredential.java
index cfcfbb6..aae9ed7 100644
--- a/webauthn-impl/src/main/java/net/shibboleth/idp/plugin/authn/webauthn/admin/impl/StorePublicKeyCredential.java
+++ b/webauthn-impl/src/main/java/net/shibboleth/idp/plugin/authn/webauthn/admin/impl/StorePublicKeyCredential.java
@@ -16,7 +16,6 @@ package net.shibboleth.idp.plugin.authn.webauthn.admin.impl;
import java.time.Instant;
import java.util.Optional;
-import java.util.Set;
import java.util.TreeSet;
import javax.annotation.Nonnull;
@@ -26,9 +25,6 @@ import org.opensaml.profile.action.ActionSupport;
import org.opensaml.profile.context.ProfileRequestContext;
import org.slf4j.Logger;
-import com.yubico.fido.metadata.AAGUID;
-import com.yubico.fido.metadata.FidoMetadataService;
-import com.yubico.fido.metadata.MetadataBLOBPayloadEntry;
import com.yubico.webauthn.RegisteredCredential;
import com.yubico.webauthn.data.ByteArray;
import com.yubico.webauthn.data.UserIdentity;
@@ -40,11 +36,8 @@ import net.shibboleth.idp.plugin.authn.webauthn.context.WebAuthnRegistrationCont
import net.shibboleth.idp.plugin.authn.webauthn.storage.CredentialRegistration;
import net.shibboleth.idp.plugin.authn.webauthn.storage.WebAuthnCredentialRepository;
import net.shibboleth.shared.annotation.constraint.NonnullAfterInit;
-import net.shibboleth.shared.annotation.constraint.NonnullElements;
-import net.shibboleth.shared.annotation.constraint.NotLive;
import net.shibboleth.shared.codec.Base64Support;
import net.shibboleth.shared.codec.EncodingException;
-import net.shibboleth.shared.collection.CollectionSupport;
import net.shibboleth.shared.component.ComponentInitializationException;
import net.shibboleth.shared.primitive.LoggerFactory;
@@ -138,7 +131,6 @@ public class StorePublicKeyCredential extends AbstractWebAuthnAuditingAction<Web
.withRegistrationTime(now)
.withCredential(credential)
.withAaguid(aaguid != null ? aaguid.getBytes() : null)
- .withAttestationMetadata(getAttestationMetadata(registrationResult.getAaguid()))
.withCredentialNickname(context.getCredentialNickname())
.withDiscoverable(isDiscoverable)
.withUserVerified(registrationResult.isUserVerified())
@@ -177,25 +169,5 @@ public class StorePublicKeyCredential extends AbstractWebAuthnAuditingAction<Web
// Checkstyle: MethodLength ON
- /**
- * Find attestation metadata for the authenticator.
- *
- * @param authenticatorId the authenticator attestation GUID
- *
- * @return the attestation metadata relating to the authenticator attestation GUID
- */
- @Nonnull @NotLive @NonnullElements private Set<MetadataBLOBPayloadEntry> getAttestationMetadata(
- final ByteArray authenticatorId) {
- final FidoMetadataService localMetadataService = getFidoMetadataService();
- if (localMetadataService != null) {
- final Set<MetadataBLOBPayloadEntry> found =
- localMetadataService.findEntries(new AAGUID(authenticatorId));
- if (found == null) {
- return CollectionSupport.emptySet();
- }
- return CollectionSupport.copyToSet(found);
- }
- return CollectionSupport.emptySet();
- }
}
diff --git a/webauthn-impl/src/main/java/net/shibboleth/idp/plugin/authn/webauthn/impl/AbstractWebAuthnAction.java b/webauthn-impl/src/main/java/net/shibboleth/idp/plugin/authn/webauthn/impl/AbstractWebAuthnAction.java
index 24034fb..190db93 100644
--- a/webauthn-impl/src/main/java/net/shibboleth/idp/plugin/authn/webauthn/impl/AbstractWebAuthnAction.java
+++ b/webauthn-impl/src/main/java/net/shibboleth/idp/plugin/authn/webauthn/impl/AbstractWebAuthnAction.java
@@ -14,6 +14,7 @@
package net.shibboleth.idp.plugin.authn.webauthn.impl;
+import java.util.Set;
import java.util.function.Function;
import javax.annotation.Nonnull;
@@ -24,7 +25,10 @@ import org.opensaml.profile.action.EventIds;
import org.opensaml.profile.context.ProfileRequestContext;
import org.slf4j.Logger;
+import com.yubico.fido.metadata.AAGUID;
import com.yubico.fido.metadata.FidoMetadataService;
+import com.yubico.fido.metadata.MetadataBLOBPayloadEntry;
+import com.yubico.webauthn.data.ByteArray;
import net.shibboleth.idp.authn.AuthnEventIds;
import net.shibboleth.idp.plugin.authn.webauthn.client.WebAuthnAuthenticationClient;
@@ -32,7 +36,10 @@ import net.shibboleth.idp.plugin.authn.webauthn.storage.WebAuthnCredentialReposi
import net.shibboleth.idp.profile.AbstractProfileAction;
import net.shibboleth.shared.annotation.constraint.NonnullAfterInit;
import net.shibboleth.shared.annotation.constraint.NonnullBeforeExec;
+import net.shibboleth.shared.annotation.constraint.NonnullElements;
import net.shibboleth.shared.annotation.constraint.NotEmpty;
+import net.shibboleth.shared.annotation.constraint.NotLive;
+import net.shibboleth.shared.collection.CollectionSupport;
import net.shibboleth.shared.component.ComponentInitializationException;
import net.shibboleth.shared.logic.Constraint;
import net.shibboleth.shared.primitive.LoggerFactory;
@@ -221,5 +228,28 @@ public class AbstractWebAuthnAction<T> extends AbstractProfileAction {
// Default does nothing
}
+
+
+ /**
+ * Find metadata for the authenticator.
+ *
+ * @param authenticatorId the authenticator attestation GUID
+ *
+ * @return the attestation metadata relating to the authenticator attestation GUID
+ */
+ @Nonnull @NotLive @NonnullElements protected Set<MetadataBLOBPayloadEntry> getAuthenticatorMetadata(
+ final ByteArray authenticatorId) {
+ final FidoMetadataService localMetadataService = getFidoMetadataService();
+ if (localMetadataService != null) {
+ final Set<MetadataBLOBPayloadEntry> found =
+ localMetadataService.findEntries(new AAGUID(authenticatorId));
+ if (found == null) {
+ return CollectionSupport.emptySet();
+ }
+ return CollectionSupport.copyToSet(found);
+ }
+ return CollectionSupport.emptySet();
+ }
+
}
diff --git a/webauthn-impl/src/main/java/net/shibboleth/idp/plugin/authn/webauthn/impl/CreatePublicKeyCredentialRequestOptions.java b/webauthn-impl/src/main/java/net/shibboleth/idp/plugin/authn/webauthn/impl/CreatePublicKeyCredentialRequestOptions.java
index 4b9838f..14683cd 100644
--- a/webauthn-impl/src/main/java/net/shibboleth/idp/plugin/authn/webauthn/impl/CreatePublicKeyCredentialRequestOptions.java
+++ b/webauthn-impl/src/main/java/net/shibboleth/idp/plugin/authn/webauthn/impl/CreatePublicKeyCredentialRequestOptions.java
@@ -37,7 +37,7 @@ import net.shibboleth.idp.plugin.authn.webauthn.authn.CredentialRequestOptionsPa
import net.shibboleth.idp.plugin.authn.webauthn.client.WebAuthnAuthenticationClient;
import net.shibboleth.idp.plugin.authn.webauthn.context.WebAuthnAuthenticationContext;
import net.shibboleth.idp.plugin.authn.webauthn.exception.WebAuthnAuthenticationClientException;
-import net.shibboleth.idp.plugin.authn.webauthn.storage.CredentialRegistration;
+import net.shibboleth.idp.plugin.authn.webauthn.storage.EnhancedCredentialRegistration;
import net.shibboleth.shared.collection.CollectionSupport;
import net.shibboleth.shared.primitive.LoggerFactory;
@@ -79,8 +79,9 @@ public class CreatePublicKeyCredentialRequestOptions extends AbstractWebAuthnAct
}
try {
- final Collection<CredentialRegistration> existingCredentials = context.getExistingCredentials();
+ final Collection<EnhancedCredentialRegistration> existingCredentials = context.getExistingCredentials();
final List<PublicKeyCredentialDescriptor> existingCredentialDescriptors = existingCredentials.stream()
+ .map(cred -> cred.getCredentialRegistration())
.map(cred -> cred.toPublicKeyCredentialDescriptor())
.filter(Objects::nonNull)
.collect(CollectionSupport.nonnullCollector(Collectors.toUnmodifiableList())).get();
diff --git a/webauthn-impl/src/main/java/net/shibboleth/idp/plugin/authn/webauthn/impl/LookupRegisteredCredentials.java b/webauthn-impl/src/main/java/net/shibboleth/idp/plugin/authn/webauthn/impl/LookupRegisteredCredentials.java
index e48032f..38ca464 100644
--- a/webauthn-impl/src/main/java/net/shibboleth/idp/plugin/authn/webauthn/impl/LookupRegisteredCredentials.java
+++ b/webauthn-impl/src/main/java/net/shibboleth/idp/plugin/authn/webauthn/impl/LookupRegisteredCredentials.java
@@ -15,6 +15,8 @@
package net.shibboleth.idp.plugin.authn.webauthn.impl;
import java.util.Collection;
+import java.util.HashSet;
+import java.util.Objects;
import java.util.Optional;
import java.util.function.Predicate;
@@ -33,6 +35,8 @@ import net.shibboleth.idp.authn.context.AuthenticationContext;
import net.shibboleth.idp.plugin.authn.webauthn.authn.WebAuthnAuthenticationEventIds;
import net.shibboleth.idp.plugin.authn.webauthn.context.BaseWebAuthnContext;
import net.shibboleth.idp.plugin.authn.webauthn.storage.CredentialRegistration;
+import net.shibboleth.idp.plugin.authn.webauthn.storage.EnhancedCredentialRegistration;
+import net.shibboleth.idp.plugin.authn.webauthn.storage.EnhancedCredentialRegistration.IBuildStage;
import net.shibboleth.idp.plugin.authn.webauthn.storage.WebAuthnCredentialRepository;
import net.shibboleth.shared.annotation.constraint.NonnullAfterInit;
import net.shibboleth.shared.annotation.constraint.NotEmpty;
@@ -134,7 +138,18 @@ public class LookupRegisteredCredentials extends AbstractWebAuthnAction<BaseWebA
repository.getRegistrationsByUsername(username);
log.debug("{} Found '{}' registered credentials for '{}'", getLogPrefix(), credentials.size(), username);
- context.setExistingCredentials(credentials);
+
+ final Collection<EnhancedCredentialRegistration> enhancedCredentialRegistrations =
+ new HashSet<>(credentials.size());
+
+ credentials.stream().filter(Objects::nonNull).forEach(cred -> {
+ final IBuildStage builder = EnhancedCredentialRegistration.builder().withCredentialRegistration(cred);
+ if (cred.getAaguid() != null) {
+ builder.withAuthenticatorMetadata(getAuthenticatorMetadata(new ByteArray(cred.getAaguid())));
+ }
+ enhancedCredentialRegistrations.add(builder.build());
+ });
+ context.setExistingCredentials(enhancedCredentialRegistrations);
final Optional<ByteArray> userHandle = repository.getUserHandleForUsername(username);
if (userHandle.isPresent()) {
@@ -150,4 +165,5 @@ public class LookupRegisteredCredentials extends AbstractWebAuthnAction<BaseWebA
}
}
+
}
diff --git a/webauthn-impl/src/main/java/net/shibboleth/idp/plugin/authn/webauthn/impl/WebAuthnEncoder.java b/webauthn-impl/src/main/java/net/shibboleth/idp/plugin/authn/webauthn/impl/WebAuthnEncoder.java
index f8dcf46..3b89e7e 100644
--- a/webauthn-impl/src/main/java/net/shibboleth/idp/plugin/authn/webauthn/impl/WebAuthnEncoder.java
+++ b/webauthn-impl/src/main/java/net/shibboleth/idp/plugin/authn/webauthn/impl/WebAuthnEncoder.java
@@ -32,6 +32,7 @@ import com.yubico.webauthn.data.AuthenticatorTransport;
import com.yubico.webauthn.data.PublicKeyCredentialCreationOptions;
import com.yubico.webauthn.data.PublicKeyCredentialRequestOptions;
+import net.shibboleth.idp.plugin.authn.webauthn.storage.EnhancedCredentialRegistration;
import net.shibboleth.shared.annotation.constraint.NotEmpty;
import net.shibboleth.shared.primitive.LoggerFactory;
@@ -129,6 +130,19 @@ public final class WebAuthnEncoder {
return formatted;
}
+ /**
+ * Does the credential have attached metadata.
+ *
+ * @param cred the credential to check
+ * @return true if the credential has metadata, false otherwise.
+ */
+ public static boolean isAuthenticatorMetadataAttached(final EnhancedCredentialRegistration cred) {
+ if (cred == null) {
+ return false;
+ }
+ return !cred.getAuthenticatorMetadata().isEmpty();
+ }
+
/**
* Convert a set of {@link AuthenticatorTransport transports} into a CSV string.
*
@@ -136,7 +150,7 @@ public final class WebAuthnEncoder {
*
* @return the CSV string
*/
- public static String formatTransports(@Nullable final Set<AuthenticatorTransport> transports) {
+ @Nonnull public static String formatTransports(@Nullable final Set<AuthenticatorTransport> transports) {
if (transports == null) {
return "";
}
diff --git a/webauthn-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/admin/webauthn-management/webauthn-management-beans.xml b/webauthn-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/admin/webauthn-management/webauthn-management-beans.xml
index 11ffcf8..2da5559 100644
--- a/webauthn-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/admin/webauthn-management/webauthn-management-beans.xml
+++ b/webauthn-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/admin/webauthn-management/webauthn-management-beans.xml
@@ -74,7 +74,7 @@
p:webAuthnContextLookupStrategy-ref="shibboleth.ChildLookup.WebAuthnManagementContext" />
<bean id="ExtractKeyRemovalInformationFromFormRequest" scope="prototype"
- class="net.shibboleth.idp.plugin.authn.webauthn.admin.impl.ExtractKeyRemovalInformationFromFormRequest"
+ class="net.shibboleth.idp.plugin.authn.webauthn.admin.impl.ExtractKeyInformationFromFormRequest"
p:httpServletRequestSupplier-ref="shibboleth.HttpServletRequestSupplier">
<property name="contextSettingConsumer">
<bean class="net.shibboleth.idp.plugin.authn.webauthn.admin.impl.ManagementContextCredentialRemovalConsumer"/>
diff --git a/webauthn-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/admin/webauthn-management/webauthn-management-flow.xml b/webauthn-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/admin/webauthn-management/webauthn-management-flow.xml
index 4e3b336..98192cc 100644
--- a/webauthn-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/admin/webauthn-management/webauthn-management-flow.xml
+++ b/webauthn-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/admin/webauthn-management/webauthn-management-flow.xml
@@ -59,13 +59,19 @@
<!-- Call the c14n subflow here so we can c14n the search username to lookup the correct credentials -->
<subflow-state id="CallSubjectCanonicalization" subflow="c14n">
<input name="calledAsSubflow" value="true" />
- <transition on="proceed" to="LookupCredentials" />
+ <transition on="proceed" to="UpdateSearchName" />
- <transition on="SubjectCanonicalizationError" to="ReselectFlow" />
+ <transition on="SubjectCanonicalizationError" to="InvalidSubjectCanonicalizationContext" />
</subflow-state>
- <action-state id="LookupCredentials">
- <evaluate expression="UpdateAdminSearchUsernameWithC14nPrincipal"/>
+ <action-state id="UpdateSearchName">
+ <evaluate expression="UpdateAdminSearchUsernameWithC14nPrincipal"/>
+
+ <evaluate expression="'proceed'" />
+ <transition on="proceed" to="LookupCredentials" />
+ </action-state>
+
+ <action-state id="LookupCredentials">
<evaluate expression="LookupCredentialsForUser"/>
<evaluate expression="'proceed'" />
diff --git a/webauthn-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/admin/webauthn-registration/webauthn-registration-beans.xml b/webauthn-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/admin/webauthn-registration/webauthn-registration-beans.xml
index 0793883..7904d4a 100644
--- a/webauthn-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/admin/webauthn-registration/webauthn-registration-beans.xml
+++ b/webauthn-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/admin/webauthn-registration/webauthn-registration-beans.xml
@@ -58,7 +58,7 @@
<bean id="InitializeSubjectCanonicalizationContext" parent="AbstractWebAuthnBaseAction"
class="net.shibboleth.idp.plugin.authn.webauthn.impl.InitializeSubjectCanonicalizationContext" scope="prototype"
- p:webAuthnContextLookupStrategy-ref="shibboleth.ChildLookup.WebAuthnRegistrationContext"/>
+ p:webAuthnContextLookupStrategy-ref="shibboleth.ChildLookup.WebAuthnRegistrationContext"/>
<bean id="PopulateSubjectCanonicalizationContext"
class="net.shibboleth.idp.authn.impl.PopulateSubjectCanonicalizationContext" scope="prototype"
@@ -144,7 +144,7 @@
p:httpServletRequestSupplier-ref="shibboleth.HttpServletRequestSupplier" />
<bean id="ExtractKeyRemovalInformationFromFormRequest" scope="prototype"
- class="net.shibboleth.idp.plugin.authn.webauthn.admin.impl.ExtractKeyRemovalInformationFromFormRequest"
+ class="net.shibboleth.idp.plugin.authn.webauthn.admin.impl.ExtractKeyInformationFromFormRequest"
p:httpServletRequestSupplier-ref="shibboleth.HttpServletRequestSupplier">
<property name="contextSettingConsumer">
<bean class="net.shibboleth.idp.plugin.authn.webauthn.admin.impl.RegistrationContextCredentialRemovalConsumer"/>
diff --git a/webauthn-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/admin/webauthn-registration/webauthn-registration-flow.xml b/webauthn-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/admin/webauthn-registration/webauthn-registration-flow.xml
index 25e1f80..3e7e9ac 100644
--- a/webauthn-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/admin/webauthn-registration/webauthn-registration-flow.xml
+++ b/webauthn-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/admin/webauthn-registration/webauthn-registration-flow.xml
@@ -65,7 +65,7 @@
<input name="calledAsSubflow" value="true" />
<transition on="proceed" to="LookupRegisteredCredentials" />
- <transition on="SubjectCanonicalizationError" to="ReselectFlow" />
+ <transition on="SubjectCanonicalizationError" to="InvalidSubjectCanonicalizationContext" />
</subflow-state>
<!-- After we canonicalize the username input, use that to lookup registered credentials -->
diff --git a/webauthn-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/authn/WebAuthn/webauthn-abstract-beans.xml b/webauthn-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/authn/WebAuthn/webauthn-abstract-beans.xml
index f68b950..3f5b8a2 100644
--- a/webauthn-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/authn/WebAuthn/webauthn-abstract-beans.xml
+++ b/webauthn-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/authn/WebAuthn/webauthn-abstract-beans.xml
@@ -30,7 +30,8 @@
<bean id="AbstractWebAuthnBaseAction" scope="prototype" abstract="true"
p:webAuthnClient="#{getObject('shibboleth.authn.webauthn.DefaultWebAuthnAuthenticationClientFactory')}"
- p:credentialRepository="#{getObject('shibboleth.authn.webauthn.DefaultCredentialRepository')}"/>
+ p:credentialRepository="#{getObject('shibboleth.authn.webauthn.DefaultCredentialRepository')}"
+ p:fidoMetadataService="#{'false'.equals('%{idp.authn.webauthn.metadata.enabled:false}') ? null : getObject('shibboleth.authn.webauthn.DefaultWebAuthnFidoMetadataServiceFactory')}"/>
<!-- Used in views to calculate CSP hashes and nonces, remove and adjust beans in flow when compatibility bumped past 5.0 -->
diff --git a/webauthn-impl/src/main/resources/net/shibboleth/idp/plugin/authn/webauthn/messages.properties b/webauthn-impl/src/main/resources/net/shibboleth/idp/plugin/authn/webauthn/messages.properties
index 48ff132..9f07636 100644
--- a/webauthn-impl/src/main/resources/net/shibboleth/idp/plugin/authn/webauthn/messages.properties
+++ b/webauthn-impl/src/main/resources/net/shibboleth/idp/plugin/authn/webauthn/messages.properties
@@ -48,6 +48,8 @@ idp.webauthn.admin.table.header.registrationTime = Registration Time
idp.webauthn.admin.table.header.action = Action
idp.webauthn.admin.noKeys = There are no registered keys
idp.webauthn.admin.unsupported = Your browser is not WebAuthn compatible
+idp.webauthn.admin.table.hasMetadata = Yes
+idp.webauthn.admin.table.noMetadata = No
idp.webauthn.ended = Your session has ended
diff --git a/webauthn-impl/src/main/resources/net/shibboleth/idp/plugin/authn/webauthn/views/webauthn-management.vm b/webauthn-impl/src/main/resources/net/shibboleth/idp/plugin/authn/webauthn/views/webauthn-management.vm
index f6ef14a..3085202 100644
--- a/webauthn-impl/src/main/resources/net/shibboleth/idp/plugin/authn/webauthn/views/webauthn-management.vm
+++ b/webauthn-impl/src/main/resources/net/shibboleth/idp/plugin/authn/webauthn/views/webauthn-management.vm
@@ -58,18 +58,17 @@ $response.addHeader("Content-Security-Policy", "default-src 'none'; style-src 's
#if ($webAuthnManContext.foundCredentials)
<table>
<tr>
- <th>#springMessageText("idp.webauthn.admin.table.header.userName", "User")</th>
<th>#springMessageText("idp.webauthn.admin.table.header.keyName", "Key Name")</th>
<th>#springMessageText("idp.webauthn.admin.table.header.authenticatorDescription", "Authenticator")</th>
<th>#springMessageText("idp.webauthn.admin.table.header.transports", "Transports")</th>
<th>#springMessageText("idp.webauthn.admin.table.header.passkey", "Passkey?")</th>
<th>#springMessageText("idp.webauthn.admin.table.header.registrationTime", "Registration Time")</th>
+ <th>#springMessageText("idp.webauthn.admin.table.header.hasMetadata", "Metadata?")</th>
<th>#springMessageText("idp.webauthn.admin.table.header.action", "Action")</th>
</tr>
#foreach($cred in $webAuthnManContext.foundCredentials)
<tr>
- <td>$encoder.encodeForHTML($cred.username)</td>
- <td>$encoder.encodeForHTML($cred.nickname)</td>
+ <td>$encoder.encodeForHTML($cred.credentialRegistration.nickname)</td>
#if ($cred.authenticatorDescription)
<td>
#if ($cred.icon)
@@ -79,16 +78,23 @@ $response.addHeader("Content-Security-Policy", "default-src 'none'; style-src 's
#else
<td>#springMessageText("idp.webauthn.admin.table.unknownCredential", "unknown")</td>
#end
- <td>$encoder.encodeForHTML($webAuthnEncoder.formatTransports($cred.transports))</td>
- <td>$encoder.encodeForHTML($webAuthnEncoder.formatDiscoverable($cred.isDiscoverable()))</td>
- <td>$encoder.encodeForHTML($webAuthnEncoder.formatInstant($cred.registrationTime))</td>
+ <td>$encoder.encodeForHTML($webAuthnEncoder.formatTransports($cred.credentialRegistration.transports))</td>
+ <td>$encoder.encodeForHTML($webAuthnEncoder.formatDiscoverable($cred.credentialRegistration.isDiscoverable()))</td>
+ <td>$encoder.encodeForHTML($webAuthnEncoder.formatInstant($cred.credentialRegistration.registrationTime))</td>
+ <td>
+ #if ($webAuthnEncoder.isAuthenticatorMetadataAttached($cred))
+ #springMessageText("idp.webauthn.admin.table.hasMetadata", "Yes")
+ #else
+ #springMessageText("idp.webauthn.admin.table.noMetadata", "No")
+ #end
+ </td>
<td>
<form id="delete_key_form" action="$flowExecutionUrl" method="post">
#parse("csrf/csrf.vm")
- <input type="hidden" name="credentialId" value="$cred.credentialIdBase64Url"/>
+ <input type="hidden" name="credentialId" value="$cred.credentialRegistration.credentialIdBase64Url"/>
<button class="webauthn-table-button" onclick="$areYouSure" id="removeButton" type="submit" name="_eventId_deleteKey">
#springMessageText("idp.webauthn.admin.credential.remove", "Remove")</button>
- </form>
+ </form>
</td>
</tr>
#end
diff --git a/webauthn-impl/src/main/resources/net/shibboleth/idp/plugin/authn/webauthn/views/webauthn-register.vm b/webauthn-impl/src/main/resources/net/shibboleth/idp/plugin/authn/webauthn/views/webauthn-register.vm
index ef1136d..cf65399 100644
--- a/webauthn-impl/src/main/resources/net/shibboleth/idp/plugin/authn/webauthn/views/webauthn-register.vm
+++ b/webauthn-impl/src/main/resources/net/shibboleth/idp/plugin/authn/webauthn/views/webauthn-register.vm
@@ -134,7 +134,7 @@ $response.addHeader("Content-Security-Policy", "default-src 'none'; style-src 's
</tr>
#foreach($cred in $webauthnRegContext.existingCredentials)
<tr>
- <td>$encoder.encodeForHTML($cred.nickname)</td>
+ <td>$encoder.encodeForHTML($cred.credentialRegistration.nickname)</td>
#if ($cred.authenticatorDescription)
<td>
#if ($cred.icon)
@@ -144,13 +144,13 @@ $response.addHeader("Content-Security-Policy", "default-src 'none'; style-src 's
#else
<td>#springMessageText("idp.webauthn.register.table.unknownCredential", "unknown")</td>
#end
- <td>$encoder.encodeForHTML($webAuthnEncoder.formatTransports($cred.transports))</td>
- <td>$encoder.encodeForHTML($webAuthnEncoder.formatDiscoverable($cred.isDiscoverable()))</td>
- <td>$encoder.encodeForHTML($webAuthnEncoder.formatInstant($cred.registrationTime))</td>
+ <td>$encoder.encodeForHTML($webAuthnEncoder.formatTransports($cred.credentialRegistration.transports))</td>
+ <td>$encoder.encodeForHTML($webAuthnEncoder.formatDiscoverable($cred.credentialRegistration.isDiscoverable()))</td>
+ <td>$encoder.encodeForHTML($webAuthnEncoder.formatInstant($cred.credentialRegistration.registrationTime))</td>
<td>
<form id="delete_key_form" action="$flowExecutionUrl" method="post">
#parse("csrf/csrf.vm")
- <input type="hidden" name="credentialId" value="$cred.credentialIdBase64Url"/>
+ <input type="hidden" name="credentialId" value="$cred.credentialRegistration.credentialIdBase64Url"/>
<button class="webauthn-table-button" onclick="$areYouSure" id="removeButton" type="submit" name="_eventId_deleteKey">
#springMessageText("idp.webauthn.register.credential.remove", "Remove")</button>
</form>
diff --git a/webauthn-impl/src/test/java/net/shibboleth/idp/plugin/authn/webauthn/admin/impl/CreatePublicKeyCredentialCreationOptionsTest.java b/webauthn-impl/src/test/java/net/shibboleth/idp/plugin/authn/webauthn/admin/impl/CreatePublicKeyCredentialCreationOptionsTest.java
index 40a3377..bcadebf 100644
--- a/webauthn-impl/src/test/java/net/shibboleth/idp/plugin/authn/webauthn/admin/impl/CreatePublicKeyCredentialCreationOptionsTest.java
+++ b/webauthn-impl/src/test/java/net/shibboleth/idp/plugin/authn/webauthn/admin/impl/CreatePublicKeyCredentialCreationOptionsTest.java
@@ -31,6 +31,7 @@ import com.yubico.webauthn.data.UserVerificationRequirement;
import net.shibboleth.idp.plugin.authn.webauthn.admin.WebAuthnRegistrationEventIds;
import net.shibboleth.idp.plugin.authn.webauthn.context.WebAuthnRegistrationContext;
import net.shibboleth.idp.plugin.authn.webauthn.impl.AbstractWebAuthnTest;
+import net.shibboleth.idp.plugin.authn.webauthn.storage.EnhancedCredentialRegistration;
import net.shibboleth.shared.collection.CollectionSupport;
import net.shibboleth.shared.component.ComponentInitializationException;
@@ -95,7 +96,8 @@ public class CreatePublicKeyCredentialCreationOptionsTest extends AbstractWebAut
context.setServerChallenge(generateRandomBytes(17));
action.initialize();
- context.setExistingCredentials(CollectionSupport.setOf(createCredentialRegistration()));
+ context.setExistingCredentials(CollectionSupport.setOf(EnhancedCredentialRegistration.builder()
+ .withCredentialRegistration(createCredentialRegistration()).build()));
final Event result = action.execute(src);
assertNull(result);
diff --git a/webauthn-impl/src/test/java/net/shibboleth/idp/plugin/authn/webauthn/admin/impl/ExtractKeyRemovalInformationFromFormRequestTest.java b/webauthn-impl/src/test/java/net/shibboleth/idp/plugin/authn/webauthn/admin/impl/ExtractKeyRemovalInformationFromFormRequestTest.java
index ad28e8e..b9e35d0 100644
--- a/webauthn-impl/src/test/java/net/shibboleth/idp/plugin/authn/webauthn/admin/impl/ExtractKeyRemovalInformationFromFormRequestTest.java
+++ b/webauthn-impl/src/test/java/net/shibboleth/idp/plugin/authn/webauthn/admin/impl/ExtractKeyRemovalInformationFromFormRequestTest.java
@@ -30,11 +30,11 @@ import net.shibboleth.shared.codec.Base64Support;
import net.shibboleth.shared.testing.ConstantSupplier;
/**
- * Tests for {@link ExtractKeyRemovalInformationFromFormRequest}
+ * Tests for {@link ExtractKeyInformationFromFormRequest}
*/
public class ExtractKeyRemovalInformationFromFormRequestTest extends AbstractWebAuthnTest {
- private ExtractKeyRemovalInformationFromFormRequest action;
+ private ExtractKeyInformationFromFormRequest action;
private WebAuthnRegistrationContext context;
@@ -48,7 +48,7 @@ public class ExtractKeyRemovalInformationFromFormRequestTest extends AbstractWeb
request = new MockHttpServletRequest();
- action = new ExtractKeyRemovalInformationFromFormRequest();
+ action = new ExtractKeyInformationFromFormRequest();
}
@Test
@@ -59,7 +59,7 @@ public class ExtractKeyRemovalInformationFromFormRequestTest extends AbstractWeb
final byte[] credentialIdBytes = generateRandomBytes(16);
final String credentialIdb64 = Base64Support.encodeURLSafe(credentialIdBytes);
- request.addParameter(ExtractKeyRemovalInformationFromFormRequest.DEFAULT_PARAMETER_NAME,
+ request.addParameter(ExtractKeyInformationFromFormRequest.DEFAULT_PARAMETER_NAME,
new String[]{credentialIdb64});
action.setHttpServletRequestSupplier(new ConstantSupplier<>(request));
action.initialize();
@@ -90,7 +90,7 @@ public class ExtractKeyRemovalInformationFromFormRequestTest extends AbstractWeb
final SimpleContext contextToUpdate = new SimpleContext();
action.setContextSettingConsumer((prc, bytes) -> contextToUpdate.setCredentialIdToRemove(bytes));
- request.addParameter(ExtractKeyRemovalInformationFromFormRequest.DEFAULT_PARAMETER_NAME,
+ request.addParameter(ExtractKeyInformationFromFormRequest.DEFAULT_PARAMETER_NAME,
new String[]{"not-encoded"});
action.setHttpServletRequestSupplier(new ConstantSupplier<>(request));
action.initialize();
diff --git a/webauthn-impl/src/test/java/net/shibboleth/idp/plugin/authn/webauthn/client/impl/YubicoWebauthnAuthenticationClientTest.java b/webauthn-impl/src/test/java/net/shibboleth/idp/plugin/authn/webauthn/client/impl/YubicoWebauthnAuthenticationClientTest.java
index 460214c..698a762 100644
--- a/webauthn-impl/src/test/java/net/shibboleth/idp/plugin/authn/webauthn/client/impl/YubicoWebauthnAuthenticationClientTest.java
+++ b/webauthn-impl/src/test/java/net/shibboleth/idp/plugin/authn/webauthn/client/impl/YubicoWebauthnAuthenticationClientTest.java
@@ -49,7 +49,6 @@ import net.shibboleth.idp.plugin.authn.webauthn.storage.CredentialRegistration;
import net.shibboleth.idp.plugin.authn.webauthn.storage.impl.InMemoryRegistrationStorage;
import net.shibboleth.idp.plugin.authn.webauthn.storage.impl.MockAuthenticator;
import net.shibboleth.shared.codec.Base64Support;
-import net.shibboleth.shared.collection.CollectionSupport;
/**
* Tests for {@link YubicoWebAuthnAuthenticationClient}. To some extent this is testing the Yubico libraries work
@@ -188,7 +187,6 @@ public class YubicoWebauthnAuthenticationClientTest extends AbstractWebAuthnTest
.withTransports(new TreeSet<AuthenticatorTransport>())
.withRegistrationTime(Instant.now())
.withCredential(credential)
- .withAttestationMetadata(CollectionSupport.emptySet())
.withCredentialNickname("Nickname")
.withDiscoverable(Optional.of(Boolean.TRUE))
.withUserVerified(true)
@@ -261,7 +259,6 @@ public class YubicoWebauthnAuthenticationClientTest extends AbstractWebAuthnTest
.withTransports(new TreeSet<AuthenticatorTransport>())
.withRegistrationTime(Instant.now())
.withCredential(credential)
- .withAttestationMetadata(CollectionSupport.emptySet())
.withCredentialNickname("Nickname")
.withDiscoverable(Optional.of(Boolean.TRUE))
.withUserVerified(true)
@@ -306,7 +303,6 @@ public class YubicoWebauthnAuthenticationClientTest extends AbstractWebAuthnTest
.withTransports(new TreeSet<AuthenticatorTransport>())
.withRegistrationTime(Instant.now())
.withCredential(credential)
- .withAttestationMetadata(CollectionSupport.emptySet())
.withCredentialNickname("Nickname")
.withDiscoverable(Optional.of(Boolean.TRUE))
.withUserVerified(true)
@@ -352,7 +348,6 @@ public class YubicoWebauthnAuthenticationClientTest extends AbstractWebAuthnTest
.withTransports(new TreeSet<AuthenticatorTransport>())
.withRegistrationTime(Instant.now())
.withCredential(credential)
- .withAttestationMetadata(CollectionSupport.emptySet())
.withCredentialNickname("Nickname")
.withDiscoverable(Optional.of(Boolean.TRUE))
.withUserVerified(true)
diff --git a/webauthn-impl/src/test/java/net/shibboleth/idp/plugin/authn/webauthn/flow/AbstractWebAuthnFlowTest.java b/webauthn-impl/src/test/java/net/shibboleth/idp/plugin/authn/webauthn/flow/AbstractWebAuthnFlowTest.java
index a2ccfbc..d8c8705 100644
--- a/webauthn-impl/src/test/java/net/shibboleth/idp/plugin/authn/webauthn/flow/AbstractWebAuthnFlowTest.java
+++ b/webauthn-impl/src/test/java/net/shibboleth/idp/plugin/authn/webauthn/flow/AbstractWebAuthnFlowTest.java
@@ -92,7 +92,6 @@ import net.shibboleth.idp.ui.context.RelyingPartyUIContext;
import net.shibboleth.shared.annotation.constraint.NotEmpty;
import net.shibboleth.shared.codec.Base64Support;
import net.shibboleth.shared.codec.EncodingException;
-import net.shibboleth.shared.collection.CollectionSupport;
import net.shibboleth.shared.collection.Pair;
import net.shibboleth.shared.servlet.impl.HttpServletRequestResponseContext;
@@ -243,7 +242,6 @@ public class AbstractWebAuthnFlowTest extends AbstractFlowTest {
.withTransports(new TreeSet<AuthenticatorTransport>())
.withRegistrationTime(Instant.now())
.withCredential(credential)
- .withAttestationMetadata(CollectionSupport.emptySet())
.withCredentialNickname("nickname")
.withDiscoverable(Optional.of(Boolean.TRUE))
.withUserVerified(true)
diff --git a/webauthn-impl/src/test/java/net/shibboleth/idp/plugin/authn/webauthn/flow/TestAdminManagementFlow.java b/webauthn-impl/src/test/java/net/shibboleth/idp/plugin/authn/webauthn/flow/TestAdminManagementFlow.java
index 27890ee..fd84f63 100644
--- a/webauthn-impl/src/test/java/net/shibboleth/idp/plugin/authn/webauthn/flow/TestAdminManagementFlow.java
+++ b/webauthn-impl/src/test/java/net/shibboleth/idp/plugin/authn/webauthn/flow/TestAdminManagementFlow.java
@@ -34,7 +34,7 @@ import com.yubico.webauthn.data.ClientAssertionExtensionOutputs;
import com.yubico.webauthn.data.PublicKeyCredential;
import net.shibboleth.idp.authn.context.SubjectCanonicalizationContext;
-import net.shibboleth.idp.plugin.authn.webauthn.admin.impl.ExtractKeyRemovalInformationFromFormRequest;
+import net.shibboleth.idp.plugin.authn.webauthn.admin.impl.ExtractKeyInformationFromFormRequest;
import net.shibboleth.idp.plugin.authn.webauthn.admin.impl.ExtractUsernameSearchFromFormRequest;
import net.shibboleth.idp.plugin.authn.webauthn.context.WebAuthnAuthenticationContext;
import net.shibboleth.idp.plugin.authn.webauthn.impl.ExtractPublicKeyCredentialAssertionFromFormRequest;
@@ -98,7 +98,7 @@ public class TestAdminManagementFlow extends AbstractWebAuthnFlowTest{
assertCurrentStateEquals("ManagementView", result.getSecond());
// Re-set external context to holder
ExternalContextHolder.setExternalContext(externalContext);
- setHttpFormRequest("POST", Map.of(ExtractKeyRemovalInformationFromFormRequest.DEFAULT_PARAMETER_NAME,
+ setHttpFormRequest("POST", Map.of(ExtractKeyInformationFromFormRequest.DEFAULT_PARAMETER_NAME,
registration.getCredentialIdBase64Url()));
externalContext.setEventId("deleteKey");
// Add c14n context to simulate c14n flows
diff --git a/webauthn-impl/src/test/java/net/shibboleth/idp/plugin/authn/webauthn/flow/TestRegistrationFlow.java b/webauthn-impl/src/test/java/net/shibboleth/idp/plugin/authn/webauthn/flow/TestRegistrationFlow.java
index 9fadeb5..5ac9de8 100644
--- a/webauthn-impl/src/test/java/net/shibboleth/idp/plugin/authn/webauthn/flow/TestRegistrationFlow.java
+++ b/webauthn-impl/src/test/java/net/shibboleth/idp/plugin/authn/webauthn/flow/TestRegistrationFlow.java
@@ -38,7 +38,7 @@ import com.yubico.webauthn.data.PublicKeyCredentialCreationOptions;
import com.yubico.webauthn.data.RegistrationExtensionInputs;
import com.yubico.webauthn.data.UserIdentity;
-import net.shibboleth.idp.plugin.authn.webauthn.admin.impl.ExtractKeyRemovalInformationFromFormRequest;
+import net.shibboleth.idp.plugin.authn.webauthn.admin.impl.ExtractKeyInformationFromFormRequest;
import net.shibboleth.idp.plugin.authn.webauthn.admin.impl.ExtractPublicKeyCredentialAttestationFromFormRequest;
import net.shibboleth.idp.plugin.authn.webauthn.context.WebAuthnAuthenticationContext;
import net.shibboleth.idp.plugin.authn.webauthn.context.WebAuthnRegistrationContext;
@@ -91,7 +91,7 @@ public class TestRegistrationFlow extends AbstractWebAuthnFlowTest{
// Re-set external context to holder
ExternalContextHolder.setExternalContext(externalContext);
- setHttpFormRequest("POST", Map.of(ExtractKeyRemovalInformationFromFormRequest.DEFAULT_PARAMETER_NAME,
+ setHttpFormRequest("POST", Map.of(ExtractKeyInformationFromFormRequest.DEFAULT_PARAMETER_NAME,
registration.getCredentialIdBase64Url()));
externalContext.setEventId("deleteKey");
result.getSecond().setCurrentState("DisplayWebAuthnRegistrationView");
@@ -136,7 +136,7 @@ public class TestRegistrationFlow extends AbstractWebAuthnFlowTest{
// Re-set external context to holder
ExternalContextHolder.setExternalContext(externalContext);
- setHttpFormRequest("POST", Map.of(ExtractKeyRemovalInformationFromFormRequest.DEFAULT_PARAMETER_NAME,
+ setHttpFormRequest("POST", Map.of(ExtractKeyInformationFromFormRequest.DEFAULT_PARAMETER_NAME,
registrationAnotherUser.getCredentialIdBase64Url()));
externalContext.setEventId("deleteKey");
result.getSecond().setCurrentState("DisplayWebAuthnRegistrationView");
diff --git a/webauthn-impl/src/test/java/net/shibboleth/idp/plugin/authn/webauthn/impl/AbstractWebAuthnTest.java b/webauthn-impl/src/test/java/net/shibboleth/idp/plugin/authn/webauthn/impl/AbstractWebAuthnTest.java
index f826daa..62a8e8f 100644
--- a/webauthn-impl/src/test/java/net/shibboleth/idp/plugin/authn/webauthn/impl/AbstractWebAuthnTest.java
+++ b/webauthn-impl/src/test/java/net/shibboleth/idp/plugin/authn/webauthn/impl/AbstractWebAuthnTest.java
@@ -348,7 +348,6 @@ public abstract class AbstractWebAuthnTest {
.withTransports(new TreeSet<AuthenticatorTransport>())
.withRegistrationTime(Instant.now())
.withCredential(credential)
- .withAttestationMetadata(CollectionSupport.emptySet())
.withCredentialNickname("nickname")
.withDiscoverable(Optional.of(Boolean.TRUE))
.withUserVerified(true)
diff --git a/webauthn-impl/src/test/java/net/shibboleth/idp/plugin/authn/webauthn/impl/LookupRegisteredCredentialsFromUserHandleTest.java b/webauthn-impl/src/test/java/net/shibboleth/idp/plugin/authn/webauthn/impl/LookupRegisteredCredentialsFromUserHandleTest.java
index c240d97..fa5a767 100644
--- a/webauthn-impl/src/test/java/net/shibboleth/idp/plugin/authn/webauthn/impl/LookupRegisteredCredentialsFromUserHandleTest.java
+++ b/webauthn-impl/src/test/java/net/shibboleth/idp/plugin/authn/webauthn/impl/LookupRegisteredCredentialsFromUserHandleTest.java
@@ -41,7 +41,6 @@ import net.shibboleth.idp.plugin.authn.webauthn.authn.WebAuthnAuthenticationEven
import net.shibboleth.idp.plugin.authn.webauthn.storage.CredentialRegistration;
import net.shibboleth.idp.plugin.authn.webauthn.storage.impl.MockAuthenticator;
import net.shibboleth.shared.codec.Base64Support;
-import net.shibboleth.shared.collection.CollectionSupport;
/**
* Tests for {@link LookupRegisteredCredentialsFromUserHandle}
@@ -97,7 +96,6 @@ public class LookupRegisteredCredentialsFromUserHandleTest extends AbstractWebAu
.withTransports(new TreeSet<AuthenticatorTransport>())
.withRegistrationTime(Instant.now())
.withCredential(credential)
- .withAttestationMetadata(CollectionSupport.emptySet())
.withCredentialNickname("Nickname")
.withDiscoverable(Optional.of(Boolean.TRUE))
.withUserVerified(true)
@@ -152,7 +150,6 @@ public class LookupRegisteredCredentialsFromUserHandleTest extends AbstractWebAu
.withTransports(new TreeSet<AuthenticatorTransport>())
.withRegistrationTime(Instant.now())
.withCredential(credential)
- .withAttestationMetadata(CollectionSupport.emptySet())
.withCredentialNickname("Nickname")
.withDiscoverable(Optional.of(Boolean.TRUE))
.withUserVerified(true)
diff --git a/webauthn-impl/src/test/java/net/shibboleth/idp/plugin/authn/webauthn/impl/LookupRegisteredCredentialsTest.java b/webauthn-impl/src/test/java/net/shibboleth/idp/plugin/authn/webauthn/impl/LookupRegisteredCredentialsTest.java
index 4ed0f21..be0c33b 100644
--- a/webauthn-impl/src/test/java/net/shibboleth/idp/plugin/authn/webauthn/impl/LookupRegisteredCredentialsTest.java
+++ b/webauthn-impl/src/test/java/net/shibboleth/idp/plugin/authn/webauthn/impl/LookupRegisteredCredentialsTest.java
@@ -41,7 +41,6 @@ import net.shibboleth.idp.plugin.authn.webauthn.context.BaseWebAuthnContext;
import net.shibboleth.idp.plugin.authn.webauthn.storage.CredentialRegistration;
import net.shibboleth.idp.plugin.authn.webauthn.storage.impl.MockAuthenticator;
import net.shibboleth.shared.codec.Base64Support;
-import net.shibboleth.shared.collection.CollectionSupport;
import net.shibboleth.shared.component.ComponentInitializationException;
/**
@@ -94,7 +93,6 @@ public class LookupRegisteredCredentialsTest extends AbstractWebAuthnTest {
.withTransports(new TreeSet<AuthenticatorTransport>())
.withRegistrationTime(Instant.now())
.withCredential(credential)
- .withAttestationMetadata(CollectionSupport.emptySet())
.withCredentialNickname("nickname")
.withDiscoverable(Optional.of(Boolean.TRUE))
.withUserVerified(true)
diff --git a/webauthn-impl/src/test/java/net/shibboleth/idp/plugin/authn/webauthn/storage/impl/CredentialRegistrationSerializerTest.java b/webauthn-impl/src/test/java/net/shibboleth/idp/plugin/authn/webauthn/storage/impl/CredentialRegistrationSerializerTest.java
index 3536138..0b46f10 100644
--- a/webauthn-impl/src/test/java/net/shibboleth/idp/plugin/authn/webauthn/storage/impl/CredentialRegistrationSerializerTest.java
+++ b/webauthn-impl/src/test/java/net/shibboleth/idp/plugin/authn/webauthn/storage/impl/CredentialRegistrationSerializerTest.java
@@ -82,7 +82,6 @@ public class CredentialRegistrationSerializerTest extends AbstractWebAuthnTest {
.withTransports(new TreeSet<AuthenticatorTransport>())
.withRegistrationTime(Instant.now())
.withCredential(credential)
- .withAttestationMetadata(CollectionSupport.emptySet())
.withCredentialNickname("nickname")
.withDiscoverable(Optional.of(Boolean.TRUE))
.withUserVerified(true)
diff --git a/webauthn-impl/src/test/java/net/shibboleth/idp/plugin/authn/webauthn/storage/impl/IdPStorageServiceCredentialRespositoryTest.java b/webauthn-impl/src/test/java/net/shibboleth/idp/plugin/authn/webauthn/storage/impl/IdPStorageServiceCredentialRespositoryTest.java
index b185b5c..fa82eba 100644
--- a/webauthn-impl/src/test/java/net/shibboleth/idp/plugin/authn/webauthn/storage/impl/IdPStorageServiceCredentialRespositoryTest.java
+++ b/webauthn-impl/src/test/java/net/shibboleth/idp/plugin/authn/webauthn/storage/impl/IdPStorageServiceCredentialRespositoryTest.java
@@ -44,7 +44,6 @@ import com.yubico.webauthn.data.UserIdentity;
import net.shibboleth.idp.plugin.authn.webauthn.impl.AbstractWebAuthnTest;
import net.shibboleth.idp.plugin.authn.webauthn.storage.CredentialRegistration;
-import net.shibboleth.shared.collection.CollectionSupport;
/**
* Tests for {@link IdPStorageServiceCredentialRespository}.
@@ -103,7 +102,6 @@ public class IdPStorageServiceCredentialRespositoryTest extends AbstractWebAuthn
.withTransports(new TreeSet<AuthenticatorTransport>())
.withRegistrationTime(Instant.now())
.withCredential(credential)
- .withAttestationMetadata(CollectionSupport.emptySet())
.withCredentialNickname("nickname")
.withDiscoverable(Optional.of(Boolean.TRUE))
.withUserVerified(true)
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list