RelyingParty.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;
26
27
import com.yubico.internal.util.CollectionUtil;
28
import com.yubico.internal.util.OptionalUtil;
29
import com.yubico.webauthn.attestation.AttestationTrustSource;
30
import com.yubico.webauthn.data.AssertionExtensionInputs;
31
import com.yubico.webauthn.data.AttestationConveyancePreference;
32
import com.yubico.webauthn.data.AuthenticatorData;
33
import com.yubico.webauthn.data.ByteArray;
34
import com.yubico.webauthn.data.CollectedClientData;
35
import com.yubico.webauthn.data.PublicKeyCredentialCreationOptions;
36
import com.yubico.webauthn.data.PublicKeyCredentialCreationOptions.PublicKeyCredentialCreationOptionsBuilder;
37
import com.yubico.webauthn.data.PublicKeyCredentialParameters;
38
import com.yubico.webauthn.data.PublicKeyCredentialRequestOptions;
39
import com.yubico.webauthn.data.PublicKeyCredentialRequestOptions.PublicKeyCredentialRequestOptionsBuilder;
40
import com.yubico.webauthn.data.RegistrationExtensionInputs;
41
import com.yubico.webauthn.data.RelyingPartyIdentity;
42
import com.yubico.webauthn.exception.AssertionFailedException;
43
import com.yubico.webauthn.exception.InvalidSignatureCountException;
44
import com.yubico.webauthn.exception.RegistrationFailedException;
45
import com.yubico.webauthn.extension.appid.AppId;
46
import java.net.MalformedURLException;
47
import java.net.URL;
48
import java.security.KeyFactory;
49
import java.security.NoSuchAlgorithmException;
50
import java.security.SecureRandom;
51
import java.security.Signature;
52
import java.time.Clock;
53
import java.util.ArrayList;
54
import java.util.Arrays;
55
import java.util.Collections;
56
import java.util.List;
57
import java.util.Optional;
58
import java.util.Set;
59
import java.util.stream.Collectors;
60
import lombok.Builder;
61
import lombok.NonNull;
62
import lombok.Value;
63
import lombok.extern.slf4j.Slf4j;
64
65
/**
66
 * Encapsulates the four basic Web Authentication operations - start/finish registration,
67
 * start/finish authentication - along with overall operational settings for them.
68
 *
69
 * <p>This class has no mutable state. An instance of this class may therefore be thought of as a
70
 * container for specialized versions (function closures) of these four operations rather than a
71
 * stateful object.
72
 */
