PublicKeyCredentialCreationOptions.java

1
// Copyright (c) 2018, Yubico AB
2
// All rights reserved.
3
//
4
// Redistribution and use in source and binary forms, with or without
5
// modification, are permitted provided that the following conditions are met:
6
//
7
// 1. Redistributions of source code must retain the above copyright notice, this
8
//    list of conditions and the following disclaimer.
9
//
10
// 2. Redistributions in binary form must reproduce the above copyright notice,
11
//    this list of conditions and the following disclaimer in the documentation
12
//    and/or other materials provided with the distribution.
13
//
14
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
18
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
20
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
21
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
22
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24
25
package com.yubico.webauthn.data;
26
27
import com.fasterxml.jackson.annotation.JsonCreator;
28
import com.fasterxml.jackson.annotation.JsonProperty;
29
import com.fasterxml.jackson.core.JsonProcessingException;
30
import com.fasterxml.jackson.databind.ObjectMapper;
31
import com.fasterxml.jackson.databind.node.ObjectNode;
32
import com.yubico.internal.util.CollectionUtil;
33
import com.yubico.internal.util.JacksonCodecs;
34
import com.yubico.webauthn.FinishRegistrationOptions;
35
import com.yubico.webauthn.RelyingParty;
36
import com.yubico.webauthn.StartRegistrationOptions;
37
import java.security.KeyFactory;
38
import java.security.NoSuchAlgorithmException;
39
import java.security.Signature;
40
import java.util.Arrays;
41
import java.util.Collections;
42
import java.util.List;
43
import java.util.Optional;
44
import java.util.Set;
45
import java.util.TreeSet;
46
import java.util.stream.Collectors;
47
import lombok.Builder;
48
import lombok.NonNull;
49
import lombok.Value;
50
import lombok.extern.slf4j.Slf4j;
51
52
/**
53
 * Parameters for a call to <code>navigator.credentials.create()</code>.
54
 *
55
 * @see <a
56
 *     href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#dictdef-publickeycredentialcreationoptions">§5.4.
57
 *     Options for Credential Creation (dictionary PublicKeyCredentialCreationOptions)</a>
58
 */
