Skip to content

Commit

Permalink
Add credProps and authenticatorDisplayName to assertion extension out…
Browse files Browse the repository at this point in the history
…puts
  • Loading branch information
emlun committed Jul 11, 2024
1 parent 02a10f6 commit a1a3e2f
Show file tree
Hide file tree
Showing 8 changed files with 193 additions and 0 deletions.
1 change: 1 addition & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ New features:
* (Experimental) Added property `credProps.authenticatorDisplayName`.
** NOTE: Experimental features may receive breaking changes without a major
version increase.
* (Experimental) Added `credProps` extension to assertion extension outputs.


== Version 2.5.2 ==
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import com.yubico.webauthn.data.AuthenticatorResponse;
import com.yubico.webauthn.data.ByteArray;
import com.yubico.webauthn.data.ClientAssertionExtensionOutputs;
import com.yubico.webauthn.data.Extensions;
import com.yubico.webauthn.data.PublicKeyCredential;
import com.yubico.webauthn.data.PublicKeyCredentialRequestOptions;
import com.yubico.webauthn.data.UserIdentity;
Expand Down Expand Up @@ -281,4 +282,33 @@ public Optional<AuthenticatorAssertionExtensionOutputs> getAuthenticatorExtensio
return AuthenticatorAssertionExtensionOutputs.fromAuthenticatorData(
credentialResponse.getResponse().getParsedAuthenticatorData());
}

/**
* Retrieve a suitable nickname for this credential, if one is available. This MAY differ from
* {@link RegistrationResult#getAuthenticatorDisplayName() the value returned during
* registration}, if any. In that case the application may want to offer the user to update the
* previously stored value, if any.
*
* <p>This returns the <code>authenticatorDisplayName</code> output from the <a
* href="https://w3c.github.io/webauthn/#sctn-authenticator-credential-properties-extension">
* <code>credProps</code></a> extension.
*
* @return A user-chosen or vendor-default display name for the credential, if available.
* Otherwise empty.
* @see <a
* href="https://w3c.github.io/webauthn/#dom-credentialpropertiesoutput-authenticatordisplayname">
* <code>authenticatorDisplayName</code> in §10.1.3. Credential Properties Extension
* (credProps)</a>
* @see RegistrationResult#getAuthenticatorDisplayName()
* @see Extensions.CredentialProperties.CredentialPropertiesOutput#getAuthenticatorDisplayName()
* @deprecated EXPERIMENTAL: This feature is from a not yet mature standard; it could change as
* the standard matures.
*/
@JsonIgnore
@Deprecated
public Optional<String> getAuthenticatorDisplayName() {
return getClientExtensionOutputs()
.flatMap(outputs -> outputs.getCredProps())
.flatMap(credProps -> credProps.getAuthenticatorDisplayName());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import com.yubico.webauthn.data.AuthenticatorResponse;
import com.yubico.webauthn.data.ByteArray;
import com.yubico.webauthn.data.ClientAssertionExtensionOutputs;
import com.yubico.webauthn.data.Extensions;
import com.yubico.webauthn.data.PublicKeyCredential;
import java.util.Optional;
import lombok.AccessLevel;
Expand Down Expand Up @@ -243,4 +244,33 @@ public Optional<AuthenticatorAssertionExtensionOutputs> getAuthenticatorExtensio
return AuthenticatorAssertionExtensionOutputs.fromAuthenticatorData(
credentialResponse.getResponse().getParsedAuthenticatorData());
}

