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

Mutations

366

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

368

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

369

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

370

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

380

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

408

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

409

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

420

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

451

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

459

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

468

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

471

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

497

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

498

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

504

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

518

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

530

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

535

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

542

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

544

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

562

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

576

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

580

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

600

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

612

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

632

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

663

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

665

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

694

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

695

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

717

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

719

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

741

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

742

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

757

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

759

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

774

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

775

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