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

Mutations

369

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

371

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

372

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

373

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

374

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

383

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

411

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

412

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

423

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

459

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

467

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

476

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

479

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

506

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

507

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

513

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

527

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

539

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

544

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

552

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

554

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

572

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

586

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

590

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

626

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

628

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

660

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

662

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

676

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

688

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

708

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

739

1.1
Location : appId
Killed by : com.yubico.webauthn.RelyingPartyStartOperationSpec
negated conditional → KILLED

741

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

770

1.1
Location : appId
Killed by : com.yubico.webauthn.RelyingPartyStartOperationSpec
negated conditional → KILLED

771

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

793

1.1
Location : attestationConveyancePreference
Killed by : com.yubico.webauthn.RelyingPartyStartOperationSpec
negated conditional → KILLED

795

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

817

1.1
Location : attestationConveyancePreference
Killed by : com.yubico.webauthn.RelyingPartyStartOperationSpec
negated conditional → KILLED

818

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

833

1.1
Location : attestationTrustSource
Killed by : com.yubico.webauthn.RelyingPartyRegistrationSpec
negated conditional → KILLED

835

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

850

1.1
Location : attestationTrustSource
Killed by : com.yubico.webauthn.RelyingPartyRegistrationSpec
negated conditional → KILLED

851

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.15.0