59
@Slf4j
60
@Value
61
@Builder(toBuilder = true)
62
public class PublicKeyCredentialCreationOptions {
63
64
  /**
65
   * Contains data about the Relying Party responsible for the request.
66
   *
67
   * <p>Its value's {@link RelyingPartyIdentity#getId() id} member specifies the <a
68
   * href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#rp-id">RP ID</a> the credential
69
   * should be scoped to. If omitted, its value will be set by the client. See {@link
70
   * RelyingPartyIdentity} for further details.
71
   */
72
  @NonNull private final RelyingPartyIdentity rp;
73
74
  /** Contains data about the user account for which the Relying Party is requesting attestation. */
75
  @NonNull private final UserIdentity user;
76
77
  /**
78
   * A challenge intended to be used for generating the newly created credential’s attestation
79
   * object. See the <a
80
   * href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#sctn-cryptographic-challenges">§13.1
81
   * Cryptographic Challenges</a> security consideration.
82
   */
83
  @NonNull private final ByteArray challenge;
84
85
  /**
86
   * Information about the desired properties of the credential to be created.
87
   *
88
   * <p>The sequence is ordered from most preferred to least preferred. The client makes a
89
   * best-effort to create the most preferred credential that it can.
90
   */
91
  @NonNull private final List<PublicKeyCredentialParameters> pubKeyCredParams;
92
93
  /**
94
   * A time, in milliseconds, that the caller is willing to wait for the call to complete. This is
95
   * treated as a hint, and MAY be overridden by the client.
96
   */
97
  private final Long timeout;
98
99
  /**
100
   * Zero or more hints, in descending order of preference, to guide the user agent in interacting
101
   * with the user during this registration operation.
102
   *
103
   * <p>For example, the {@link PublicKeyCredentialHint#SECURITY_KEY} hint may be used to ask the
104
   * client to emphasize the option of registering with an external security key, or the {@link
105
   * PublicKeyCredentialHint#CLIENT_DEVICE} hint may be used to ask the client to emphasize the
106
   * option of registering a built-in passkey provider.
107
   *
108
   * <p>These hints are not requirements, and do not bind the user-agent, but may guide it in
109
   * providing the best experience by using contextual information about the request.
110
   *
111
   * <p>Hints MAY contradict preferences in {@link #getAuthenticatorSelection()}. When this occurs,
112
   * the hints take precedence.
113
   *
114
   * <p>This library does not take these hints into account in any way, other than passing them
115
   * through so they can be used in the argument to <code>navigator.credentials.create()</code> on
116
   * the client side.
117
   *
118
   * <p>The default is empty.
119
   *
120
   * @see PublicKeyCredentialHint
121
   * @see StartRegistrationOptions#getHints()
122
   * @see PublicKeyCredentialCreationOptionsBuilder#hints(List)
123
   * @see PublicKeyCredentialCreationOptionsBuilder#hints(String...)
124
   * @see PublicKeyCredentialCreationOptionsBuilder#hints(PublicKeyCredentialHint...)
125
   * @see <a
126
   *     href="https://www.w3.org/TR/2023/WD-webauthn-3-20230927/#dom-publickeycredentialcreationoptions-hints">PublicKeyCredentialCreationOptions.hints</a>
127
   * @see <a
128
   *     href="https://www.w3.org/TR/2023/WD-webauthn-3-20230927/#enumdef-publickeycredentialhints">§5.8.7.
129
   *     User-agent Hints Enumeration (enum PublicKeyCredentialHints)</a>
130
   */
131
  private final List<String> hints;
132
133
  /**
134
   * Intended for use by Relying Parties that wish to limit the creation of multiple credentials for
135
   * the same account on a single authenticator. The client is requested to return an error if the
136
   * new credential would be created on an authenticator that also contains one of the credentials
137
   * enumerated in this parameter.
138
   */
139
  private final Set<PublicKeyCredentialDescriptor> excludeCredentials;
140
141
  /**
142
   * Intended for use by Relying Parties that wish to select the appropriate authenticators to
143
   * participate in the create() operation.
144
   */
145
  private final AuthenticatorSelectionCriteria authenticatorSelection;
146
147
  /**
148
   * Intended for use by Relying Parties that wish to express their preference for attestation
149
   * conveyance. The default is {@link AttestationConveyancePreference#NONE}.
150
   */
151
  @NonNull private final AttestationConveyancePreference attestation;
152
153
  /**
154
   * Additional parameters requesting additional processing by the client and authenticator.
155
   *
156
   * <p>For example, the caller may request that only authenticators with certain capabilities be
157
   * used to create the credential, or that particular information be returned in the attestation
158
   * object. Some extensions are defined in <a
159
   * href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#sctn-extensions">§9 WebAuthn
160
   * Extensions</a>; consult the IANA "WebAuthn Extension Identifier" registry established by <a
161
   * href="https://tools.ietf.org/html/draft-hodges-webauthn-registries">[WebAuthn-Registries]</a>
162
   * for an up-to-date list of registered WebAuthn Extensions.
163
   */
164
  @NonNull private final RegistrationExtensionInputs extensions;
165
166
  @Builder
167
  @JsonCreator
168
  private PublicKeyCredentialCreationOptions(
169 1 1. <init> : negated conditional → KILLED
      @NonNull @JsonProperty("rp") RelyingPartyIdentity rp,
170 1 1. <init> : negated conditional → KILLED
      @NonNull @JsonProperty("user") UserIdentity user,
171 1 1. <init> : negated conditional → KILLED
      @NonNull @JsonProperty("challenge") ByteArray challenge,
172 1 1. <init> : negated conditional → KILLED
      @NonNull @JsonProperty("pubKeyCredParams")
173
          List<PublicKeyCredentialParameters> pubKeyCredParams,
174
      @JsonProperty("timeout") Long timeout,
175
      @JsonProperty("hints") List<String> hints,
176
      @JsonProperty("excludeCredentials") Set<PublicKeyCredentialDescriptor> excludeCredentials,
177
      @JsonProperty("authenticatorSelection") AuthenticatorSelectionCriteria authenticatorSelection,
178
      @JsonProperty("attestation") AttestationConveyancePreference attestation,
179
      @JsonProperty("extensions") RegistrationExtensionInputs extensions) {
180
    this.rp = rp;
181
    this.user = user;
182
    this.challenge = challenge;
183
    this.pubKeyCredParams = filterAvailableAlgorithms(pubKeyCredParams);
184
    this.timeout = timeout;
185 1 1. <init> : negated conditional → KILLED
    this.hints = hints == null ? Collections.emptyList() : Collections.unmodifiableList(hints);
186
    this.excludeCredentials =
187 1 1. <init> : negated conditional → KILLED
        excludeCredentials == null
188
            ? null
189
            : CollectionUtil.immutableSortedSet(new TreeSet<>(excludeCredentials));
190
    this.authenticatorSelection = authenticatorSelection;
191 1 1. <init> : negated conditional → KILLED
    this.attestation = attestation == null ? AttestationConveyancePreference.NONE : attestation;
192
    this.extensions =
193 1 1. <init> : negated conditional → KILLED
        extensions == null ? RegistrationExtensionInputs.builder().build() : extensions;
194
  }
195
196
  /**
197
   * Serialize this {@link PublicKeyCredentialCreationOptions} value to JSON suitable for sending to
198
   * the client.
199
   *
200
   * <p>Any {@link ByteArray} values in this data structure will be {@link ByteArray#getBase64Url()
201
   * Base64Url} encoded. Those values MUST be decoded into <code>BufferSource</code> values (such as
202
   * <code>Uint8Array</code>) on the client side before calling <code>navigator.credentials.create()
203
   * </code>.
204
   *
205
   * <p>After decoding binary values, the resulting JavaScript object is suitable for passing as an
206
   * argument to <code>navigator.credentials.create()</code>.
207
   *
208
   * @return a JSON value suitable for sending to the client and passing as an argument to <code>
209
   *     navigator.credentials.create()</code>, after decoding binary options from Base64Url
210
   *     strings.
211
   * @throws JsonProcessingException if JSON serialization fails.
212
   */
213
  public String toCredentialsCreateJson() throws JsonProcessingException {
214
    ObjectMapper json = JacksonCodecs.json();
215
    ObjectNode result = json.createObjectNode();
216
    result.set("publicKey", json.valueToTree(this));
217 1 1. toCredentialsCreateJson : replaced return value with "" for com/yubico/webauthn/data/PublicKeyCredentialCreationOptions::toCredentialsCreateJson → KILLED
    return json.writeValueAsString(result);
218
  }
219
220
  /**
221
   * Encode this {@link PublicKeyCredentialCreationOptions} to JSON. The inverse of {@link
222
   * #fromJson(String)}.
223
   *
224
   * <p>This method is suitable for encoding the {@link PublicKeyCredentialCreationOptions} for
225
   * temporary storage so that it can later be passed as an argument to {@link
226
   * RelyingParty#finishRegistration(FinishRegistrationOptions)}. The {@link #fromJson(String)}
227
   * factory function is guaranteed to restore an identical {@link
228
   * PublicKeyCredentialCreationOptions} instance.
229
   *
230
   * <p>Note that encoding might not be needed if you can simply keep the {@link
231
   * PublicKeyCredentialCreationOptions} instance in server memory.
232
   *
233
   * @return this {@link PublicKeyCredentialCreationOptions} encoded to JSON.
234
   * @throws JsonProcessingException
235
   */
236
  public String toJson() throws JsonProcessingException {
237 1 1. toJson : replaced return value with "" for com/yubico/webauthn/data/PublicKeyCredentialCreationOptions::toJson → KILLED
    return JacksonCodecs.json().writeValueAsString(this);
238
  }
239
240
  /**
241
   * Decode a {@link PublicKeyCredentialCreationOptions} from JSON. The inverse of {@link
242
   * #toJson()}.
243
   *
244
   * <p>If the JSON was generated by the {@link #toJson()} method, then {@link #fromJson(String)} in
245
   * the same library version guarantees to restore an identical {@link
246
   * PublicKeyCredentialCreationOptions} instance. This is not guaranteed between different library
247
   * versions.
248
   *
249
   * @return a {@link PublicKeyCredentialCreationOptions} decoded from the input JSON.
250
   * @throws JsonProcessingException
251
   */
252
  public static PublicKeyCredentialCreationOptions fromJson(String json)
253
      throws JsonProcessingException {
254 1 1. fromJson : replaced return value with null for com/yubico/webauthn/data/PublicKeyCredentialCreationOptions::fromJson → KILLED
    return JacksonCodecs.json().readValue(json, PublicKeyCredentialCreationOptions.class);
255
  }
256
257
  public Optional<Long> getTimeout() {
258 1 1. getTimeout : replaced return value with Optional.empty for com/yubico/webauthn/data/PublicKeyCredentialCreationOptions::getTimeout → KILLED
    return Optional.ofNullable(timeout);
259
  }
260
261
  public Optional<Set<PublicKeyCredentialDescriptor>> getExcludeCredentials() {
262 1 1. getExcludeCredentials : replaced return value with Optional.empty for com/yubico/webauthn/data/PublicKeyCredentialCreationOptions::getExcludeCredentials → KILLED
    return Optional.ofNullable(excludeCredentials);
263
  }
264
265
  public Optional<AuthenticatorSelectionCriteria> getAuthenticatorSelection() {
266 1 1. getAuthenticatorSelection : replaced return value with Optional.empty for com/yubico/webauthn/data/PublicKeyCredentialCreationOptions::getAuthenticatorSelection → KILLED
    return Optional.ofNullable(authenticatorSelection);
267
  }
268
269
  public static PublicKeyCredentialCreationOptionsBuilder.MandatoryStages builder() {
270 1 1. builder : replaced return value with null for com/yubico/webauthn/data/PublicKeyCredentialCreationOptions::builder → KILLED
    return new PublicKeyCredentialCreationOptionsBuilder.MandatoryStages();
271
  }
272
273
  public static class PublicKeyCredentialCreationOptionsBuilder {
274
    private Long timeout = null;
275
    private Set<PublicKeyCredentialDescriptor> excludeCredentials = null;
276
    private AuthenticatorSelectionCriteria authenticatorSelection = null;
277
278
    public static class MandatoryStages {
279
      private final PublicKeyCredentialCreationOptionsBuilder builder =
280
          new PublicKeyCredentialCreationOptionsBuilder();
281
282
      /**
283
       * {@link PublicKeyCredentialCreationOptionsBuilder#rp(RelyingPartyIdentity) rp} is a required
284
       * parameter.
285
       *
286
       * @see PublicKeyCredentialCreationOptionsBuilder#rp(RelyingPartyIdentity)
287
       */
288
      public Step2 rp(RelyingPartyIdentity rp) {
289
        builder.rp(rp);
290 1 1. rp : replaced return value with null for com/yubico/webauthn/data/PublicKeyCredentialCreationOptions$PublicKeyCredentialCreationOptionsBuilder$MandatoryStages::rp → KILLED
        return new Step2();
291
      }
292
293
      public class Step2 {
294
        /**
295
         * {@link PublicKeyCredentialCreationOptionsBuilder#user(UserIdentity) user} is a required
296
         * parameter.
297
         *
298
         * @see PublicKeyCredentialCreationOptionsBuilder#user(UserIdentity)
299
         */
300
        public Step3 user(UserIdentity user) {
301
          builder.user(user);
302 1 1. user : replaced return value with null for com/yubico/webauthn/data/PublicKeyCredentialCreationOptions$PublicKeyCredentialCreationOptionsBuilder$MandatoryStages$Step2::user → KILLED
          return new Step3();
303
        }
304
      }
305
306
      public class Step3 {
307
        /**
308
         * {@link PublicKeyCredentialCreationOptionsBuilder#challenge(ByteArray) challenge} is a
309
         * required parameter.
310
         *
311
         * @see PublicKeyCredentialCreationOptionsBuilder#challenge(ByteArray)
312
         */
313
        public Step4 challenge(ByteArray challenge) {
314
          builder.challenge(challenge);
315 1 1. challenge : replaced return value with null for com/yubico/webauthn/data/PublicKeyCredentialCreationOptions$PublicKeyCredentialCreationOptionsBuilder$MandatoryStages$Step3::challenge → KILLED
          return new Step4();
316
        }
317
      }
318
319
      public class Step4 {
320
        /**
321
         * {@link PublicKeyCredentialCreationOptionsBuilder#pubKeyCredParams(List) pubKeyCredParams}
322
         * is a required parameter.
323
         *
324
         * @see PublicKeyCredentialCreationOptionsBuilder#pubKeyCredParams(List)
325
         */
326
        public PublicKeyCredentialCreationOptionsBuilder pubKeyCredParams(
327
            List<PublicKeyCredentialParameters> pubKeyCredParams) {
328 1 1. pubKeyCredParams : replaced return value with null for com/yubico/webauthn/data/PublicKeyCredentialCreationOptions$PublicKeyCredentialCreationOptionsBuilder$MandatoryStages$Step4::pubKeyCredParams → KILLED
          return builder.pubKeyCredParams(pubKeyCredParams);
329
        }
330
      }
331
    }
332
333
    /**
334
     * A time, in milliseconds, that the caller is willing to wait for the call to complete. This is
335
     * treated as a hint, and MAY be overridden by the client.
336
     */
337 1 1. timeout : negated conditional → KILLED
    public PublicKeyCredentialCreationOptionsBuilder timeout(@NonNull Optional<Long> timeout) {
338
      this.timeout = timeout.orElse(null);
339 1 1. timeout : replaced return value with null for com/yubico/webauthn/data/PublicKeyCredentialCreationOptions$PublicKeyCredentialCreationOptionsBuilder::timeout → KILLED
      return this;
340
    }
341
342
    /*
343
     * Workaround, see: https://github.com/rzwitserloot/lombok/issues/2623#issuecomment-714816001
344
     * Consider reverting this workaround if Lombok fixes that issue.
345
     */
346
    private PublicKeyCredentialCreationOptionsBuilder timeout(Long timeout) {
347 1 1. timeout : replaced return value with null for com/yubico/webauthn/data/PublicKeyCredentialCreationOptions$PublicKeyCredentialCreationOptionsBuilder::timeout → KILLED
      return this.timeout(Optional.ofNullable(timeout));
348
    }
349
350
    /**
351
     * A time, in milliseconds, that the caller is willing to wait for the call to complete. This is
352
     * treated as a hint, and MAY be overridden by the client.
353
     */
354
    public PublicKeyCredentialCreationOptionsBuilder timeout(long timeout) {
355 1 1. timeout : replaced return value with null for com/yubico/webauthn/data/PublicKeyCredentialCreationOptions$PublicKeyCredentialCreationOptionsBuilder::timeout → NO_COVERAGE
      return this.timeout(Optional.of(timeout));
356
    }
357
358
    /**
359
     * Zero or more hints, in descending order of preference, to guide the user agent in interacting
360
     * with the user during this registration operation.
361
     *
362
     * <p>For example, the {@link PublicKeyCredentialHint#SECURITY_KEY} hint may be used to ask the
363
     * client to emphasize the option of registering with an external security key, or the {@link
364
     * PublicKeyCredentialHint#CLIENT_DEVICE} hint may be used to ask the client to emphasize the
365
     * option of registering a built-in passkey provider.
366
     *
367
     * <p>These hints are not requirements, and do not bind the user-agent, but may guide it in
368
     * providing the best experience by using contextual information about the request.
369
     *
370
     * <p>Hints MAY contradict preferences in {@link #getAuthenticatorSelection()}. When this
371
     * occurs, the hints take precedence.
372
     *
373
     * <p>This library does not take these hints into account in any way, other than passing them
374
     * through so they can be used in the argument to <code>navigator.credentials.create()</code> on
375
     * the client side.
376
     *
377
     * <p>The default is empty.
378
     *
379
     * @see PublicKeyCredentialHint
380
     * @see StartRegistrationOptions#getHints()
381
     * @see PublicKeyCredentialCreationOptions#getHints()
382
     * @see PublicKeyCredentialCreationOptionsBuilder#hints(List)
383
     * @see PublicKeyCredentialCreationOptionsBuilder#hints(PublicKeyCredentialHint...)
384
     * @see <a
385
     *     href="https://www.w3.org/TR/2023/WD-webauthn-3-20230927/#dom-publickeycredentialcreationoptions-hints">PublicKeyCredentialCreationOptions.hints</a>
386
     * @see <a
387
     *     href="https://www.w3.org/TR/2023/WD-webauthn-3-20230927/#enumdef-publickeycredentialhints">§5.8.7.
388
     *     User-agent Hints Enumeration (enum PublicKeyCredentialHints)</a>
389
     */
390 1 1. hints : negated conditional → KILLED
    public PublicKeyCredentialCreationOptionsBuilder hints(@NonNull String... hints) {
391
      this.hints = Arrays.asList(hints);
392 1 1. hints : replaced return value with null for com/yubico/webauthn/data/PublicKeyCredentialCreationOptions$PublicKeyCredentialCreationOptionsBuilder::hints → SURVIVED
      return this;
393
    }
394
395
    /**
396
     * Zero or more hints, in descending order of preference, to guide the user agent in interacting
397
     * with the user during this registration operation.
398
     *
399
     * <p>For example, the {@link PublicKeyCredentialHint#SECURITY_KEY} hint may be used to ask the
400
     * client to emphasize the option of registering with an external security key, or the {@link
401
     * PublicKeyCredentialHint#CLIENT_DEVICE} hint may be used to ask the client to emphasize the
402
     * option of registering a built-in passkey provider.
403
     *
404
     * <p>These hints are not requirements, and do not bind the user-agent, but may guide it in
405
     * providing the best experience by using contextual information about the request.
406
     *
407
     * <p>Hints MAY contradict preferences in {@link #getAuthenticatorSelection()}. When this
408
     * occurs, the hints take precedence.
409
     *
410
     * <p>This library does not take these hints into account in any way, other than passing them
411
     * through so they can be used in the argument to <code>navigator.credentials.create()</code> on
412
     * the client side.
413
     *
414
     * <p>The default is empty.
415
     *
416
     * @see PublicKeyCredentialHint
417
     * @see StartRegistrationOptions#getHints()
418
     * @see PublicKeyCredentialCreationOptions#getHints()
419
     * @see PublicKeyCredentialCreationOptionsBuilder#hints(List)
420
     * @see PublicKeyCredentialCreationOptionsBuilder#hints(String...)
421
     * @see <a
422
     *     href="https://www.w3.org/TR/2023/WD-webauthn-3-20230927/#dom-publickeycredentialcreationoptions-hints">PublicKeyCredentialCreationOptions.hints</a>
423
     * @see <a
424
     *     href="https://www.w3.org/TR/2023/WD-webauthn-3-20230927/#enumdef-publickeycredentialhints">§5.8.7.
425
     *     User-agent Hints Enumeration (enum PublicKeyCredentialHints)</a>
426
     */
427
    public PublicKeyCredentialCreationOptionsBuilder hints(
428 1 1. hints : negated conditional → KILLED
        @NonNull PublicKeyCredentialHint... hints) {
429 1 1. hints : replaced return value with null for com/yubico/webauthn/data/PublicKeyCredentialCreationOptions$PublicKeyCredentialCreationOptionsBuilder::hints → SURVIVED
      return this.hints(
430 1 1. lambda$hints$0 : replaced return value with null for com/yubico/webauthn/data/PublicKeyCredentialCreationOptions$PublicKeyCredentialCreationOptionsBuilder::lambda$hints$0 → KILLED
          Arrays.stream(hints).map(PublicKeyCredentialHint::getValue).toArray(String[]::new));
431
    }
432
433
    /**
434
     * Zero or more hints, in descending order of preference, to guide the user agent in interacting
435
     * with the user during this registration operation.
436
     *
437
     * <p>For example, the {@link PublicKeyCredentialHint#SECURITY_KEY} hint may be used to ask the
438
     * client to emphasize the option of registering with an external security key, or the {@link
439
     * PublicKeyCredentialHint#CLIENT_DEVICE} hint may be used to ask the client to emphasize the
440
     * option of registering a built-in passkey provider.
441
     *
442
     * <p>These hints are not requirements, and do not bind the user-agent, but may guide it in
443
     * providing the best experience by using contextual information about the request.
444
     *
445
     * <p>Hints MAY contradict preferences in {@link #getAuthenticatorSelection()}. When this
446
     * occurs, the hints take precedence.
447
     *
448
     * <p>This library does not take these hints into account in any way, other than passing them
449
     * through so they can be used in the argument to <code>navigator.credentials.create()</code> on
450
     * the client side.
451
     *
452
     * <p>The default is empty.
453
     *
454
     * @see PublicKeyCredentialHint
455
     * @see StartRegistrationOptions#getHints()
456
     * @see PublicKeyCredentialCreationOptions#getHints()
457
     * @see PublicKeyCredentialCreationOptionsBuilder#hints(String...)
458
     * @see PublicKeyCredentialCreationOptionsBuilder#hints(PublicKeyCredentialHint...)
459
     * @see <a
460
     *     href="https://www.w3.org/TR/2023/WD-webauthn-3-20230927/#dom-publickeycredentialcreationoptions-hints">PublicKeyCredentialCreationOptions.hints</a>
461
     * @see <a
462
     *     href="https://www.w3.org/TR/2023/WD-webauthn-3-20230927/#enumdef-publickeycredentialhints">§5.8.7.
463
     *     User-agent Hints Enumeration (enum PublicKeyCredentialHints)</a>
464
     */
465 1 1. hints : negated conditional → KILLED
    public PublicKeyCredentialCreationOptionsBuilder hints(@NonNull List<String> hints) {
466
      this.hints = hints;
467 1 1. hints : replaced return value with null for com/yubico/webauthn/data/PublicKeyCredentialCreationOptions$PublicKeyCredentialCreationOptionsBuilder::hints → KILLED
      return this;
468
    }
469
470
    /**
471
     * Intended for use by Relying Parties that wish to limit the creation of multiple credentials
472
     * for the same account on a single authenticator. The client is requested to return an error if
473
     * the new credential would be created on an authenticator that also contains one of the
474
     * credentials enumerated in this parameter.
475
     */
476
    public PublicKeyCredentialCreationOptionsBuilder excludeCredentials(
477
        Optional<Set<PublicKeyCredentialDescriptor>> excludeCredentials) {
478 1 1. excludeCredentials : replaced return value with null for com/yubico/webauthn/data/PublicKeyCredentialCreationOptions$PublicKeyCredentialCreationOptionsBuilder::excludeCredentials → KILLED
      return this.excludeCredentials(excludeCredentials.orElse(null));
479
    }
480
481
    /**
482
     * Intended for use by Relying Parties that wish to limit the creation of multiple credentials
483
     * for the same account on a single authenticator. The client is requested to return an error if
484
     * the new credential would be created on an authenticator that also contains one of the
485
     * credentials enumerated in this parameter.
486
     */
487
    public PublicKeyCredentialCreationOptionsBuilder excludeCredentials(
488
        Set<PublicKeyCredentialDescriptor> excludeCredentials) {
489
      this.excludeCredentials = excludeCredentials;
490 1 1. excludeCredentials : replaced return value with null for com/yubico/webauthn/data/PublicKeyCredentialCreationOptions$PublicKeyCredentialCreationOptionsBuilder::excludeCredentials → KILLED
      return this;
491
    }
492
493
    /**
494
     * Intended for use by Relying Parties that wish to select the appropriate authenticators to
495
     * participate in the create() operation.
496
     */
497
    public PublicKeyCredentialCreationOptionsBuilder authenticatorSelection(
498 1 1. authenticatorSelection : negated conditional → KILLED
        @NonNull Optional<AuthenticatorSelectionCriteria> authenticatorSelection) {
499 1 1. authenticatorSelection : replaced return value with null for com/yubico/webauthn/data/PublicKeyCredentialCreationOptions$PublicKeyCredentialCreationOptionsBuilder::authenticatorSelection → KILLED
      return this.authenticatorSelection(authenticatorSelection.orElse(null));
500
    }
501
502
    /**
503
     * Intended for use by Relying Parties that wish to select the appropriate authenticators to
504
     * participate in the create() operation.
505
     */
506
    public PublicKeyCredentialCreationOptionsBuilder authenticatorSelection(
507
        AuthenticatorSelectionCriteria authenticatorSelection) {
508
      this.authenticatorSelection = authenticatorSelection;
509 1 1. authenticatorSelection : replaced return value with null for com/yubico/webauthn/data/PublicKeyCredentialCreationOptions$PublicKeyCredentialCreationOptionsBuilder::authenticatorSelection → KILLED
      return this;
510
    }
511
  }
512
513
  /*
514
   * Essentially a copy of RelyingParty.filterAvailableAlgorithms(List) because that method and WebAuthnCodecs are not visible here.
515
   */
516
  private static List<PublicKeyCredentialParameters> filterAvailableAlgorithms(
517
      List<PublicKeyCredentialParameters> pubKeyCredParams) {
518 1 1. filterAvailableAlgorithms : replaced return value with Collections.emptyList for com/yubico/webauthn/data/PublicKeyCredentialCreationOptions::filterAvailableAlgorithms → KILLED
    return Collections.unmodifiableList(
519
        pubKeyCredParams.stream()
520
            .filter(
521
                param -> {
522
                  try {
523
                    switch (param.getAlg()) {
524
                      case EdDSA:
525
                        KeyFactory.getInstance("EdDSA");
526
                        break;
527
528
                      case ES256:
529
                      case ES384:
530
                      case ES512:
531
                        KeyFactory.getInstance("EC");
532
                        break;
533
534
                      case RS256:
535
                      case RS384:
536
                      case RS512:
537
                      case RS1:
538
                        KeyFactory.getInstance("RSA");
539
                        break;
540
541
                      default:
542
                        log.warn(
543
                            "Unknown algorithm: {}. Please file a bug report.", param.getAlg());
544
                    }
545
                  } catch (NoSuchAlgorithmException e) {
546
                    log.warn(
547
                        "Unsupported algorithm in PublicKeyCredentialCreationOptions.pubKeyCredParams: {}. No KeyFactory available; registrations with this key algorithm will fail. You may need to add a dependency and load a provider using java.security.Security.addProvider().",
548
                        param.getAlg());
549 1 1. lambda$filterAvailableAlgorithms$0 : replaced boolean return with true for com/yubico/webauthn/data/PublicKeyCredentialCreationOptions::lambda$filterAvailableAlgorithms$0 → KILLED
                    return false;
550
                  }
551
552
                  try {
553
                    switch (param.getAlg()) {
554
                      case EdDSA:
555
                        Signature.getInstance("EDDSA");
556
                        break;
557
558
                      case ES256:
559
                        Signature.getInstance("SHA256withECDSA");
560
                        break;
561
562
                      case ES384:
563
                        Signature.getInstance("SHA384withECDSA");
564
                        break;
565
566
                      case ES512:
567
                        Signature.getInstance("SHA512withECDSA");
568
                        break;
569
570
                      case RS256:
571
                        Signature.getInstance("SHA256withRSA");
572
                        break;
573
574
                      case RS384:
575
                        Signature.getInstance("SHA384withRSA");
576
                        break;
577
578
                      case RS512:
579
                        Signature.getInstance("SHA512withRSA");
580
                        break;
581
582
                      case RS1:
583
                        Signature.getInstance("SHA1withRSA");
584
                        break;
585
586
                      default:
587
                        log.warn(
588
                            "Unknown algorithm: {}. Please file a bug report.", param.getAlg());
589
                    }
590
                  } catch (NoSuchAlgorithmException e) {
591
                    log.warn(
592
                        "Unsupported algorithm in PublicKeyCredentialCreationOptions.pubKeyCredParams: {}. No Signature available; registrations with this key algorithm will fail. You may need to add a dependency and load a provider using java.security.Security.addProvider().",
593
                        param.getAlg());
594 1 1. lambda$filterAvailableAlgorithms$0 : replaced boolean return with true for com/yubico/webauthn/data/PublicKeyCredentialCreationOptions::lambda$filterAvailableAlgorithms$0 → NO_COVERAGE
                    return false;
595
                  }
596
597 1 1. lambda$filterAvailableAlgorithms$0 : replaced boolean return with false for com/yubico/webauthn/data/PublicKeyCredentialCreationOptions::lambda$filterAvailableAlgorithms$0 → KILLED
                  return true;
598
                })
599
            .collect(Collectors.toList()));
600
  }
601
}

