diff --git a/NEWS b/NEWS index d2384d656..83ccbaa98 100644 --- a/NEWS +++ b/NEWS @@ -1,9 +1,17 @@ == Version 2.1.0 (unreleased) == +Deprecations: + +* Deprecated method `AssertionResult.getCredentialId(): ByteArray`. Use + `.getCredential().getCredentialId()` instead. +* Deprecated method `AssertionResult.getUserHandle(): ByteArray`. Use + `.getCredential().getUserHandle()` instead. + New features: * Added method `FidoMetadataDownloader.refreshBlob()`. * Added function `COSEAlgorithmIdentifier.fromPublicKey(ByteArray)`. +* Added method `AssertionResult.getCredential(): RegisteredCredential`. == Version 2.0.0 == diff --git a/webauthn-server-core/src/main/java/com/yubico/webauthn/AssertionResult.java b/webauthn-server-core/src/main/java/com/yubico/webauthn/AssertionResult.java index 2b8c3c0f1..1fb1d9909 100644 --- a/webauthn-server-core/src/main/java/com/yubico/webauthn/AssertionResult.java +++ b/webauthn-server-core/src/main/java/com/yubico/webauthn/AssertionResult.java @@ -26,6 +26,7 @@ import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; +import com.yubico.internal.util.ExceptionUtil; import com.yubico.webauthn.data.AuthenticatorAssertionExtensionOutputs; import com.yubico.webauthn.data.AuthenticatorData; import com.yubico.webauthn.data.ByteArray; @@ -46,24 +47,16 @@ public class AssertionResult { private final boolean success; /** - * The credential - * ID of the credential used for the assertion. - * - * @see Credential - * ID - * @see PublicKeyCredentialRequestOptions#getAllowCredentials() - */ - @NonNull private final ByteArray credentialId; - - /** - * The user handle - * of the authenticated user. + * The {@link RegisteredCredential} that was returned by {@link + * CredentialRepository#lookup(ByteArray, ByteArray)} and whose public key was used to + * successfully verify the assertion signature. * - * @see User Handle - * @see UserIdentity#getId() - * @see #getUsername() + *
NOTE: The {@link RegisteredCredential#getSignatureCount() signature count} in this object
+ * will reflect the signature counter state before the assertion operation, not the new
+ * counter value. When updating your database state, use the signature counter from {@link
+ * #getSignatureCount()} instead.
*/
- @NonNull private final ByteArray userHandle;
+ private final RegisteredCredential credential;
/**
* The username of the authenticated user.
@@ -107,12 +100,33 @@ public class AssertionResult {
private final AuthenticatorAssertionExtensionOutputs authenticatorExtensionOutputs;
+ private AssertionResult(
+ boolean success,
+ @NonNull @JsonProperty("credential") RegisteredCredential credential,
+ @NonNull String username,
+ long signatureCount,
+ boolean signatureCounterValid,
+ ClientAssertionExtensionOutputs clientExtensionOutputs,
+ AuthenticatorAssertionExtensionOutputs authenticatorExtensionOutputs) {
+ this(
+ success,
+ credential,
+ username,
+ null,
+ null,
+ signatureCount,
+ signatureCounterValid,
+ clientExtensionOutputs,
+ authenticatorExtensionOutputs);
+ }
+
@JsonCreator
private AssertionResult(
@JsonProperty("success") boolean success,
- @NonNull @JsonProperty("credentialId") ByteArray credentialId,
- @NonNull @JsonProperty("userHandle") ByteArray userHandle,
+ @NonNull @JsonProperty("credential") RegisteredCredential credential,
@NonNull @JsonProperty("username") String username,
+ @JsonProperty("credentialId") ByteArray credentialId, // TODO: Delete in next major release
+ @JsonProperty("userHandle") ByteArray userHandle, // TODO: Delete in next major release
@JsonProperty("signatureCount") long signatureCount,
@JsonProperty("signatureCounterValid") boolean signatureCounterValid,
@JsonProperty("clientExtensionOutputs")
@@ -120,9 +134,20 @@ private AssertionResult(
@JsonProperty("authenticatorExtensionOutputs")
AuthenticatorAssertionExtensionOutputs authenticatorExtensionOutputs) {
this.success = success;
- this.credentialId = credentialId;
- this.userHandle = userHandle;
+ this.credential = credential;
this.username = username;
+
+ if (credentialId != null) {
+ ExceptionUtil.assure(
+ credential.getCredentialId().equals(credentialId),
+ "Legacy credentialId is present and does not equal credential.credentialId");
+ }
+ if (userHandle != null) {
+ ExceptionUtil.assure(
+ credential.getUserHandle().equals(userHandle),
+ "Legacy userHandle is present and does not equal credential.userHandle");
+ }
+
this.signatureCount = signatureCount;
this.signatureCounterValid = signatureCounterValid;
this.clientExtensionOutputs =
@@ -132,6 +157,36 @@ private AssertionResult(
this.authenticatorExtensionOutputs = authenticatorExtensionOutputs;
}
+ /**
+ * The credential
+ * ID of the credential used for the assertion.
+ *
+ * @see Credential
+ * ID
+ * @see PublicKeyCredentialRequestOptions#getAllowCredentials()
+ * @deprecated Use {@link #getCredential()}.{@link RegisteredCredential#getCredentialId()
+ * getCredentialId()} instead.
+ */
+ @Deprecated
+ public ByteArray getCredentialId() {
+ return credential.getCredentialId();
+ }
+
+ /**
+ * The user handle
+ * of the authenticated user.
+ *
+ * @see User Handle
+ * @see UserIdentity#getId()
+ * @see #getUsername()
+ * @deprecated Use {@link #getCredential()}.{@link RegisteredCredential#getUserHandle()} ()
+ * getUserHandle()} instead.
+ */
+ @Deprecated
+ public ByteArray getUserHandle() {
+ return credential.getUserHandle();
+ }
+
/**
* The client
@@ -180,49 +235,42 @@ public Step2 success(boolean success) {
}
public class Step2 {
- public Step3 credentialId(ByteArray credentialId) {
- builder.credentialId(credentialId);
+ public Step3 credential(RegisteredCredential credential) {
+ builder.credential(credential);
return new Step3();
}
}
public class Step3 {
- public Step4 userHandle(ByteArray userHandle) {
- builder.userHandle(userHandle);
+ public Step4 username(String username) {
+ builder.username(username);
return new Step4();
}
}
public class Step4 {
- public Step5 username(String username) {
- builder.username(username);
+ public Step5 signatureCount(long signatureCount) {
+ builder.signatureCount(signatureCount);
return new Step5();
}
}
public class Step5 {
- public Step6 signatureCount(long signatureCount) {
- builder.signatureCount(signatureCount);
+ public Step6 signatureCounterValid(boolean signatureCounterValid) {
+ builder.signatureCounterValid(signatureCounterValid);
return new Step6();
}
}
public class Step6 {
- public Step7 signatureCounterValid(boolean signatureCounterValid) {
- builder.signatureCounterValid(signatureCounterValid);
- return new Step7();
- }
- }
-
- public class Step7 {
- public Step8 clientExtensionOutputs(
+ public Step7 clientExtensionOutputs(
ClientAssertionExtensionOutputs clientExtensionOutputs) {
builder.clientExtensionOutputs(clientExtensionOutputs);
- return new Step8();
+ return new Step7();
}
}
- public class Step8 {
+ public class Step7 {
public AssertionResultBuilder assertionExtensionOutputs(
AuthenticatorAssertionExtensionOutputs authenticatorExtensionOutputs) {
return builder.authenticatorExtensionOutputs(authenticatorExtensionOutputs);
diff --git a/webauthn-server-core/src/main/java/com/yubico/webauthn/FinishAssertionSteps.java b/webauthn-server-core/src/main/java/com/yubico/webauthn/FinishAssertionSteps.java
index 543cd2d96..b0194b501 100644
--- a/webauthn-server-core/src/main/java/com/yubico/webauthn/FinishAssertionSteps.java
+++ b/webauthn-server-core/src/main/java/com/yubico/webauthn/FinishAssertionSteps.java
@@ -203,7 +203,7 @@ class Step7 implements Step