73
@Slf4j
74
@Builder(toBuilder = true)
75
@Value
76
public class RelyingParty {
77
78
  private static final SecureRandom random = new SecureRandom();
79
80
  /**
81
   * The {@link RelyingPartyIdentity} that will be set as the {@link
82
   * PublicKeyCredentialCreationOptions#getRp() rp} parameter when initiating registration
83
   * operations, and which {@link AuthenticatorData#getRpIdHash()} will be compared against. This is
84
   * a required parameter.
85
   *
86
   * <p>A successful registration or authentication operation requires {@link
87
   * AuthenticatorData#getRpIdHash()} to exactly equal the SHA-256 hash of this member's {@link
88
   * RelyingPartyIdentity#getId() id} member. Alternatively, it may instead equal the SHA-256 hash
89
   * of {@link #getAppId() appId} if the latter is present.
90
   *
91
   * @see #startRegistration(StartRegistrationOptions)
92
   * @see PublicKeyCredentialCreationOptions
93
   */
94
  @NonNull private final RelyingPartyIdentity identity;
95
96
  /**
97
   * The allowed origins that returned authenticator responses will be compared against.
98
   *
99
   * <p>The default is the set containing only the string <code>
100
   * "https://" + {@link #getIdentity()}.getId()</code>.
101
   *
102
   * <p>If {@link RelyingPartyBuilder#allowOriginPort(boolean) allowOriginPort} and {@link
103
   * RelyingPartyBuilder#allowOriginSubdomain(boolean) allowOriginSubdomain} are both <code>false
104
   * </code> (the default), then a successful registration or authentication operation requires
105
   * {@link CollectedClientData#getOrigin()} to exactly equal one of these values.
106
   *
107
   * <p>If {@link RelyingPartyBuilder#allowOriginPort(boolean) allowOriginPort} is <code>true</code>
108
   * , then the above rule is relaxed to allow any port number in {@link
109
   * CollectedClientData#getOrigin()}, regardless of any port specified.
110
   *
111
   * <p>If {@link RelyingPartyBuilder#allowOriginSubdomain(boolean) allowOriginSubdomain} is <code>
112
   * true</code>, then the above rule is relaxed to allow any subdomain, of any depth, of any of
113
   * these values.
114
   *
115
   * <p>For either of the above relaxations to take effect, both the allowed origin and the client
116
   * data origin must be valid URLs. Origins that are not valid URLs are matched only by exact
117
   * string equality.
118
   *
119
   * @see #getIdentity()
120
   */
121
  @NonNull private final Set<String> origins;
122
123
  /**
124
   * An abstract database which can look up credentials, usernames and user handles from usernames,
125
   * user handles and credential IDs. This is a required parameter.
126
   *
127
   * <p>This is used to look up:
128
   *
129
   * <ul>
130
   *   <li>the user handle for a user logging in via user name
131
   *   <li>the user name for a user logging in via user handle
132
   *   <li>the credential IDs to include in {@link
133
   *       PublicKeyCredentialCreationOptions#getExcludeCredentials()}
134
   *   <li>the credential IDs to include in {@link
135
   *       PublicKeyCredentialRequestOptions#getAllowCredentials()}
136
   *   <li>that the correct user owns the credential when verifying an assertion
137
   *   <li>the public key to use to verify an assertion
138
   *   <li>the stored signature counter when verifying an assertion
139
   * </ul>
140
   */
141
  @NonNull private final CredentialRepository credentialRepository;
142
143
  /**
144
   * The extension input to set for the <code>appid</code> and <code>appidExclude</code> extensions.
145
   *
146
   * <p>You do not need this extension if you have not previously supported U2F. Its purpose is to
147
   * make already-registered U2F credentials forward-compatible with the WebAuthn API. It is not
148
   * needed for new registrations, even of U2F authenticators.
149
   *
150
   * <p>If this member is set, {@link #startAssertion(StartAssertionOptions) startAssertion} will
151
   * automatically set the <code>appid</code> extension input, and {@link
152
   * #finishAssertion(FinishAssertionOptions) finishAssertion} will adjust its verification logic to
153
   * also accept this AppID as an alternative to the RP ID. Likewise, {@link
154
   * #startRegistration(StartRegistrationOptions)} startRegistration} will automatically set the
155
   * <code>appidExclude</code> extension input.
156
   *
157
   * <p>By default, this is not set.
158
   *
159
   * @see AssertionExtensionInputs#getAppid()
160
   * @see RegistrationExtensionInputs#getAppidExclude()
161
   * @see <a href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#sctn-appid-extension">§10.1.
162
   *     FIDO AppID Extension (appid)</a>
163
   * @see <a
164
   *     href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#sctn-appid-exclude-extension">§10.2.
165
   *     FIDO AppID Exclusion Extension (appidExclude)</a>
166
   */
167
  @NonNull private final Optional<AppId> appId;
168
169
  /**
170
   * The argument for the {@link PublicKeyCredentialCreationOptions#getAttestation() attestation}
171
   * parameter in registration operations.
172
   *
173
   * <p>Unless your application has a concrete policy for authenticator attestation, it is
174
   * recommended to leave this parameter undefined.
175
   *
176
   * <p>If you set this, you may want to explicitly set {@link
177
   * RelyingPartyBuilder#allowUntrustedAttestation(boolean) allowUntrustedAttestation} and {@link
178
   * RelyingPartyBuilder#attestationTrustSource(AttestationTrustSource) attestationTrustSource} too.
179
   *
180
   * <p>By default, this is not set.
181
   *
182
   * @see PublicKeyCredentialCreationOptions#getAttestation()
183
   * @see <a href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#sctn-attestation">§6.4.
184
   *     Attestation</a>
185
   */
186
  @NonNull private final Optional<AttestationConveyancePreference> attestationConveyancePreference;
187
188
  /**
189
   * An {@link AttestationTrustSource} instance to use for looking up trust roots for authenticator
190
   * attestation. This matters only if {@link #getAttestationConveyancePreference()} is non-empty
191
   * and not set to {@link AttestationConveyancePreference#NONE}.
192
   *
193
   * <p>By default, this is not set.
194
   *
195
   * @see PublicKeyCredentialCreationOptions#getAttestation()
196
   * @see <a href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#sctn-attestation">§6.4.
197
   *     Attestation</a>
198
   */
199
  @NonNull private final Optional<AttestationTrustSource> attestationTrustSource;
200
201
  /**
202
   * The argument for the {@link PublicKeyCredentialCreationOptions#getPubKeyCredParams()
203
   * pubKeyCredParams} parameter in registration operations.
204
   *
205
   * <p>This is a list of acceptable public key algorithms and their parameters, ordered from most
206
   * to least preferred.
207
   *
208
   * <p>The default is the following list, in order:
209
   *
210
   * <ol>
211
   *   <li>{@link com.yubico.webauthn.data.PublicKeyCredentialParameters#ES256 ES256}
212
   *   <li>{@link com.yubico.webauthn.data.PublicKeyCredentialParameters#EdDSA EdDSA}
213
   *   <li>{@link com.yubico.webauthn.data.PublicKeyCredentialParameters#ES384 ES384}
214
   *   <li>{@link com.yubico.webauthn.data.PublicKeyCredentialParameters#ES512 ES512}
215
   *   <li>{@link com.yubico.webauthn.data.PublicKeyCredentialParameters#Ed448 Ed448}
216
   *   <li>{@link com.yubico.webauthn.data.PublicKeyCredentialParameters#RS256 RS256}
217
   *   <li>{@link com.yubico.webauthn.data.PublicKeyCredentialParameters#RS384 RS384}
218
   *   <li>{@link com.yubico.webauthn.data.PublicKeyCredentialParameters#RS512 RS512}
219
   *   <li>{@link com.yubico.webauthn.data.PublicKeyCredentialParameters#ML_DSA_44 ML_DSA_44}
220
   *   <li>{@link com.yubico.webauthn.data.PublicKeyCredentialParameters#ML_DSA_65 ML_DSA_65}
221
   *   <li>{@link com.yubico.webauthn.data.PublicKeyCredentialParameters#ML_DSA_87 ML_DSA_87}
222
   * </ol>
223
   *
224
   * @since 0.2.0
225
   * @see PublicKeyCredentialCreationOptions#getAttestation()
226
   * @see <a href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#sctn-attestation">§6.4.
227
   *     Attestation</a>
228
   */
229
  @Builder.Default @NonNull
230
  private final List<PublicKeyCredentialParameters> preferredPubkeyParams =
231
      Collections.unmodifiableList(
232
          Arrays.asList(
233
              PublicKeyCredentialParameters.ES256,
234
              PublicKeyCredentialParameters.EdDSA,
235
              PublicKeyCredentialParameters.ES384,
236
              PublicKeyCredentialParameters.ES512,
237
              PublicKeyCredentialParameters.Ed448,
238
              PublicKeyCredentialParameters.RS256,
239
              PublicKeyCredentialParameters.RS384,
240
              PublicKeyCredentialParameters.RS512,
241
              PublicKeyCredentialParameters.ML_DSA_44,
242
              PublicKeyCredentialParameters.ML_DSA_65,
243
              PublicKeyCredentialParameters.ML_DSA_87));
244
245
  /**
246
   * If <code>true</code>, the origin matching rule is relaxed to allow any port number.
247
   *
248
   * <p>The default is <code>false</code>.
249
   *
250
   * <p>Examples with <code>
251
   * origins: ["https://example.org", "https://accounts.example.org", "https://acme.com:8443"]
252
   * </code>
253
   *
254
   * <ul>
255
   *   <li>
256
   *       <p><code>allowOriginPort: false</code>
257
   *       <p>Accepted:
258
   *       <ul>
259
   *         <li><code>https://example.org</code>
260
   *         <li><code>https://accounts.example.org</code>
261
   *         <li><code>https://acme.com:8443</code>
262
   *       </ul>
263
   *       <p>Rejected:
264
   *       <ul>
265
   *         <li><code>https://example.org:8443</code>
266
   *         <li><code>https://shop.example.org</code>
267
   *         <li><code>https://acme.com</code>
268
   *         <li><code>https://acme.com:9000</code>
269
   *       </ul>
270
   *   <li>
271
   *       <p><code>allowOriginPort: true</code>
272
   *       <p>Accepted:
273
   *       <ul>
274
   *         <li><code>https://example.org</code>
275
   *         <li><code>https://example.org:8443</code>
276
   *         <li><code>https://accounts.example.org</code>
277
   *         <li><code>https://acme.com</code>
278
   *         <li><code>https://acme.com:8443</code>
279
   *         <li><code>https://acme.com:9000</code>
280
   *       </ul>
281
   *       <p>Rejected:
282
   *       <ul>
283
   *         <li><code>https://shop.example.org</code>
284
   *       </ul>
285
   * </ul>
286
   */
287
  @Builder.Default private final boolean allowOriginPort = false;
288
289
  /**
290
   * If <code>true</code>, the origin matching rule is relaxed to allow any subdomain, of any depth,
291
   * of the values of {@link RelyingPartyBuilder#origins(Set) origins}.
292
   *
293
   * <p>Please see <a
294
   * href="https://www.w3.org/TR/2023/WD-webauthn-3-20230927/#sctn-code-injection">Security
295
   * Considerations: Code injection attacks</a> for discussion of the risks in setting this to
296
   * <code>true</code>.
297
   *
298
   * <p>The default is <code>false</code>.
299
   *
300
   * <p>Examples with <code>origins: ["https://example.org", "https://acme.com:8443"]</code>
301
   *
302
   * <ul>
303
   *   <li>
304
   *       <p><code>allowOriginSubdomain: false</code>
305
   *       <p>Accepted:
306
   *       <ul>
307
   *         <li><code>https://example.org</code>
308
   *         <li><code>https://acme.com:8443</code>
309
   *       </ul>
310
   *       <p>Rejected:
311
   *       <ul>
312
   *         <li><code>https://example.org:8443</code>
313
   *         <li><code>https://accounts.example.org</code>
314
   *         <li><code>https://acme.com</code>
315
   *         <li><code>https://eu.shop.acme.com:8443</code>
316
   *       </ul>
317
   *   <li>
318
   *       <p><code>allowOriginSubdomain: true</code>
319
   *       <p>Accepted:
320
   *       <ul>
321
   *         <li><code>https://example.org</code>
322
   *         <li><code>https://accounts.example.org</code>
323
   *         <li><code>https://acme.com:8443</code>
324
   *         <li><code>https://eu.shop.acme.com:8443</code>
325
   *       </ul>
326
   *       <p>Rejected:
327
   *       <ul>
328
   *         <li><code>https://example.org:8443</code>
329
   *         <li><code>https://acme.com</code>
330
   *       </ul>
331
   * </ul>
332
   *
333
   * @see <a href="https://www.w3.org/TR/2023/WD-webauthn-3-20230927/#sctn-code-injection">§13.4.8.
334
   *     Code injection attacks</a>
335
   */
336
  @Builder.Default private final boolean allowOriginSubdomain = false;
337
338
  /**
339
   * If <code>false</code>, {@link #finishRegistration(FinishRegistrationOptions)
340
   * finishRegistration} will only allow registrations where the attestation signature can be linked
341
   * to a trusted attestation root. This excludes none attestation, and self attestation unless the
342
   * self attestation key is explicitly trusted.
343
   *
344
   * <p>Regardless of the value of this option, invalid attestation statements of supported formats
345
   * will always be rejected. For example, a "packed" attestation statement with an invalid
346
   * signature will be rejected even if this option is set to <code>true</code>.
347
   *
348
   * <p>The default is <code>true</code>.
349
   */
350
  @Builder.Default private final boolean allowUntrustedAttestation = true;
351
352
  /**
353
   * If <code>true</code>, {@link #finishAssertion(FinishAssertionOptions) finishAssertion} will
354
   * succeed only if the {@link AuthenticatorData#getSignatureCounter() signature counter value} in
355
   * the response is strictly greater than the {@link RegisteredCredential#getSignatureCount()
356
   * stored signature counter value}, or if both counters are exactly zero.
357
   *
358
   * <p>The default is <code>true</code>.
359
   */
360
  @Builder.Default private final boolean validateSignatureCounter = true;
361
362
  /**
363
   * A {@link Clock} which will be used to tell the current time while verifying attestation
364
   * certificate chains.
365
   *
366
   * <p>This is intended primarily for testing, and relevant only if {@link
367
   * RelyingPartyBuilder#attestationTrustSource(AttestationTrustSource)} is set.
368
   *
369
   * <p>The default is <code>Clock.systemUTC()</code>.
370
   */
371
  @Builder.Default @NonNull private final Clock clock = Clock.systemUTC();
372
373
  @Builder
374
  private RelyingParty(
375
      @NonNull RelyingPartyIdentity identity,
376
      Set<String> origins,
377
      @NonNull CredentialRepository credentialRepository,
378
      @NonNull Optional<AppId> appId,
379
      @NonNull Optional<AttestationConveyancePreference> attestationConveyancePreference,
380
      @NonNull Optional<AttestationTrustSource> attestationTrustSource,
381
      List<PublicKeyCredentialParameters> preferredPubkeyParams,
382
      boolean allowOriginPort,
383
      boolean allowOriginSubdomain,
384
      boolean allowUntrustedAttestation,
385
      boolean validateSignatureCounter,
386
      Clock clock) {
387
    this.identity = identity;
388
    this.origins =
389 1 1. <init> : negated conditional → KILLED
        origins != null
390
            ? CollectionUtil.immutableSet(origins)
391
            : Collections.singleton("https://" + identity.getId());
392
393
    for (String origin : this.origins) {
394
      try {
395
        new URL(origin);
396
      } catch (MalformedURLException e) {
397
        log.warn(
398
            "Allowed origin is not a valid URL, it will match only by exact string equality: {}",
399
            origin);
400
      }
401
    }
402
403
    this.credentialRepository = credentialRepository;
404
    this.appId = appId;
405
    this.attestationConveyancePreference = attestationConveyancePreference;
406
    this.attestationTrustSource = attestationTrustSource;
407
    this.preferredPubkeyParams = filterAvailableAlgorithms(preferredPubkeyParams);
408
    this.allowOriginPort = allowOriginPort;
409
    this.allowOriginSubdomain = allowOriginSubdomain;
410
    this.allowUntrustedAttestation = allowUntrustedAttestation;
411
    this.validateSignatureCounter = validateSignatureCounter;
412
    this.clock = clock;
413
  }
414
415
  private static ByteArray generateChallenge() {
416
    byte[] bytes = new byte[32];
417 1 1. generateChallenge : removed call to java/security/SecureRandom::nextBytes → KILLED
    random.nextBytes(bytes);
418 1 1. generateChallenge : replaced return value with null for com/yubico/webauthn/RelyingParty::generateChallenge → KILLED
    return new ByteArray(bytes);
419
  }
420
421
  /**
422
   * Filter <code>pubKeyCredParams</code> to only contain algorithms with a {@link KeyFactory} and a
423
   * {@link Signature} available, and log a warning for every unsupported algorithm.
424
   *
425
   * @return a new {@link List} containing only the algorithms supported in the current JCA context.
426
   */
427
  static List<PublicKeyCredentialParameters> filterAvailableAlgorithms(
428
      List<PublicKeyCredentialParameters> pubKeyCredParams) {
429 1 1. filterAvailableAlgorithms : replaced return value with Collections.emptyList for com/yubico/webauthn/RelyingParty::filterAvailableAlgorithms → KILLED
    return Collections.unmodifiableList(
430
        pubKeyCredParams.stream()
431
            .filter(
432
                param -> {
433
                  try {
434
                    switch (param.getAlg()) {
435
                      case EdDSA:
436
                      case Ed25519:
437
                        KeyFactory.getInstance("Ed25519");
438
                        break;
439
440
                      case Ed448:
441
                        KeyFactory.getInstance("Ed448");
442
                        break;
443
444
                      case ES256:
445
                      case ES384:
446
                      case ES512:
447
                        KeyFactory.getInstance("EC");
448
                        break;
449
450
                      case RS256:
451
                      case RS384:
452
                      case RS512:
453
                      case RS1:
454
                        KeyFactory.getInstance("RSA");
455
                        break;
456
457
                      case ML_DSA_44:
458
                        KeyFactory.getInstance("ML-DSA-44");
459
                        break;
460
461
                      case ML_DSA_65:
462
                        KeyFactory.getInstance("ML-DSA-65");
463
                        break;
464
465
                      case ML_DSA_87:
466
                        KeyFactory.getInstance("ML-DSA-87");
467
                        break;
468
469
                      default:
470
                        log.warn(
471
                            "Unknown algorithm: {}. Please file a bug report.", param.getAlg());
472
                    }
473
                  } catch (NoSuchAlgorithmException e) {
474
                    log.warn(
475
                        "Unsupported algorithm in RelyingParty.preferredPubkeyParams: {}. 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().",
476
                        param.getAlg());
477 1 1. lambda$filterAvailableAlgorithms$0 : replaced boolean return with true for com/yubico/webauthn/RelyingParty::lambda$filterAvailableAlgorithms$0 → KILLED
                    return false;
478
                  }
479
480
                  final String signatureAlgName;
481
                  try {
482
                    signatureAlgName = WebAuthnCodecs.getJavaAlgorithmName(param.getAlg());
483
                  } catch (IllegalArgumentException e) {
484
                    log.warn("Unknown algorithm: {}. Please file a bug report.", param.getAlg());
485 1 1. lambda$filterAvailableAlgorithms$0 : replaced boolean return with true for com/yubico/webauthn/RelyingParty::lambda$filterAvailableAlgorithms$0 → NO_COVERAGE
                    return false;
486
                  }
487
488
                  try {
489
                    Signature.getInstance(signatureAlgName);
490
                  } catch (NoSuchAlgorithmException e) {
491
                    log.warn(
492
                        "Unsupported algorithm in RelyingParty.preferredPubkeyParams: {}. 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().",
493
                        param.getAlg());
494 1 1. lambda$filterAvailableAlgorithms$0 : replaced boolean return with true for com/yubico/webauthn/RelyingParty::lambda$filterAvailableAlgorithms$0 → NO_COVERAGE
                    return false;
495
                  }
496
497 1 1. lambda$filterAvailableAlgorithms$0 : replaced boolean return with false for com/yubico/webauthn/RelyingParty::lambda$filterAvailableAlgorithms$0 → KILLED
                  return true;
498
                })
499
            .collect(Collectors.toList()));
500
  }
501
502
  public PublicKeyCredentialCreationOptions startRegistration(
503
      StartRegistrationOptions startRegistrationOptions) {
504
    PublicKeyCredentialCreationOptionsBuilder builder =
505
        PublicKeyCredentialCreationOptions.builder()
506
            .rp(identity)
507
            .user(startRegistrationOptions.getUser())
508
            .challenge(generateChallenge())
509
            .pubKeyCredParams(preferredPubkeyParams)
510
            .excludeCredentials(
511
                credentialRepository.getCredentialIdsForUsername(
512
                    startRegistrationOptions.getUser().getName()))
513
            .authenticatorSelection(startRegistrationOptions.getAuthenticatorSelection())
514
            .extensions(
515
                startRegistrationOptions
516
                    .getExtensions()
517
                    .merge(
518
                        RegistrationExtensionInputs.builder()
519
                            .appidExclude(appId)
520
                            .credProps()
521
                            .build()))
522
            .timeout(startRegistrationOptions.getTimeout())
523
            .hints(startRegistrationOptions.getHints());
524 1 1. startRegistration : removed call to java/util/Optional::ifPresent → KILLED
    attestationConveyancePreference.ifPresent(builder::attestation);
525 1 1. startRegistration : replaced return value with null for com/yubico/webauthn/RelyingParty::startRegistration → KILLED
    return builder.build();
526
  }
527
528
  public RegistrationResult finishRegistration(FinishRegistrationOptions finishRegistrationOptions)
529
      throws RegistrationFailedException {
530
    try {
531 1 1. finishRegistration : replaced return value with null for com/yubico/webauthn/RelyingParty::finishRegistration → KILLED
      return _finishRegistration(finishRegistrationOptions).run();
532
    } catch (IllegalArgumentException e) {
533
      throw new RegistrationFailedException(e);
534
    }
535
  }
536
537
  /**
538
   * This method is NOT part of the public API.
539
   *
540
   * <p>This method is called internally by {@link #finishRegistration(FinishRegistrationOptions)}.
541
   * It is a separate method to facilitate testing; users should call {@link
542
   * #finishRegistration(FinishRegistrationOptions)} instead of this method.
543
   */
544
  FinishRegistrationSteps _finishRegistration(FinishRegistrationOptions options) {
545 1 1. _finishRegistration : replaced return value with null for com/yubico/webauthn/RelyingParty::_finishRegistration → KILLED
    return FinishRegistrationSteps.fromV1(this, options);
546
  }
547
548
  public AssertionRequest startAssertion(StartAssertionOptions startAssertionOptions) {
549
    PublicKeyCredentialRequestOptionsBuilder pkcro =
550
        PublicKeyCredentialRequestOptions.builder()
551
            .challenge(generateChallenge())
552
            .rpId(identity.getId())
553
            .allowCredentials(
554
                OptionalUtil.orElseOptional(
555
                        startAssertionOptions.getUsername(),
556
                        () ->
557 1 1. lambda$startAssertion$1 : replaced return value with Optional.empty for com/yubico/webauthn/RelyingParty::lambda$startAssertion$1 → KILLED
                            startAssertionOptions
558
                                .getUserHandle()
559
                                .flatMap(credentialRepository::getUsernameForUserHandle))
560
                    .map(
561
                        un ->
562 1 1. lambda$startAssertion$2 : replaced return value with Collections.emptyList for com/yubico/webauthn/RelyingParty::lambda$startAssertion$2 → KILLED
                            new ArrayList<>(credentialRepository.getCredentialIdsForUsername(un))))
563
            .extensions(
564
                startAssertionOptions
565
                    .getExtensions()
566
                    .merge(startAssertionOptions.getExtensions().toBuilder().appid(appId).build()))
567
            .timeout(startAssertionOptions.getTimeout())
568
            .hints(startAssertionOptions.getHints());
569
570 1 1. startAssertion : removed call to java/util/Optional::ifPresent → KILLED
    startAssertionOptions.getUserVerification().ifPresent(pkcro::userVerification);
571
572 1 1. startAssertion : replaced return value with null for com/yubico/webauthn/RelyingParty::startAssertion → KILLED
    return AssertionRequest.builder()
573
        .publicKeyCredentialRequestOptions(pkcro.build())
574
        .username(startAssertionOptions.getUsername())
575
        .userHandle(startAssertionOptions.getUserHandle())
576
        .build();
577
  }
578
579
  /**
580
   * @throws InvalidSignatureCountException if {@link
581
   *     RelyingPartyBuilder#validateSignatureCounter(boolean) validateSignatureCounter} is <code>
582
   *     true</code>, the {@link AuthenticatorData#getSignatureCounter() signature count} in the
583
   *     response is less than or equal to the {@link RegisteredCredential#getSignatureCount()
584
   *     stored signature count}, and at least one of the signature count values is nonzero.
585
   * @throws AssertionFailedException if validation fails for any other reason.
586
   */
587
  public AssertionResult finishAssertion(FinishAssertionOptions finishAssertionOptions)
588
      throws AssertionFailedException {
589
    try {
590 1 1. finishAssertion : replaced return value with null for com/yubico/webauthn/RelyingParty::finishAssertion → KILLED
      return _finishAssertion(finishAssertionOptions).run();
591
    } catch (IllegalArgumentException e) {
592
      throw new AssertionFailedException(e);
593
    }
594
  }
595
596
  /**
597
   * This method is NOT part of the public API.
598
   *
599
   * <p>This method is called internally by {@link #finishAssertion(FinishAssertionOptions)}. It is
600
   * a separate method to facilitate testing; users should call {@link
601
   * #finishAssertion(FinishAssertionOptions)} instead of this method.
602
   */
603
  FinishAssertionSteps<RegisteredCredential> _finishAssertion(FinishAssertionOptions options) {
604 1 1. _finishAssertion : replaced return value with null for com/yubico/webauthn/RelyingParty::_finishAssertion → KILLED
    return FinishAssertionSteps.fromV1(this, options);
605
  }
606
607
  public static RelyingPartyBuilder.MandatoryStages builder() {
608 1 1. builder : replaced return value with null for com/yubico/webauthn/RelyingParty::builder → KILLED
    return new RelyingPartyBuilder.MandatoryStages();
609
  }
610
611
  public static class RelyingPartyBuilder {
612
    private @NonNull Optional<AppId> appId = Optional.empty();
613
    private @NonNull Optional<AttestationConveyancePreference> attestationConveyancePreference =
614
        Optional.empty();
615
    private @NonNull Optional<AttestationTrustSource> attestationTrustSource = Optional.empty();
616
617
    /**
618
     * The allowed origins that returned authenticator responses will be compared against.
619
     *
620
     * <p>The default is the set containing only the string <code>
621
     * "https://" + {@link #getIdentity()}.getId()</code>.
622
     *
623
     * <p>If {@link RelyingPartyBuilder#allowOriginPort(boolean) allowOriginPort} and {@link
624
     * RelyingPartyBuilder#allowOriginSubdomain(boolean) allowOriginSubdomain} are both <code>false
625
     * </code> (the default), then a successful registration or authentication operation requires
626
     * {@link CollectedClientData#getOrigin()} to exactly equal one of these values.
627
     *
628
     * <p>If {@link RelyingPartyBuilder#allowOriginPort(boolean) allowOriginPort} is <code>true
629
     * </code> , then the above rule is relaxed to allow any port number in {@link
630
     * CollectedClientData#getOrigin()}, regardless of any port specified.
631
     *
632
     * <p>If {@link RelyingPartyBuilder#allowOriginSubdomain(boolean) allowOriginSubdomain} is
633
     * <code>true</code>, then the above rule is relaxed to allow any subdomain, of any depth, of
634
     * any of these values.
635
     *
636
     * <p>For either of the above relaxations to take effect, both the allowed origin and the client
637
     * data origin must be valid URLs. Origins that are not valid URLs are matched only by exact
638
     * string equality.
639
     *
640
     * @since 0.6.0
641
     * @see #getIdentity()
642
     * @see #origins(Optional)
643
     */
644
    public RelyingPartyBuilder origins(@NonNull Set<String> origins) {
645
      this.origins = origins;
646 1 1. origins : replaced return value with null for com/yubico/webauthn/RelyingParty$RelyingPartyBuilder::origins → KILLED
      return this;
647
    }
648
649
    /**
650
     * The allowed origins that returned authenticator responses will be compared against.
651
     *
652
     * <p>If set to empty, this setting reverts to the default value.
653
     *
654
     * <p>The default is the set containing only the string <code>
655
     * "https://" + {@link #getIdentity()}.getId()</code>.
656
     *
657
     * <p>If {@link RelyingPartyBuilder#allowOriginPort(boolean) allowOriginPort} and {@link
658
     * RelyingPartyBuilder#allowOriginSubdomain(boolean) allowOriginSubdomain} are both <code>false
659
     * </code> (the default), then a successful registration or authentication operation requires
660
     * {@link CollectedClientData#getOrigin()} to exactly equal one of these values.
661
     *
662
     * <p>If {@link RelyingPartyBuilder#allowOriginPort(boolean) allowOriginPort} is <code>true
663
     * </code> , then the above rule is relaxed to allow any port number in {@link
664
     * CollectedClientData#getOrigin()}, regardless of any port specified.
665
     *
666
     * <p>If {@link RelyingPartyBuilder#allowOriginSubdomain(boolean) allowOriginSubdomain} is
667
     * <code>true</code>, then the above rule is relaxed to allow any subdomain, of any depth, of
668
     * any of these values.
669
     *
670
     * <p>For either of the above relaxations to take effect, both the allowed origin and the client
671
     * data origin must be valid URLs. Origins that are not valid URLs are matched only by exact
672
     * string equality.
673
     *
674
     * @since 2.7.0
675
     * @see #getIdentity()
676
     * @see #origins(Set)
677
     */
678
    public RelyingPartyBuilder origins(@NonNull Optional<Set<String>> origins) {
679
      this.origins = origins.orElse(null);
680 1 1. origins : replaced return value with null for com/yubico/webauthn/RelyingParty$RelyingPartyBuilder::origins → KILLED
      return this;
681
    }
682
683
    public static class MandatoryStages {
684
      private final RelyingPartyBuilder builder = new RelyingPartyBuilder();
685
686
      /**
687
       * {@link RelyingPartyBuilder#identity(RelyingPartyIdentity) identity} is a required
688
       * parameter.
689
       *
690
       * @see RelyingPartyBuilder#identity(RelyingPartyIdentity)
691
       */
692
      public Step2 identity(RelyingPartyIdentity identity) {
693
        builder.identity(identity);
694 1 1. identity : replaced return value with null for com/yubico/webauthn/RelyingParty$RelyingPartyBuilder$MandatoryStages::identity → KILLED
        return new Step2();
695
      }
696
697
      public class Step2 {
698
        /**
699
         * {@link RelyingPartyBuilder#credentialRepository(CredentialRepository)
700
         * credentialRepository} is a required parameter.
701
         *
702
         * @see RelyingPartyBuilder#credentialRepository(CredentialRepository)
703
         * @see #credentialRepositoryV2(CredentialRepositoryV2)
704
         */
705
        public RelyingPartyBuilder credentialRepository(CredentialRepository credentialRepository) {
706 1 1. credentialRepository : replaced return value with null for com/yubico/webauthn/RelyingParty$RelyingPartyBuilder$MandatoryStages$Step2::credentialRepository → KILLED
          return builder.credentialRepository(credentialRepository);
707
        }
708
709
        /**
710
         * {@link RelyingPartyBuilder#credentialRepository(CredentialRepository)
711
         * credentialRepository} is a required parameter. This setter differs from {@link
712
         * #credentialRepository(CredentialRepository)} in that it takes an instance of {@link
713
         * CredentialRepositoryV2} and converts the builder's return type to {@link RelyingPartyV2}.
714
         * {@link CredentialRepositoryV2} does not require the application to support usernames,
715
         * unless {@link RelyingPartyV2.RelyingPartyV2Builder#usernameRepository(UsernameRepository)
716
         * usernameRepository} is also set in a subsequent builder step.
717
         *
718
         * @see #credentialRepository(CredentialRepository)
719
         * @deprecated EXPERIMENTAL: This is an experimental feature. It is likely to change or be
720
         *     deleted before reaching a mature release.
721
         */
722
        @Deprecated
723
        public <C extends CredentialRecord>
724
            RelyingPartyV2.RelyingPartyV2Builder<C> credentialRepositoryV2(
725
                CredentialRepositoryV2<C> credentialRepository) {
726 1 1. credentialRepositoryV2 : replaced return value with null for com/yubico/webauthn/RelyingParty$RelyingPartyBuilder$MandatoryStages$Step2::credentialRepositoryV2 → KILLED
          return RelyingPartyV2.builder(builder.identity, credentialRepository);
727
        }
728
      }
729
    }
730
731
    /**
732
     * The extension input to set for the <code>appid</code> and <code>appidExclude</code>
733
     * extensions.
734
     *
735
     * <p>You do not need this extension if you have not previously supported U2F. Its purpose is to
736
     * make already-registered U2F credentials forward-compatible with the WebAuthn API. It is not
737
     * needed for new registrations, even of U2F authenticators.
738
     *
739
     * <p>If this member is set, {@link #startAssertion(StartAssertionOptions) startAssertion} will
740
     * automatically set the <code>appid</code> extension input, and {@link
741
     * #finishAssertion(FinishAssertionOptions) finishAssertion} will adjust its verification logic
742
     * to also accept this AppID as an alternative to the RP ID. Likewise, {@link
743
     * #startRegistration(StartRegistrationOptions)} startRegistration} will automatically set the
744
     * <code>appidExclude</code> extension input.
745
     *
746
     * <p>By default, this is not set.
747
     *
748
     * @see AssertionExtensionInputs#getAppid()
749
     * @see RegistrationExtensionInputs#getAppidExclude()
750
     * @see <a
751
     *     href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#sctn-appid-extension">§10.1.
752
     *     FIDO AppID Extension (appid)</a>
753
     * @see <a
754
     *     href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#sctn-appid-exclude-extension">§10.2.
755
     *     FIDO AppID Exclusion Extension (appidExclude)</a>
756
     */
757
    public RelyingPartyBuilder appId(@NonNull Optional<AppId> appId) {
758
      this.appId = appId;
759 1 1. appId : replaced return value with null for com/yubico/webauthn/RelyingParty$RelyingPartyBuilder::appId → KILLED
      return this;
760
    }
761
762
    /**
763
     * The extension input to set for the <code>appid</code> and <code>appidExclude</code>
764
     * extensions.
765
     *
766
     * <p>You do not need this extension if you have not previously supported U2F. Its purpose is to
767
     * make already-registered U2F credentials forward-compatible with the WebAuthn API. It is not
768
     * needed for new registrations, even of U2F authenticators.
769
     *
770
     * <p>If this member is set, {@link #startAssertion(StartAssertionOptions) startAssertion} will
771
     * automatically set the <code>appid</code> extension input, and {@link
772
     * #finishAssertion(FinishAssertionOptions) finishAssertion} will adjust its verification logic
773
     * to also accept this AppID as an alternative to the RP ID. Likewise, {@link
774
     * #startRegistration(StartRegistrationOptions)} startRegistration} will automatically set the
775
     * <code>appidExclude</code> extension input.
776
     *
777
     * <p>By default, this is not set.
778
     *
779
     * @see AssertionExtensionInputs#getAppid()
780
     * @see RegistrationExtensionInputs#getAppidExclude()
781
     * @see <a
782
     *     href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#sctn-appid-extension">§10.1.
783
     *     FIDO AppID Extension (appid)</a>
784
     * @see <a
785
     *     href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#sctn-appid-exclude-extension">§10.2.
786
     *     FIDO AppID Exclusion Extension (appidExclude)</a>
787
     */
788
    public RelyingPartyBuilder appId(@NonNull AppId appId) {
789 1 1. appId : replaced return value with null for com/yubico/webauthn/RelyingParty$RelyingPartyBuilder::appId → KILLED
      return this.appId(Optional.of(appId));
790
    }
791
792
    /**
793
     * The argument for the {@link PublicKeyCredentialCreationOptions#getAttestation() attestation}
794
     * parameter in registration operations.
795
     *
796
     * <p>Unless your application has a concrete policy for authenticator attestation, it is
797
     * recommended to leave this parameter undefined.
798
     *
799
     * <p>If you set this, you may want to explicitly set {@link
800
     * RelyingPartyBuilder#allowUntrustedAttestation(boolean) allowUntrustedAttestation} and {@link
801
     * RelyingPartyBuilder#attestationTrustSource(AttestationTrustSource) attestationTrustSource}
802
     * too.
803
     *
804
     * <p>By default, this is not set.
805
     *
806
     * @see PublicKeyCredentialCreationOptions#getAttestation()
807
     * @see <a href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#sctn-attestation">§6.4.
808
     *     Attestation</a>
809
     */
810
    public RelyingPartyBuilder attestationConveyancePreference(
811
        @NonNull Optional<AttestationConveyancePreference> attestationConveyancePreference) {
812
      this.attestationConveyancePreference = attestationConveyancePreference;
813 1 1. attestationConveyancePreference : replaced return value with null for com/yubico/webauthn/RelyingParty$RelyingPartyBuilder::attestationConveyancePreference → KILLED
      return this;
814
    }
815
816
    /**
817
     * The argument for the {@link PublicKeyCredentialCreationOptions#getAttestation() attestation}
818
     * parameter in registration operations.
819
     *
820
     * <p>Unless your application has a concrete policy for authenticator attestation, it is
821
     * recommended to leave this parameter undefined.
822
     *
823
     * <p>If you set this, you may want to explicitly set {@link
824
     * RelyingPartyBuilder#allowUntrustedAttestation(boolean) allowUntrustedAttestation} and {@link
825
     * RelyingPartyBuilder#attestationTrustSource(AttestationTrustSource) attestationTrustSource}
826
     * too.
827
     *
828
     * <p>By default, this is not set.
829
     *
830
     * @see PublicKeyCredentialCreationOptions#getAttestation()
831
     * @see <a href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#sctn-attestation">§6.4.
832
     *     Attestation</a>
833
     */
834
    public RelyingPartyBuilder attestationConveyancePreference(
835
        @NonNull AttestationConveyancePreference attestationConveyancePreference) {
836 1 1. attestationConveyancePreference : replaced return value with null for com/yubico/webauthn/RelyingParty$RelyingPartyBuilder::attestationConveyancePreference → KILLED
      return this.attestationConveyancePreference(Optional.of(attestationConveyancePreference));
837
    }
838
839
    /**
840
     * An {@link AttestationTrustSource} instance to use for looking up trust roots for
841
     * authenticator attestation. This matters only if {@link #getAttestationConveyancePreference()}
842
     * is non-empty and not set to {@link AttestationConveyancePreference#NONE}.
843
     *
844
     * <p>By default, this is not set.
845
     *
846
     * @see PublicKeyCredentialCreationOptions#getAttestation()
847
     * @see <a href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#sctn-attestation">§6.4.
848
     *     Attestation</a>
849
     */
850
    public RelyingPartyBuilder attestationTrustSource(
851
        @NonNull Optional<AttestationTrustSource> attestationTrustSource) {
852
      this.attestationTrustSource = attestationTrustSource;
853 1 1. attestationTrustSource : replaced return value with null for com/yubico/webauthn/RelyingParty$RelyingPartyBuilder::attestationTrustSource → KILLED
      return this;
854
    }
855
856
    /**
857
     * An {@link AttestationTrustSource} instance to use for looking up trust roots for
858
     * authenticator attestation. This matters only if {@link #getAttestationConveyancePreference()}
859
     * is non-empty and not set to {@link AttestationConveyancePreference#NONE}.
860
     *
861
     * <p>By default, this is not set.
862
     *
863
     * @see PublicKeyCredentialCreationOptions#getAttestation()
864
     * @see <a href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#sctn-attestation">§6.4.
865
     *     Attestation</a>
866
     */
867
    public RelyingPartyBuilder attestationTrustSource(
868
        @NonNull AttestationTrustSource attestationTrustSource) {
869 1 1. attestationTrustSource : replaced return value with null for com/yubico/webauthn/RelyingParty$RelyingPartyBuilder::attestationTrustSource → KILLED
      return this.attestationTrustSource(Optional.of(attestationTrustSource));
870
    }
871
  }
872
}