Mutations

169

1.1
Location : <init>
Killed by : com.yubico.webauthn.data.PublicKeyCredentialCreationOptionsTest.doesNotLogWarningIfAllAlgorithmsAvailable(com.yubico.webauthn.data.PublicKeyCredentialCreationOptionsTest)
negated conditional → KILLED

170

1.1
Location : <init>
Killed by : com.yubico.webauthn.data.PublicKeyCredentialCreationOptionsTest.doesNotLogWarningIfAllAlgorithmsAvailable(com.yubico.webauthn.data.PublicKeyCredentialCreationOptionsTest)
negated conditional → KILLED

171

1.1
Location : <init>
Killed by : com.yubico.webauthn.data.PublicKeyCredentialCreationOptionsTest.doesNotLogWarningIfAllAlgorithmsAvailable(com.yubico.webauthn.data.PublicKeyCredentialCreationOptionsTest)
negated conditional → KILLED

172

1.1
Location : <init>
Killed by : com.yubico.webauthn.data.PublicKeyCredentialCreationOptionsTest.doesNotLogWarningIfAllAlgorithmsAvailable(com.yubico.webauthn.data.PublicKeyCredentialCreationOptionsTest)
negated conditional → KILLED

185

1.1
Location : <init>
Killed by : com.yubico.webauthn.data.PublicKeyCredentialCreationOptionsTest.doesNotLogWarningIfAllAlgorithmsAvailable(com.yubico.webauthn.data.PublicKeyCredentialCreationOptionsTest)
negated conditional → KILLED

