Skip to content

Commit b6f6a9a

Browse files
authored
Merge pull request #378 from Yubico/publicKeyCredentialHint
Add support for PublicKeyCredentialHint
2 parents 49f0aeb + 7694886 commit b6f6a9a

File tree

10 files changed

+1121
-25
lines changed

10 files changed

+1121
-25
lines changed

webauthn-server-core/src/main/java/com/yubico/webauthn/RelyingParty.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -493,7 +493,8 @@ public PublicKeyCredentialCreationOptions startRegistration(
493493
.appidExclude(appId)
494494
.credProps()
495495
.build()))
496-
.timeout(startRegistrationOptions.getTimeout());
496+
.timeout(startRegistrationOptions.getTimeout())
497+
.hints(startRegistrationOptions.getHints());
497498
attestationConveyancePreference.ifPresent(builder::attestation);
498499
return builder.build();
499500
}
@@ -537,7 +538,8 @@ public AssertionRequest startAssertion(StartAssertionOptions startAssertionOptio
537538
startAssertionOptions
538539
.getExtensions()
539540
.merge(startAssertionOptions.getExtensions().toBuilder().appid(appId).build()))
540-
.timeout(startAssertionOptions.getTimeout());
541+
.timeout(startAssertionOptions.getTimeout())
542+
.hints(startAssertionOptions.getHints());
541543

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

webauthn-server-core/src/main/java/com/yubico/webauthn/RelyingPartyV2.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -452,7 +452,8 @@ public PublicKeyCredentialCreationOptions startRegistration(
452452
.appidExclude(appId)
453453
.credProps()
454454
.build()))
455-
.timeout(startRegistrationOptions.getTimeout());
455+
.timeout(startRegistrationOptions.getTimeout())
456+
.hints(startRegistrationOptions.getHints());
456457
attestationConveyancePreference.ifPresent(builder::attestation);
457458
return builder.build();
458459
}
@@ -509,7 +510,8 @@ public AssertionRequest startAssertion(StartAssertionOptions startAssertionOptio
509510
startAssertionOptions
510511
.getExtensions()
511512
.merge(startAssertionOptions.getExtensions().toBuilder().appid(appId).build()))
512-
.timeout(startAssertionOptions.getTimeout());
513+
.timeout(startAssertionOptions.getTimeout())
514+
.hints(startAssertionOptions.getHints());
513515

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

webauthn-server-core/src/main/java/com/yubico/webauthn/StartAssertionOptions.java

Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,13 @@
2626