Mutations

389

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

417

1.1
Location : generateChallenge
Killed by : com.yubico.webauthn.RelyingPartyTest.filtersAlgorithmsToThoseAvailable(com.yubico.webauthn.RelyingPartyTest)
removed call to java/security/SecureRandom::nextBytes → KILLED

418

1.1
Location : generateChallenge
Killed by : com.yubico.webauthn.RelyingPartyTest.filtersAlgorithmsToThoseAvailable(com.yubico.webauthn.RelyingPartyTest)
replaced return value with null for com/yubico/webauthn/RelyingParty::generateChallenge → KILLED

429

1.1
Location : filterAvailableAlgorithms
Killed by : com.yubico.webauthn.RelyingPartyTest.logsWarningIfAlgorithmNotAvailable(com.yubico.webauthn.RelyingPartyTest)
replaced return value with Collections.emptyList for com/yubico/webauthn/RelyingParty::filterAvailableAlgorithms → KILLED

477

1.1
Location : lambda$filterAvailableAlgorithms$0
Killed by : com.yubico.webauthn.RelyingPartyTest.logsWarningIfAlgorithmNotAvailable(com.yubico.webauthn.RelyingPartyTest)
replaced boolean return with true for com/yubico/webauthn/RelyingParty::lambda$filterAvailableAlgorithms$0 → KILLED