187

1.1
Location : <init>
Killed by : com.yubico.webauthn.data.PublicKeyCredentialCreationOptionsTest.doesNotLogWarningIfAllAlgorithmsAvailable(com.yubico.webauthn.data.PublicKeyCredentialCreationOptionsTest)
negated conditional → KILLED

191

1.1
Location : <init>
Killed by : com.yubico.webauthn.RelyingPartyStartOperationSpec
negated conditional → KILLED

193

1.1
Location : <init>
Killed by : com.yubico.webauthn.RelyingPartyStartOperationSpec
negated conditional → KILLED

217

1.1
Location : toCredentialsCreateJson
Killed by : com.yubico.webauthn.RelyingPartyStartOperationSpec
replaced return value with "" for com/yubico/webauthn/data/PublicKeyCredentialCreationOptions::toCredentialsCreateJson → KILLED

237

1.1
Location : toJson
Killed by : com.yubico.webauthn.data.JsonIoSpec
replaced return value with "" for com/yubico/webauthn/data/PublicKeyCredentialCreationOptions::toJson → KILLED

254

1.1
Location : fromJson
Killed by : com.yubico.webauthn.data.JsonIoSpec
replaced return value with null for com/yubico/webauthn/data/PublicKeyCredentialCreationOptions::fromJson → KILLED

