Skip to content

Commit

Permalink
Merge pull request #378 from Yubico/publicKeyCredentialHint
Browse files Browse the repository at this point in the history
Add support for PublicKeyCredentialHint
  • Loading branch information
emlun authored Sep 24, 2024
2 parents 49f0aeb + 7694886 commit b6f6a9a
Show file tree
Hide file tree
Showing 10 changed files with 1,121 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -493,7 +493,8 @@ public PublicKeyCredentialCreationOptions startRegistration(
.appidExclude(appId)
.credProps()
.build()))
.timeout(startRegistrationOptions.getTimeout());
.timeout(startRegistrationOptions.getTimeout())
.hints(startRegistrationOptions.getHints());
attestationConveyancePreference.ifPresent(builder::attestation);
return builder.build();
}
Expand Down Expand Up @@ -537,7 +538,8 @@ public AssertionRequest startAssertion(StartAssertionOptions startAssertionOptio
startAssertionOptions
.getExtensions()
.merge(startAssertionOptions.getExtensions().toBuilder().appid(appId).build()))
.timeout(startAssertionOptions.getTimeout());
.timeout(startAssertionOptions.getTimeout())
.hints(startAssertionOptions.getHints());

startAssertionOptions.getUserVerification().ifPresent(pkcro::userVerification);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -452,7 +452,8 @@ public PublicKeyCredentialCreationOptions startRegistration(
.appidExclude(appId)
.credProps()
.build()))
.timeout(startRegistrationOptions.getTimeout());
.timeout(startRegistrationOptions.getTimeout())
.hints(startRegistrationOptions.getHints());
attestationConveyancePreference.ifPresent(builder::attestation);
return builder.build();
}
Expand Down Expand Up @@ -509,7 +510,8 @@ public AssertionRequest startAssertion(StartAssertionOptions startAssertionOptio
startAssertionOptions
.getExtensions()
.merge(startAssertionOptions.getExtensions().toBuilder().appid(appId).build()))
.timeout(startAssertionOptions.getTimeout());
.timeout(startAssertionOptions.getTimeout())
.hints(startAssertionOptions.getHints());

startAssertionOptions.getUserVerification().ifPresent(pkcro::userVerification);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,13 @@