485

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

494

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

497

1.1
Location : lambda$filterAvailableAlgorithms$0
Killed by : com.yubico.webauthn.RelyingPartyTest.defaultSettingsLogWarningIfSomeAlgorithmNotAvailable(com.yubico.webauthn.RelyingPartyTest)
replaced boolean return with false for com/yubico/webauthn/RelyingParty::lambda$filterAvailableAlgorithms$0 → KILLED

524

1.1
Location : startRegistration
Killed by : com.yubico.webauthn.RelyingPartyTest.filtersAlgorithmsToThoseAvailable(com.yubico.webauthn.RelyingPartyTest)
removed call to java/util/Optional::ifPresent → KILLED

525

1.1
Location : startRegistration
Killed by : com.yubico.webauthn.RelyingPartyTest.filtersAlgorithmsToThoseAvailable(com.yubico.webauthn.RelyingPartyTest)
replaced return value with null for com/yubico/webauthn/RelyingParty::startRegistration → KILLED

531

1.1
Location : finishRegistration
Killed by : com.yubico.webauthn.RelyingPartyCeremoniesSpec
replaced return value with null for com/yubico/webauthn/RelyingParty::finishRegistration → KILLED

545

1.1
Location : _finishRegistration
Killed by : com.yubico.webauthn.RelyingPartyCeremoniesSpec
replaced return value with null for com/yubico/webauthn/RelyingParty::_finishRegistration → KILLED