2727
import com.yubico.webauthn.data.AssertionExtensionInputs;
2828
import com.yubico.webauthn.data.ByteArray;
29+
import com.yubico.webauthn.data.PublicKeyCredentialDescriptor;
30+
import com.yubico.webauthn.data.PublicKeyCredentialHint;
2931
import com.yubico.webauthn.data.PublicKeyCredentialRequestOptions;
3032
import com.yubico.webauthn.data.UserVerificationRequirement;
33+
import java.util.Arrays;
34+
import java.util.Collections;
35+
import java.util.List;
3136
import java.util.Optional;
3237
import lombok.Builder;
3338
import lombok.NonNull;
@@ -79,6 +84,55 @@ public class StartAssertionOptions {
7984
*/
8085
private final Long timeout;
8186

87+
/**
88+
* Zero or more hints, in descending order of preference, to guide the user agent in interacting
89+
* with the user during this authentication operation.
90+
*
91+
* <p>For example, the {@link PublicKeyCredentialHint#SECURITY_KEY} hint may be used to ask the
92+
* client to emphasize the option of authenticating with an external security key, or the {@link
93+
* PublicKeyCredentialHint#CLIENT_DEVICE} hint may be used to ask the client to emphasize the
94+
* option of authenticating a built-in passkey provider.
95+
*
96+
* <p>These hints are not requirements, and do not bind the user-agent, but may guide it in
97+
* providing the best experience by using contextual information about the request.
98+
*
99+
* <p>Hints MAY contradict information contained in {@link
100+
* PublicKeyCredentialDescriptor#getTransports()}. When this occurs, the hints take precedence.
101+
*
102+
* <p>This library does not take these hints into account in any way, other than passing them
103+
* through to the {@link PublicKeyCredentialRequestOptions} so they can be used in the argument to
104+
* <code>navigator.credentials.get()</code> on the client side.
105+
*
106+
* <p>The default is empty.
107+
*
108+
* @see PublicKeyCredentialHint
109+
* @see PublicKeyCredentialRequestOptions#getHints()
110+
* @see StartAssertionOptionsBuilder#hints(List)
111+
* @see StartAssertionOptionsBuilder#hints(String...)
112+
* @see StartAssertionOptionsBuilder#hints(PublicKeyCredentialHint...)
113+
* @see <a
114+
* href="https://www.w3.org/TR/2023/WD-webauthn-3-20230927/#dom-publickeycredentialrequestoptions-hints">PublicKeyCredentialRequestOptions.hints</a>
115+
* @see <a
116+
* href="https://www.w3.org/TR/2023/WD-webauthn-3-20230927/#enumdef-publickeycredentialhints">§5.8.7.
117+
* User-agent Hints Enumeration (enum PublicKeyCredentialHints)</a>
118+
*/
119+
private final List<String> hints;
120+
121+
private StartAssertionOptions(
122+
String username,
123+
ByteArray userHandle,
124+
@NonNull AssertionExtensionInputs extensions,
125+
UserVerificationRequirement userVerification,
126+
Long timeout,
127+
List<String> hints) {
128+
this.username = username;
129+
this.userHandle = userHandle;
130+
this.extensions = extensions;
131+
this.userVerification = userVerification;
132+
this.timeout = timeout;
133+
this.hints = hints == null ? Collections.emptyList() : Collections.unmodifiableList(hints);
134+
}
135+
82136
/**
83137
* The username of the user to authenticate, if the user has already been identified.
84138
*
@@ -370,5 +424,122 @@ public StartAssertionOptionsBuilder timeout(long timeout) {
370424
private StartAssertionOptionsBuilder timeout(Long timeout) {
371425
return this.timeout(Optional.ofNullable(timeout));
372426
}
427+
428+
/**
429+
* Zero or more hints, in descending order of preference, to guide the user agent in interacting
430+
* with the user during this authentication operation.
431+
*
432+
* <p>Setting this property multiple times overwrites any value set previously.
433+
*
434+
* <p>For example, the {@link PublicKeyCredentialHint#SECURITY_KEY} hint may be used to ask the
435+
* client to emphasize the option of authenticating with an external security key, or the {@link
436+
* PublicKeyCredentialHint#CLIENT_DEVICE} hint may be used to ask the client to emphasize the
437+
* option of authenticating a built-in passkey provider.
438+
*
439+
* <p>These hints are not requirements, and do not bind the user-agent, but may guide it in
440+
* providing the best experience by using contextual information about the request.
441+
*
442+
* <p>Hints MAY contradict information contained in {@link
443+
* PublicKeyCredentialDescriptor#getTransports()}. When this occurs, the hints take precedence.
444+
*
445+
* <p>This library does not take these hints into account in any way, other than passing them
446+
* through to the {@link PublicKeyCredentialRequestOptions} so they can be used in the argument
447+
* to <code>navigator.credentials.get()</code> on the client side.
448+
*
449+
* <p>The default is empty.
450+
*
451+
* @see PublicKeyCredentialHint
452+
* @see PublicKeyCredentialRequestOptions#getHints()
453+
* @see StartAssertionOptions#getHints()
454+
* @see StartAssertionOptionsBuilder#hints(List)
455+
* @see StartAssertionOptionsBuilder#hints(PublicKeyCredentialHint...)
456+
* @see <a
457+
* href="https://www.w3.org/TR/2023/WD-webauthn-3-20230927/#dom-publickeycredentialrequestoptions-hints">PublicKeyCredentialRequestOptions.hints</a>
458+
* @see <a
459+
* href="https://www.w3.org/TR/2023/WD-webauthn-3-20230927/#enumdef-publickeycredentialhints">§5.8.7.
460+
* User-agent Hints Enumeration (enum PublicKeyCredentialHints)</a>
461+
*/
462+
public StartAssertionOptionsBuilder hints(@NonNull String... hints) {
463+
this.hints = Arrays.asList(hints);
464+
return this;
465+
}
466+
467+
/**
468+
* Zero or more hints, in descending order of preference, to guide the user agent in interacting
469+
* with the user during this authentication operation.
470+
*
471+
* <p>Setting this property multiple times overwrites any value set previously.
472+
*
473+
* <p>For example, the {@link PublicKeyCredentialHint#SECURITY_KEY} hint may be used to ask the
474+
* client to emphasize the option of authenticating with an external security key, or the {@link
475+
* PublicKeyCredentialHint#CLIENT_DEVICE} hint may be used to ask the client to emphasize the
476+
* option of authenticating a built-in passkey provider.
477+
*
478+
* <p>These hints are not requirements, and do not bind the user-agent, but may guide it in
479+
* providing the best experience by using contextual information about the request.
480+
*
481+
* <p>Hints MAY contradict information contained in {@link
482+
* PublicKeyCredentialDescriptor#getTransports()}. When this occurs, the hints take precedence.
483+
*
484+
* <p>This library does not take these hints into account in any way, other than passing them
485+
* through to the {@link PublicKeyCredentialRequestOptions} so they can be used in the argument
486+
* to <code>navigator.credentials.get()</code> on the client side.
487+
*
488+
* <p>The default is empty.
489+
*
490+
* @see PublicKeyCredentialHint
491+
* @see PublicKeyCredentialRequestOptions#getHints()
492+
* @see StartAssertionOptions#getHints()
493+
* @see StartAssertionOptionsBuilder#hints(List)
494+
* @see StartAssertionOptionsBuilder#hints(String...)
495+
* @see <a
496+
* href="https://www.w3.org/TR/2023/WD-webauthn-3-20230927/#dom-publickeycredentialrequestoptions-hints">PublicKeyCredentialRequestOptions.hints</a>
497+
* @see <a
498+
* href="https://www.w3.org/TR/2023/WD-webauthn-3-20230927/#enumdef-publickeycredentialhints">§5.8.7.
499+
* User-agent Hints Enumeration (enum PublicKeyCredentialHints)</a>
500+
*/
501+
public StartAssertionOptionsBuilder hints(@NonNull PublicKeyCredentialHint... hints) {
502+
return this.hints(
503+
Arrays.stream(hints).map(PublicKeyCredentialHint::getValue).toArray(String[]::new));
504+
}
505+
506+
/**
507+
* Zero or more hints, in descending order of preference, to guide the user agent in interacting
508+
* with the user during this authentication operation.
509+
*
510+
* <p>Setting this property multiple times overwrites any value set previously.
511+
*
512+
* <p>For example, the {@link PublicKeyCredentialHint#SECURITY_KEY} hint may be used to ask the
513+
* client to emphasize the option of authenticating with an external security key, or the {@link
514+
* PublicKeyCredentialHint#CLIENT_DEVICE} hint may be used to ask the client to emphasize the
515+
* option of authenticating a built-in passkey provider.
516+
*
517+
* <p>These hints are not requirements, and do not bind the user-agent, but may guide it in
518+
* providing the best experience by using contextual information about the request.
519+
*
520+
* <p>Hints MAY contradict information contained in {@link
521+
* PublicKeyCredentialDescriptor#getTransports()}. When this occurs, the hints take precedence.
522+
*
523+
* <p>This library does not take these hints into account in any way, other than passing them
524+
* through to the {@link PublicKeyCredentialRequestOptions} so they can be used in the argument
525+
* to <code>navigator.credentials.get()</code> on the client side.
526+
*
527+
* <p>The default is empty.
528+
*
529+
* @see PublicKeyCredentialHint
530+
* @see PublicKeyCredentialRequestOptions#getHints()
531+
* @see StartAssertionOptions#getHints()
532+
* @see StartAssertionOptionsBuilder#hints(String...)
533+
* @see StartAssertionOptionsBuilder#hints(PublicKeyCredentialHint...)
534+
* @see <a
535+
* href="https://www.w3.org/TR/2023/WD-webauthn-3-20230927/#dom-publickeycredentialrequestoptions-hints">PublicKeyCredentialRequestOptions.hints</a>
536+
* @see <a
537+
* href="https://www.w3.org/TR/2023/WD-webauthn-3-20230927/#enumdef-publickeycredentialhints">§5.8.7.
538+
* User-agent Hints Enumeration (enum PublicKeyCredentialHints)</a>
539+
*/
540+
public StartAssertionOptionsBuilder hints(@NonNull List<String> hints) {
541+
this.hints = hints;
542+
return this;
543+
}
373544
}
374545
}

0 commit comments

Comments
 (0)