import com.yubico.webauthn.data.AssertionExtensionInputs;
import com.yubico.webauthn.data.ByteArray;
import com.yubico.webauthn.data.PublicKeyCredentialDescriptor;
import com.yubico.webauthn.data.PublicKeyCredentialHint;
import com.yubico.webauthn.data.PublicKeyCredentialRequestOptions;
import com.yubico.webauthn.data.UserVerificationRequirement;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import lombok.Builder;
import lombok.NonNull;
Expand Down Expand Up @@ -79,6 +84,55 @@ public class StartAssertionOptions {
*/
private final Long timeout;

/**
* Zero or more hints, in descending order of preference, to guide the user agent in interacting
* with the user during this authentication operation.
*
* <p>For example, the {@link PublicKeyCredentialHint#SECURITY_KEY} hint may be used to ask the
* client to emphasize the option of authenticating with an external security key, or the {@link
* PublicKeyCredentialHint#CLIENT_DEVICE} hint may be used to ask the client to emphasize the
* option of authenticating a built-in passkey provider.
*
* <p>These hints are not requirements, and do not bind the user-agent, but may guide it in
* providing the best experience by using contextual information about the request.
*
* <p>Hints MAY contradict information contained in {@link
* PublicKeyCredentialDescriptor#getTransports()}. When this occurs, the hints take precedence.
*
* <p>This library does not take these hints into account in any way, other than passing them
* through to the {@link PublicKeyCredentialRequestOptions} so they can be used in the argument to
* <code>navigator.credentials.get()</code> on the client side.
*
* <p>The default is empty.
*
* @see PublicKeyCredentialHint
* @see PublicKeyCredentialRequestOptions#getHints()
* @see StartAssertionOptionsBuilder#hints(List)
* @see StartAssertionOptionsBuilder#hints(String...)
* @see StartAssertionOptionsBuilder#hints(PublicKeyCredentialHint...)
* @see <a
* href="https://www.w3.org/TR/2023/WD-webauthn-3-20230927/#dom-publickeycredentialrequestoptions-hints">PublicKeyCredentialRequestOptions.hints</a>
* @see <a
* href="https://www.w3.org/TR/2023/WD-webauthn-3-20230927/#enumdef-publickeycredentialhints">§5.8.7.
* User-agent Hints Enumeration (enum PublicKeyCredentialHints)</a>
*/
private final List<String> hints;

private StartAssertionOptions(
String username,
ByteArray userHandle,
@NonNull AssertionExtensionInputs extensions,
UserVerificationRequirement userVerification,
Long timeout,
List<String> hints) {
this.username = username;
this.userHandle = userHandle;
this.extensions = extensions;
this.userVerification = userVerification;
this.timeout = timeout;
this.hints = hints == null ? Collections.emptyList() : Collections.unmodifiableList(hints);
}

/**
* The username of the user to authenticate, if the user has already been identified.
*
Expand Down Expand Up @@ -370,5 +424,122 @@ public StartAssertionOptionsBuilder timeout(long timeout) {
private StartAssertionOptionsBuilder timeout(Long timeout) {
return this.timeout(Optional.ofNullable(timeout));
}

/**
* Zero or more hints, in descending order of preference, to guide the user agent in interacting
* with the user during this authentication operation.
*
* <p>Setting this property multiple times overwrites any value set previously.
*
* <p>For example, the {@link PublicKeyCredentialHint#SECURITY_KEY} hint may be used to ask the
* client to emphasize the option of authenticating with an external security key, or the {@link
* PublicKeyCredentialHint#CLIENT_DEVICE} hint may be used to ask the client to emphasize the
* option of authenticating a built-in passkey provider.
*
* <p>These hints are not requirements, and do not bind the user-agent, but may guide it in
* providing the best experience by using contextual information about the request.
*
* <p>Hints MAY contradict information contained in {@link
* PublicKeyCredentialDescriptor#getTransports()}. When this occurs, the hints take precedence.
*
* <p>This library does not take these hints into account in any way, other than passing them
* through to the {@link PublicKeyCredentialRequestOptions} so they can be used in the argument
* to <code>navigator.credentials.get()</code> on the client side.
*
* <p>The default is empty.
*
* @see PublicKeyCredentialHint
* @see PublicKeyCredentialRequestOptions#getHints()
* @see StartAssertionOptions#getHints()
* @see StartAssertionOptionsBuilder#hints(List)
* @see StartAssertionOptionsBuilder#hints(PublicKeyCredentialHint...)
* @see <a
* href="https://www.w3.org/TR/2023/WD-webauthn-3-20230927/#dom-publickeycredentialrequestoptions-hints">PublicKeyCredentialRequestOptions.hints</a>
* @see <a
* href="https://www.w3.org/TR/2023/WD-webauthn-3-20230927/#enumdef-publickeycredentialhints">§5.8.7.
* User-agent Hints Enumeration (enum PublicKeyCredentialHints)</a>
*/
public StartAssertionOptionsBuilder hints(@NonNull String... hints) {
this.hints = Arrays.asList(hints);
return this;
}

/**
* Zero or more hints, in descending order of preference, to guide the user agent in interacting
* with the user during this authentication operation.
*
* <p>Setting this property multiple times overwrites any value set previously.
*
* <p>For example, the {@link PublicKeyCredentialHint#SECURITY_KEY} hint may be used to ask the
* client to emphasize the option of authenticating with an external security key, or the {@link
* PublicKeyCredentialHint#CLIENT_DEVICE} hint may be used to ask the client to emphasize the
* option of authenticating a built-in passkey provider.
*
* <p>These hints are not requirements, and do not bind the user-agent, but may guide it in
* providing the best experience by using contextual information about the request.
*
* <p>Hints MAY contradict information contained in {@link
* PublicKeyCredentialDescriptor#getTransports()}. When this occurs, the hints take precedence.
*
* <p>This library does not take these hints into account in any way, other than passing them
* through to the {@link PublicKeyCredentialRequestOptions} so they can be used in the argument
* to <code>navigator.credentials.get()</code> on the client side.
*
* <p>The default is empty.
*
* @see PublicKeyCredentialHint
* @see PublicKeyCredentialRequestOptions#getHints()
* @see StartAssertionOptions#getHints()
* @see StartAssertionOptionsBuilder#hints(List)
* @see StartAssertionOptionsBuilder#hints(String...)
* @see <a
* href="https://www.w3.org/TR/2023/WD-webauthn-3-20230927/#dom-publickeycredentialrequestoptions-hints">PublicKeyCredentialRequestOptions.hints</a>
* @see <a
* href="https://www.w3.org/TR/2023/WD-webauthn-3-20230927/#enumdef-publickeycredentialhints">§5.8.7.
* User-agent Hints Enumeration (enum PublicKeyCredentialHints)</a>
*/
public StartAssertionOptionsBuilder hints(@NonNull PublicKeyCredentialHint... hints) {
return this.hints(
Arrays.stream(hints).map(PublicKeyCredentialHint::getValue).toArray(String[]::new));
}

/**
* Zero or more hints, in descending order of preference, to guide the user agent in interacting
* with the user during this authentication operation.
*
* <p>Setting this property multiple times overwrites any value set previously.
*
* <p>For example, the {@link PublicKeyCredentialHint#SECURITY_KEY} hint may be used to ask the
* client to emphasize the option of authenticating with an external security key, or the {@link
* PublicKeyCredentialHint#CLIENT_DEVICE} hint may be used to ask the client to emphasize the
* option of authenticating a built-in passkey provider.
*
* <p>These hints are not requirements, and do not bind the user-agent, but may guide it in
* providing the best experience by using contextual information about the request.
*
* <p>Hints MAY contradict information contained in {@link
* PublicKeyCredentialDescriptor#getTransports()}. When this occurs, the hints take precedence.
*
* <p>This library does not take these hints into account in any way, other than passing them
* through to the {@link PublicKeyCredentialRequestOptions} so they can be used in the argument
* to <code>navigator.credentials.get()</code> on the client side.
*
* <p>The default is empty.
*
* @see PublicKeyCredentialHint
* @see PublicKeyCredentialRequestOptions#getHints()
* @see StartAssertionOptions#getHints()
* @see StartAssertionOptionsBuilder#hints(String...)
* @see StartAssertionOptionsBuilder#hints(PublicKeyCredentialHint...)
* @see <a
* href="https://www.w3.org/TR/2023/WD-webauthn-3-20230927/#dom-publickeycredentialrequestoptions-hints">PublicKeyCredentialRequestOptions.hints</a>
* @see <a
* href="https://www.w3.org/TR/2023/WD-webauthn-3-20230927/#enumdef-publickeycredentialhints">§5.8.7.
* User-agent Hints Enumeration (enum PublicKeyCredentialHints)</a>
*/
public StartAssertionOptionsBuilder hints(@NonNull List<String> hints) {
this.hints = hints;
return this;
}
}
}
Loading

1 comment on commit b6f6a9a

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mutation test results

Package Coverage Stats Prev Prev
Overall 81 % 🔹 1412 🔺 / 1726 🔺 82 % 1380 / 1682
com.yubico.fido.metadata 68 % 🔹 222 🔻 / 324 🔹 68 % 223 / 324
com.yubico.internal.util 46 % 🟢 57 🔺 / 123 🔹 45 % 56 / 123
com.yubico.webauthn 88 % 🔹 673 🔺 / 761 🔺 88 % 656 / 742
com.yubico.webauthn.attestation 92 % 🔹 13 🔹 / 14 🔹 92 % 13 / 14
com.yubico.webauthn.data 92 % 🔻 422 🔺 / 457 🔺 94 % 407 / 432
com.yubico.webauthn.extension.appid 100 % 🏆 13 🔹 / 13 🔹 100 % 13 / 13
com.yubico.webauthn.extension.uvm 50 % 🔹 12 🔹 / 24 🔹 50 % 12 / 24
com.yubico.webauthn.meta 0 % 🔹 0 🔹 / 10 🔹 0 % 0 / 10

Previous run: 49f0aeb - Diff

Detailed reports: workflow run #282

Please sign in to comment.