258

1.1
Location : getTimeout
Killed by : com.yubico.webauthn.RelyingPartyStartOperationSpec
replaced return value with Optional.empty for com/yubico/webauthn/data/PublicKeyCredentialCreationOptions::getTimeout → KILLED

262

1.1
Location : getExcludeCredentials
Killed by : com.yubico.webauthn.RelyingPartyStartOperationSpec
replaced return value with Optional.empty for com/yubico/webauthn/data/PublicKeyCredentialCreationOptions::getExcludeCredentials → KILLED

266

1.1
Location : getAuthenticatorSelection
Killed by : com.yubico.webauthn.RelyingPartyStartOperationSpec
replaced return value with Optional.empty for com/yubico/webauthn/data/PublicKeyCredentialCreationOptions::getAuthenticatorSelection → KILLED

270

1.1
Location : builder
Killed by : com.yubico.webauthn.data.PublicKeyCredentialCreationOptionsTest.doesNotLogWarningIfAllAlgorithmsAvailable(com.yubico.webauthn.data.PublicKeyCredentialCreationOptionsTest)
replaced return value with null for com/yubico/webauthn/data/PublicKeyCredentialCreationOptions::builder → KILLED

290

1.1
Location : rp
Killed by : com.yubico.webauthn.data.PublicKeyCredentialCreationOptionsTest.doesNotLogWarningIfAllAlgorithmsAvailable(com.yubico.webauthn.data.PublicKeyCredentialCreationOptionsTest)
replaced return value with null for com/yubico/webauthn/data/PublicKeyCredentialCreationOptions$PublicKeyCredentialCreationOptionsBuilder$MandatoryStages::rp → KILLED