557

1.1
Location : lambda$startAssertion$1
Killed by : com.yubico.webauthn.RelyingPartyStartOperationSpec
replaced return value with Optional.empty for com/yubico/webauthn/RelyingParty::lambda$startAssertion$1 → KILLED

562

1.1
Location : lambda$startAssertion$2
Killed by : com.yubico.webauthn.RelyingPartyStartOperationSpec
replaced return value with Collections.emptyList for com/yubico/webauthn/RelyingParty::lambda$startAssertion$2 → KILLED

570

1.1
Location : startAssertion
Killed by : com.yubico.webauthn.RelyingPartyAssertionSpec
removed call to java/util/Optional::ifPresent → KILLED

572

1.1
Location : startAssertion
Killed by : com.yubico.webauthn.RelyingPartyUserIdentificationSpec
replaced return value with null for com/yubico/webauthn/RelyingParty::startAssertion → KILLED

590

1.1
Location : finishAssertion
Killed by : com.yubico.webauthn.RelyingPartyUserIdentificationSpec
replaced return value with null for com/yubico/webauthn/RelyingParty::finishAssertion → KILLED

604

1.1
Location : _finishAssertion
Killed by : com.yubico.webauthn.RelyingPartyUserIdentificationSpec
replaced return value with null for com/yubico/webauthn/RelyingParty::_finishAssertion → KILLED