/**
* Retrieve a suitable nickname for this credential, if one is available. This MAY differ from
* {@link RegistrationResult#getAuthenticatorDisplayName() the value returned during
* registration}, if any. In that case the application may want to offer the user to update the
* previously stored value, if any.
*
* <p>This returns the <code>authenticatorDisplayName</code> output from the <a
* href="https://w3c.github.io/webauthn/#sctn-authenticator-credential-properties-extension">
* <code>credProps</code></a> extension.
*
* @return A user-chosen or vendor-default display name for the credential, if available.
* Otherwise empty.
* @see <a
* href="https://w3c.github.io/webauthn/#dom-credentialpropertiesoutput-authenticatordisplayname">
* <code>authenticatorDisplayName</code> in §10.1.3. Credential Properties Extension
* (credProps)</a>
* @see RegistrationResult#getAuthenticatorDisplayName()
* @see Extensions.CredentialProperties.CredentialPropertiesOutput#getAuthenticatorDisplayName()
* @deprecated EXPERIMENTAL: This feature is from a not yet mature standard; it could change as
* the standard matures.
*/
@JsonIgnore
@Deprecated
public Optional<String> getAuthenticatorDisplayName() {
return getClientExtensionOutputs()
.flatMap(outputs -> outputs.getCredProps())
.flatMap(credProps -> credProps.getAuthenticatorDisplayName());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,8 @@ public Optional<Boolean> isDiscoverable() {
* href="https://w3c.github.io/webauthn/#dom-credentialpropertiesoutput-authenticatordisplayname">
* <code>authenticatorDisplayName</code> in §10.1.3. Credential Properties Extension
* (credProps)</a>
* @see AssertionResult#getAuthenticatorDisplayName()
* @see AssertionResultV2#getAuthenticatorDisplayName()
* @see Extensions.CredentialProperties.CredentialPropertiesOutput#getAuthenticatorDisplayName()
* @deprecated EXPERIMENTAL: This feature is from a not yet mature standard; it could change as
* the standard matures.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,13 +64,18 @@ public class ClientAssertionExtensionOutputs implements ClientExtensionOutputs {
*/
private final Boolean appid;

private final Extensions.CredentialProperties.CredentialPropertiesOutput credProps;

private final Extensions.LargeBlob.LargeBlobAuthenticationOutput largeBlob;

@JsonCreator
private ClientAssertionExtensionOutputs(
@JsonProperty("appid") Boolean appid,
@JsonProperty("credProps")
Extensions.CredentialProperties.CredentialPropertiesOutput credProps,
@JsonProperty("largeBlob") Extensions.LargeBlob.LargeBlobAuthenticationOutput largeBlob) {
this.appid = appid;
this.credProps = credProps;
this.largeBlob = largeBlob;
}

Expand All @@ -81,6 +86,9 @@ public Set<String> getExtensionIds() {
if (appid != null) {
ids.add(Extensions.Appid.EXTENSION_ID);
}
if (credProps != null) {
ids.add(Extensions.CredentialProperties.EXTENSION_ID);
}
if (largeBlob != null) {
ids.add(Extensions.LargeBlob.EXTENSION_ID);
}
Expand All @@ -100,6 +108,24 @@ public Optional<Boolean> getAppid() {
return Optional.ofNullable(appid);
}

/**
* The extension output for the Credential Properties Extension (<code>credProps</code>), if any.
*
* <p>This value MAY be present but have all members empty if the extension was successfully
* processed but no credential properties could be determined.
*
* @see com.yubico.webauthn.data.Extensions.CredentialProperties.CredentialPropertiesOutput
* @see <a
* href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#sctn-authenticator-credential-properties-extension">§10.4.
* Credential Properties Extension (credProps)</a>
* @deprecated EXPERIMENTAL: This feature is from a not yet mature standard; it could change as
* the standard matures.
*/
@Deprecated
public Optional<Extensions.CredentialProperties.CredentialPropertiesOutput> getCredProps() {
return Optional.ofNullable(credProps);
}

/**
* The extension output for the <a
* href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#sctn-large-blob-extension">Large blob
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
import com.fasterxml.jackson.annotation.JsonValue;
import com.upokecenter.cbor.CBORObject;
import com.upokecenter.cbor.CBORType;
import com.yubico.webauthn.AssertionResult;
import com.yubico.webauthn.AssertionResultV2;
import com.yubico.webauthn.RegistrationResult;
import com.yubico.webauthn.StartRegistrationOptions;
import com.yubico.webauthn.extension.uvm.KeyProtectionType;
Expand Down Expand Up @@ -131,6 +133,8 @@ public Optional<Boolean> getRk() {
* <code>authenticatorDisplayName</code> in §10.1.3. Credential Properties Extension
* (credProps)</a>
* @see RegistrationResult#getAuthenticatorDisplayName()
* @see AssertionResult#getAuthenticatorDisplayName()
* @see AssertionResultV2#getAuthenticatorDisplayName()
* @deprecated EXPERIMENTAL: This feature is from a not yet mature standard; it could change
* as the standard matures.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import com.yubico.webauthn.data.AuthenticatorTransport
import com.yubico.webauthn.data.ByteArray
import com.yubico.webauthn.data.ClientAssertionExtensionOutputs
import com.yubico.webauthn.data.CollectedClientData
import com.yubico.webauthn.data.Extensions.CredentialProperties.CredentialPropertiesOutput
import com.yubico.webauthn.data.Extensions.LargeBlob.LargeBlobAuthenticationInput
import com.yubico.webauthn.data.Extensions.LargeBlob.LargeBlobAuthenticationOutput
import com.yubico.webauthn.data.Extensions.Uvm.UvmEntry
Expand Down Expand Up @@ -2845,6 +2846,55 @@ class RelyingPartyAssertionSpec
)
}
}

describe("exposes the credProps.authenticatorDisplayName extension output as getAuthenticatorDisplayName()") {
val pkcTemplate =
TestAuthenticator.createAssertion(
challenge =
request.getPublicKeyCredentialRequestOptions.getChallenge,
credentialKey = credentialKeypair,
credentialId = credential.getId,
)

it("""when set to "hej".""") {
val pkc = pkcTemplate.toBuilder
.clientExtensionResults(
pkcTemplate.getClientExtensionResults.toBuilder
.credProps(
CredentialPropertiesOutput
.builder()
.authenticatorDisplayName("hej")
.build()
)
.build()
)
.build()
val result = rp.finishAssertion(
FinishAssertionOptions
.builder()
.request(request)
.response(pkc)
.build()
)

result.getAuthenticatorDisplayName.toScala should equal(
Some("hej")
)
}

it("when not available.") {
val pkc = pkcTemplate
val result = rp.finishAssertion(
FinishAssertionOptions
.builder()
.request(request)
.response(pkc)
.build()
)

result.getAuthenticatorDisplayName.toScala should equal(None)
}
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import com.yubico.webauthn.data.AuthenticatorTransport
import com.yubico.webauthn.data.ByteArray
import com.yubico.webauthn.data.ClientAssertionExtensionOutputs
import com.yubico.webauthn.data.CollectedClientData
import com.yubico.webauthn.data.Extensions.CredentialProperties.CredentialPropertiesOutput
import com.yubico.webauthn.data.Extensions.LargeBlob.LargeBlobAuthenticationInput
import com.yubico.webauthn.data.Extensions.LargeBlob.LargeBlobAuthenticationOutput
import com.yubico.webauthn.data.Extensions.Uvm.UvmEntry
Expand Down Expand Up @@ -2920,6 +2921,55 @@ class RelyingPartyV2AssertionSpec
)
}
}

describe("exposes the credProps.authenticatorDisplayName extension output as getAuthenticatorDisplayName()") {
val pkcTemplate =
TestAuthenticator.createAssertion(
challenge =
request.getPublicKeyCredentialRequestOptions.getChallenge,
credentialKey = credentialKeypair,
credentialId = credential.getId,
)

it("""when set to "hej".""") {
val pkc = pkcTemplate.toBuilder
.clientExtensionResults(
pkcTemplate.getClientExtensionResults.toBuilder
.credProps(
CredentialPropertiesOutput
.builder()
.authenticatorDisplayName("hej")
.build()
)
.build()
)
.build()
val result = rp.finishAssertion(
FinishAssertionOptions
.builder()
.request(request)
.response(pkc)
.build()
)

result.getAuthenticatorDisplayName.toScala should equal(
Some("hej")
)
}

it("when not available.") {
val pkc = pkcTemplate
val result = rp.finishAssertion(
FinishAssertionOptions
.builder()
.request(request)
.response(pkc)
.build()
)

result.getAuthenticatorDisplayName.toScala should equal(None)
}
}
}
}
}
Expand Down

0 comments on commit a1a3e2f

Please sign in to comment.