302

1.1
Location : user
Killed by : com.yubico.webauthn.data.PublicKeyCredentialCreationOptionsTest.doesNotLogWarningIfAllAlgorithmsAvailable(com.yubico.webauthn.data.PublicKeyCredentialCreationOptionsTest)
replaced return value with null for com/yubico/webauthn/data/PublicKeyCredentialCreationOptions$PublicKeyCredentialCreationOptionsBuilder$MandatoryStages$Step2::user → KILLED

315

1.1
Location : challenge
Killed by : com.yubico.webauthn.data.PublicKeyCredentialCreationOptionsTest.doesNotLogWarningIfAllAlgorithmsAvailable(com.yubico.webauthn.data.PublicKeyCredentialCreationOptionsTest)
replaced return value with null for com/yubico/webauthn/data/PublicKeyCredentialCreationOptions$PublicKeyCredentialCreationOptionsBuilder$MandatoryStages$Step3::challenge → KILLED

328

1.1
Location : pubKeyCredParams
Killed by : com.yubico.webauthn.data.PublicKeyCredentialCreationOptionsTest.doesNotLogWarningIfAllAlgorithmsAvailable(com.yubico.webauthn.data.PublicKeyCredentialCreationOptionsTest)
replaced return value with null for com/yubico/webauthn/data/PublicKeyCredentialCreationOptions$PublicKeyCredentialCreationOptionsBuilder$MandatoryStages$Step4::pubKeyCredParams → KILLED