608

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

646

1.1
Location : origins
Killed by : com.yubico.webauthn.RelyingPartyTest.testOriginsWithEmptySet(com.yubico.webauthn.RelyingPartyTest)
replaced return value with null for com/yubico/webauthn/RelyingParty$RelyingPartyBuilder::origins → KILLED

680

1.1
Location : origins
Killed by : com.yubico.webauthn.RelyingPartyTest.testOriginsWithOptionalSet(com.yubico.webauthn.RelyingPartyTest)
replaced return value with null for com/yubico/webauthn/RelyingParty$RelyingPartyBuilder::origins → KILLED

694

1.1
Location : identity
Killed by : com.yubico.webauthn.RelyingPartyTest.doesNotLogWarningIfAllAlgorithmsAvailable(com.yubico.webauthn.RelyingPartyTest)
replaced return value with null for com/yubico/webauthn/RelyingParty$RelyingPartyBuilder$MandatoryStages::identity → KILLED

706

1.1
Location : credentialRepository
Killed by : com.yubico.webauthn.RelyingPartyTest.doesNotLogWarningIfAllAlgorithmsAvailable(com.yubico.webauthn.RelyingPartyTest)
replaced return value with null for com/yubico/webauthn/RelyingParty$RelyingPartyBuilder$MandatoryStages$Step2::credentialRepository → KILLED