337

1.1
Location : timeout
Killed by : com.yubico.webauthn.RelyingPartyTest.filtersAlgorithmsToThoseAvailable(com.yubico.webauthn.RelyingPartyTest)
negated conditional → KILLED

339

1.1
Location : timeout
Killed by : com.yubico.webauthn.RelyingPartyTest.filtersAlgorithmsToThoseAvailable(com.yubico.webauthn.RelyingPartyTest)
replaced return value with null for com/yubico/webauthn/data/PublicKeyCredentialCreationOptions$PublicKeyCredentialCreationOptionsBuilder::timeout → KILLED

347

1.1
Location : timeout
Killed by : com.yubico.webauthn.data.BuildersSpec
replaced return value with null for com/yubico/webauthn/data/PublicKeyCredentialCreationOptions$PublicKeyCredentialCreationOptionsBuilder::timeout → KILLED

355

1.1
Location : timeout
Killed by : none
replaced return value with null for com/yubico/webauthn/data/PublicKeyCredentialCreationOptions$PublicKeyCredentialCreationOptionsBuilder::timeout → NO_COVERAGE

390

1.1
Location : hints
Killed by : com.yubico.webauthn.data.BuildersSpec
negated conditional → KILLED

392

1.1
Location : hints
Killed by : none
replaced return value with null for com/yubico/webauthn/data/PublicKeyCredentialCreationOptions$PublicKeyCredentialCreationOptionsBuilder::hints → SURVIVED

428

1.1
Location : hints
Killed by : com.yubico.webauthn.data.JsonIoSpec
negated conditional → KILLED

429

1.1
Location : hints
Killed by : none
replaced return value with null for com/yubico/webauthn/data/PublicKeyCredentialCreationOptions$PublicKeyCredentialCreationOptionsBuilder::hints → SURVIVED

430

1.1
Location : lambda$hints$0
Killed by : com.yubico.webauthn.data.BuildersSpec
replaced return value with null for com/yubico/webauthn/data/PublicKeyCredentialCreationOptions$PublicKeyCredentialCreationOptionsBuilder::lambda$hints$0 → KILLED

465

1.1
Location : hints
Killed by : com.yubico.webauthn.RelyingPartyTest.filtersAlgorithmsToThoseAvailable(com.yubico.webauthn.RelyingPartyTest)
negated conditional → KILLED

467

1.1
Location : hints
Killed by : com.yubico.webauthn.RelyingPartyTest.filtersAlgorithmsToThoseAvailable(com.yubico.webauthn.RelyingPartyTest)
replaced return value with null for com/yubico/webauthn/data/PublicKeyCredentialCreationOptions$PublicKeyCredentialCreationOptionsBuilder::hints → KILLED

478

1.1
Location : excludeCredentials
Killed by : com.yubico.webauthn.data.BuildersSpec
replaced return value with null for com/yubico/webauthn/data/PublicKeyCredentialCreationOptions$PublicKeyCredentialCreationOptionsBuilder::excludeCredentials → KILLED

490

1.1
Location : excludeCredentials
Killed by : com.yubico.webauthn.RelyingPartyTest.filtersAlgorithmsToThoseAvailable(com.yubico.webauthn.RelyingPartyTest)
replaced return value with null for com/yubico/webauthn/data/PublicKeyCredentialCreationOptions$PublicKeyCredentialCreationOptionsBuilder::excludeCredentials → KILLED

498

1.1
Location : authenticatorSelection
Killed by : com.yubico.webauthn.RelyingPartyTest.filtersAlgorithmsToThoseAvailable(com.yubico.webauthn.RelyingPartyTest)
negated conditional → KILLED

499

1.1
Location : authenticatorSelection
Killed by : com.yubico.webauthn.RelyingPartyTest.filtersAlgorithmsToThoseAvailable(com.yubico.webauthn.RelyingPartyTest)
replaced return value with null for com/yubico/webauthn/data/PublicKeyCredentialCreationOptions$PublicKeyCredentialCreationOptionsBuilder::authenticatorSelection → KILLED

509

1.1
Location : authenticatorSelection
Killed by : com.yubico.webauthn.RelyingPartyTest.filtersAlgorithmsToThoseAvailable(com.yubico.webauthn.RelyingPartyTest)
replaced return value with null for com/yubico/webauthn/data/PublicKeyCredentialCreationOptions$PublicKeyCredentialCreationOptionsBuilder::authenticatorSelection → KILLED

518

1.1
Location : filterAvailableAlgorithms
Killed by : com.yubico.webauthn.data.PublicKeyCredentialCreationOptionsTest.filtersAlgorithmsToThoseAvailable(com.yubico.webauthn.data.PublicKeyCredentialCreationOptionsTest)
replaced return value with Collections.emptyList for com/yubico/webauthn/data/PublicKeyCredentialCreationOptions::filterAvailableAlgorithms → KILLED

549

1.1
Location : lambda$filterAvailableAlgorithms$0
Killed by : com.yubico.webauthn.data.PublicKeyCredentialCreationOptionsTest.filtersAlgorithmsToThoseAvailable(com.yubico.webauthn.data.PublicKeyCredentialCreationOptionsTest)
replaced boolean return with true for com/yubico/webauthn/data/PublicKeyCredentialCreationOptions::lambda$filterAvailableAlgorithms$0 → KILLED

594

1.1
Location : lambda$filterAvailableAlgorithms$0
Killed by : none
replaced boolean return with true for com/yubico/webauthn/data/PublicKeyCredentialCreationOptions::lambda$filterAvailableAlgorithms$0 → NO_COVERAGE

597

1.1
Location : lambda$filterAvailableAlgorithms$0
Killed by : com.yubico.webauthn.data.PublicKeyCredentialCreationOptionsTest.filtersAlgorithmsToThoseAvailable(com.yubico.webauthn.data.PublicKeyCredentialCreationOptionsTest)
replaced boolean return with false for com/yubico/webauthn/data/PublicKeyCredentialCreationOptions::lambda$filterAvailableAlgorithms$0 → KILLED

Active mutators

Tests examined


Report generated by PIT 1.15.0