726

1.1
Location : credentialRepositoryV2
Killed by : com.yubico.webauthn.RelyingPartyTest.testOriginsWithOptionalSet(com.yubico.webauthn.RelyingPartyTest)
replaced return value with null for com/yubico/webauthn/RelyingParty$RelyingPartyBuilder$MandatoryStages$Step2::credentialRepositoryV2 → KILLED

759

1.1
Location : appId
Killed by : com.yubico.webauthn.RelyingPartyStartOperationSpec
replaced return value with null for com/yubico/webauthn/RelyingParty$RelyingPartyBuilder::appId → KILLED

789

1.1
Location : appId
Killed by : com.yubico.webauthn.RelyingPartyStartOperationSpec
replaced return value with null for com/yubico/webauthn/RelyingParty$RelyingPartyBuilder::appId → KILLED

813

1.1
Location : attestationConveyancePreference
Killed by : com.yubico.webauthn.RelyingPartyStartOperationSpec
replaced return value with null for com/yubico/webauthn/RelyingParty$RelyingPartyBuilder::attestationConveyancePreference → KILLED

836

1.1
Location : attestationConveyancePreference
Killed by : com.yubico.webauthn.RelyingPartyStartOperationSpec
replaced return value with null for com/yubico/webauthn/RelyingParty$RelyingPartyBuilder::attestationConveyancePreference → KILLED

853

1.1
Location : attestationTrustSource
Killed by : com.yubico.webauthn.RelyingPartyRegistrationSpec
replaced return value with null for com/yubico/webauthn/RelyingParty$RelyingPartyBuilder::attestationTrustSource → KILLED

869

1.1
Location : attestationTrustSource
Killed by : com.yubico.webauthn.RelyingPartyRegistrationSpec
replaced return value with null for com/yubico/webauthn/RelyingParty$RelyingPartyBuilder::attestationTrustSource → KILLED

Active mutators

Tests examined


Report generated by PIT 1.20.3