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
            .hints(startRegistrationOptions.getHints());
498 1 1. startRegistration : removed call to java/util/Optional::ifPresent → KILLED
    attestationConveyancePreference.ifPresent(builder::attestation);
499 1 1. startRegistration : replaced return value with null for com/yubico/webauthn/RelyingParty::startRegistration → KILLED
    return builder.build();
500
  }
501
502
  public RegistrationResult finishRegistration(FinishRegistrationOptions finishRegistrationOptions)
503
      throws RegistrationFailedException {
504
    try {
505 1 1. finishRegistration : replaced return value with null for com/yubico/webauthn/RelyingParty::finishRegistration → KILLED
      return _finishRegistration(finishRegistrationOptions).run();
506
    } catch (IllegalArgumentException e) {
507
      throw new RegistrationFailedException(e);
508
    }
509
  }
510
511
  /**
512
   * This method is NOT part of the public API.
513
   *
514
   * <p>This method is called internally by {@link #finishRegistration(FinishRegistrationOptions)}.
515
   * It is a separate method to facilitate testing; users should call {@link
516
   * #finishRegistration(FinishRegistrationOptions)} instead of this method.
517
   */
518
  FinishRegistrationSteps _finishRegistration(FinishRegistrationOptions options) {
519 1 1. _finishRegistration : replaced return value with null for com/yubico/webauthn/RelyingParty::_finishRegistration → KILLED
    return FinishRegistrationSteps.fromV1(this, options);
520
  }
521
522
  public AssertionRequest startAssertion(StartAssertionOptions startAssertionOptions) {
523
    PublicKeyCredentialRequestOptionsBuilder pkcro =
524
        PublicKeyCredentialRequestOptions.builder()
525
            .challenge(generateChallenge())
526
            .rpId(identity.getId())
527
            .allowCredentials(
528
                OptionalUtil.orElseOptional(
529
                        startAssertionOptions.getUsername(),
530
                        () ->
531 1 1. lambda$startAssertion$1 : replaced return value with Optional.empty for com/yubico/webauthn/RelyingParty::lambda$startAssertion$1 → KILLED
                            startAssertionOptions
532
                                .getUserHandle()
533
                                .flatMap(credentialRepository::getUsernameForUserHandle))
534
                    .map(
535
                        un ->
536 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))))
537
            .extensions(
538
                startAssertionOptions
539
                    .getExtensions()
540
                    .merge(startAssertionOptions.getExtensions().toBuilder().appid(appId).build()))
541
            .timeout(startAssertionOptions.getTimeout())
542
            .hints(startAssertionOptions.getHints());
543
544 1 1. startAssertion : removed call to java/util/Optional::ifPresent → KILLED
    startAssertionOptions.getUserVerification().ifPresent(pkcro::userVerification);
545
546 1 1. startAssertion : replaced return value with null for com/yubico/webauthn/RelyingParty::startAssertion → KILLED
    return AssertionRequest.builder()
547
        .publicKeyCredentialRequestOptions(pkcro.build())
548
        .username(startAssertionOptions.getUsername())
549
        .userHandle(startAssertionOptions.getUserHandle())
550
        .build();
551
  }
552
553
  /**
554
   * @throws InvalidSignatureCountException if {@link
555
   *     RelyingPartyBuilder#validateSignatureCounter(boolean) validateSignatureCounter} is <code>
556
   *     true</code>, the {@link AuthenticatorData#getSignatureCounter() signature count} in the
557
   *     response is less than or equal to the {@link RegisteredCredential#getSignatureCount()
558
   *     stored signature count}, and at least one of the signature count values is nonzero.
559
   * @throws AssertionFailedException if validation fails for any other reason.
560
   */
561
  public AssertionResult finishAssertion(FinishAssertionOptions finishAssertionOptions)
562
      throws AssertionFailedException {
563
    try {
564 1 1. finishAssertion : replaced return value with null for com/yubico/webauthn/RelyingParty::finishAssertion → KILLED
      return _finishAssertion(finishAssertionOptions).run();
565
    } catch (IllegalArgumentException e) {
566
      throw new AssertionFailedException(e);
567
    }
568
  }
569
570
  /**
571
   * This method is NOT part of the public API.
572
   *
573
   * <p>This method is called internally by {@link #finishAssertion(FinishAssertionOptions)}. It is
574
   * a separate method to facilitate testing; users should call {@link
575
   * #finishAssertion(FinishAssertionOptions)} instead of this method.
576
   */
577
  FinishAssertionSteps<RegisteredCredential> _finishAssertion(FinishAssertionOptions options) {
578 1 1. _finishAssertion : replaced return value with null for com/yubico/webauthn/RelyingParty::_finishAssertion → KILLED
    return FinishAssertionSteps.fromV1(this, options);
579
  }
580
581
  public static RelyingPartyBuilder.MandatoryStages builder() {
582 1 1. builder : replaced return value with null for com/yubico/webauthn/RelyingParty::builder → KILLED
    return new RelyingPartyBuilder.MandatoryStages();
583
  }
584
585
  public static class RelyingPartyBuilder {
586
    private @NonNull Optional<AppId> appId = Optional.empty();
587
    private @NonNull Optional<AttestationConveyancePreference> attestationConveyancePreference =
588
        Optional.empty();
589
    private @NonNull Optional<AttestationTrustSource> attestationTrustSource = Optional.empty();
590
591
    public static class MandatoryStages {
592
      private final RelyingPartyBuilder builder = new RelyingPartyBuilder();
593
594
      /**
595
       * {@link RelyingPartyBuilder#identity(RelyingPartyIdentity) identity} is a required
596
       * parameter.
597
       *
598
       * @see RelyingPartyBuilder#identity(RelyingPartyIdentity)
599
       */
600
      public Step2 identity(RelyingPartyIdentity identity) {
601
        builder.identity(identity);
602 1 1. identity : replaced return value with null for com/yubico/webauthn/RelyingParty$RelyingPartyBuilder$MandatoryStages::identity → KILLED
        return new Step2();
603
      }
604
605
      public class Step2 {
606
        /**
607
         * {@link RelyingPartyBuilder#credentialRepository(CredentialRepository)
608
         * credentialRepository} is a required parameter.
609
         *
610
         * @see RelyingPartyBuilder#credentialRepository(CredentialRepository)
611
         * @see #credentialRepositoryV2(CredentialRepositoryV2)
612
         */
613
        public RelyingPartyBuilder credentialRepository(CredentialRepository credentialRepository) {
614 1 1. credentialRepository : replaced return value with null for com/yubico/webauthn/RelyingParty$RelyingPartyBuilder$MandatoryStages$Step2::credentialRepository → KILLED
          return builder.credentialRepository(credentialRepository);
615
        }
616
617
        /**
618
         * {@link RelyingPartyBuilder#credentialRepository(CredentialRepository)
619
         * credentialRepository} is a required parameter. This setter differs from {@link
620
         * #credentialRepository(CredentialRepository)} in that it takes an instance of {@link
621
         * CredentialRepositoryV2} and converts the builder's return type to {@link RelyingPartyV2}.
622
         * {@link CredentialRepositoryV2} does not require the application to support usernames,
623
         * unless {@link RelyingPartyV2.RelyingPartyV2Builder#usernameRepository(UsernameRepository)
624
         * usernameRepository} is also set in a subsequent builder step.
625
         *
626
         * @see #credentialRepository(CredentialRepository)
627
         * @deprecated EXPERIMENTAL: This is an experimental feature. It is likely to change or be
628
         *     deleted before reaching a mature release.
629
         */
630
        @Deprecated
631
        public <C extends CredentialRecord>
632
            RelyingPartyV2.RelyingPartyV2Builder<C> credentialRepositoryV2(
633
                CredentialRepositoryV2<C> credentialRepository) {
634 1 1. credentialRepositoryV2 : replaced return value with null for com/yubico/webauthn/RelyingParty$RelyingPartyBuilder$MandatoryStages$Step2::credentialRepositoryV2 → KILLED
          return RelyingPartyV2.builder(builder.identity, credentialRepository);
635
        }
636
      }
637
    }
638
639
    /**
640
     * The extension input to set for the <code>appid</code> and <code>appidExclude</code>
641
     * extensions.
642
     *
643
     * <p>You do not need this extension if you have not previously supported U2F. Its purpose is to
644
     * make already-registered U2F credentials forward-compatible with the WebAuthn API. It is not
645
     * needed for new registrations, even of U2F authenticators.
646
     *
647
     * <p>If this member is set, {@link #startAssertion(StartAssertionOptions) startAssertion} will
648
     * automatically set the <code>appid</code> extension input, and {@link
649
     * #finishAssertion(FinishAssertionOptions) finishAssertion} will adjust its verification logic
650
     * to also accept this AppID as an alternative to the RP ID. Likewise, {@link
651
     * #startRegistration(StartRegistrationOptions)} startRegistration} will automatically set the
652
     * <code>appidExclude</code> extension input.
653
     *
654
     * <p>By default, this is not set.
655
     *
656
     * @see AssertionExtensionInputs#getAppid()
657
     * @see RegistrationExtensionInputs#getAppidExclude()
658
     * @see <a
659
     *     href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#sctn-appid-extension">§10.1.
660
     *     FIDO AppID Extension (appid)</a>
661
     * @see <a
662
     *     href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#sctn-appid-exclude-extension">§10.2.
663
     *     FIDO AppID Exclusion Extension (appidExclude)</a>
664
     */
665 1 1. appId : negated conditional → KILLED
    public RelyingPartyBuilder appId(@NonNull Optional<AppId> appId) {
666
      this.appId = appId;
667 1 1. appId : replaced return value with null for com/yubico/webauthn/RelyingParty$RelyingPartyBuilder::appId → KILLED
      return this;
668
    }
669
670
    /**
671
     * The extension input to set for the <code>appid</code> and <code>appidExclude</code>
672
     * extensions.
673
     *
674
     * <p>You do not need this extension if you have not previously supported U2F. Its purpose is to
675
     * make already-registered U2F credentials forward-compatible with the WebAuthn API. It is not
676
     * needed for new registrations, even of U2F authenticators.
677
     *
678
     * <p>If this member is set, {@link #startAssertion(StartAssertionOptions) startAssertion} will
679
     * automatically set the <code>appid</code> extension input, and {@link
680
     * #finishAssertion(FinishAssertionOptions) finishAssertion} will adjust its verification logic
681
     * to also accept this AppID as an alternative to the RP ID. Likewise, {@link
682
     * #startRegistration(StartRegistrationOptions)} startRegistration} will automatically set the
683
     * <code>appidExclude</code> extension input.
684
     *
685
     * <p>By default, this is not set.
686
     *
687
     * @see AssertionExtensionInputs#getAppid()
688
     * @see RegistrationExtensionInputs#getAppidExclude()
689
     * @see <a
690
     *     href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#sctn-appid-extension">§10.1.
691
     *     FIDO AppID Extension (appid)</a>
692
     * @see <a
693
     *     href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#sctn-appid-exclude-extension">§10.2.
694
     *     FIDO AppID Exclusion Extension (appidExclude)</a>
695
     */
696 1 1. appId : negated conditional → KILLED
    public RelyingPartyBuilder appId(@NonNull AppId appId) {
697 1 1. appId : replaced return value with null for com/yubico/webauthn/RelyingParty$RelyingPartyBuilder::appId → KILLED
      return this.appId(Optional.of(appId));
698
    }
699
700
    /**
701
     * The argument for the {@link PublicKeyCredentialCreationOptions#getAttestation() attestation}
702
     * parameter in registration operations.
703
     *
704
     * <p>Unless your application has a concrete policy for authenticator attestation, it is
705
     * recommended to leave this parameter undefined.
706
     *
707
     * <p>If you set this, you may want to explicitly set {@link
708
     * RelyingPartyBuilder#allowUntrustedAttestation(boolean) allowUntrustedAttestation} and {@link
709
     * RelyingPartyBuilder#attestationTrustSource(AttestationTrustSource) attestationTrustSource}
710
     * too.
711
     *
712
     * <p>By default, this is not set.
713
     *
714
     * @see PublicKeyCredentialCreationOptions#getAttestation()
715
     * @see <a href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#sctn-attestation">§6.4.
716
     *     Attestation</a>
717
     */
718
    public RelyingPartyBuilder attestationConveyancePreference(
719 1 1. attestationConveyancePreference : negated conditional → KILLED
        @NonNull Optional<AttestationConveyancePreference> attestationConveyancePreference) {
720
      this.attestationConveyancePreference = attestationConveyancePreference;
721 1 1. attestationConveyancePreference : replaced return value with null for com/yubico/webauthn/RelyingParty$RelyingPartyBuilder::attestationConveyancePreference → KILLED
      return this;
722
    }
723
724
    /**
725
     * The argument for the {@link PublicKeyCredentialCreationOptions#getAttestation() attestation}
726
     * parameter in registration operations.
727
     *
728
     * <p>Unless your application has a concrete policy for authenticator attestation, it is
729
     * recommended to leave this parameter undefined.
730
     *
731
     * <p>If you set this, you may want to explicitly set {@link
732
     * RelyingPartyBuilder#allowUntrustedAttestation(boolean) allowUntrustedAttestation} and {@link
733
     * RelyingPartyBuilder#attestationTrustSource(AttestationTrustSource) attestationTrustSource}
734
     * too.
735
     *
736
     * <p>By default, this is not set.
737
     *
738
     * @see PublicKeyCredentialCreationOptions#getAttestation()
739
     * @see <a href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#sctn-attestation">§6.4.
740
     *     Attestation</a>
741
     */
742
    public RelyingPartyBuilder attestationConveyancePreference(
743 1 1. attestationConveyancePreference : negated conditional → KILLED
        @NonNull AttestationConveyancePreference attestationConveyancePreference) {
744 1 1. attestationConveyancePreference : replaced return value with null for com/yubico/webauthn/RelyingParty$RelyingPartyBuilder::attestationConveyancePreference → KILLED
      return this.attestationConveyancePreference(Optional.of(attestationConveyancePreference));
745
    }
746
747
    /**
748
     * An {@link AttestationTrustSource} instance to use for looking up trust roots for
749
     * authenticator attestation. This matters only if {@link #getAttestationConveyancePreference()}
750
     * is non-empty and not set to {@link AttestationConveyancePreference#NONE}.
751
     *
752
     * <p>By default, this is not set.
753
     *
754
     * @see PublicKeyCredentialCreationOptions#getAttestation()
755
     * @see <a href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#sctn-attestation">§6.4.
756
     *     Attestation</a>
757
     */
758
    public RelyingPartyBuilder attestationTrustSource(
759 1 1. attestationTrustSource : negated conditional → KILLED
        @NonNull Optional<AttestationTrustSource> attestationTrustSource) {
760
      this.attestationTrustSource = attestationTrustSource;
761 1 1. attestationTrustSource : replaced return value with null for com/yubico/webauthn/RelyingParty$RelyingPartyBuilder::attestationTrustSource → KILLED
      return this;
762
    }
763
764
    /**
765
     * An {@link AttestationTrustSource} instance to use for looking up trust roots for
766
     * authenticator attestation. This matters only if {@link #getAttestationConveyancePreference()}
767
     * is non-empty and not set to {@link AttestationConveyancePreference#NONE}.
768
     *
769
     * <p>By default, this is not set.
770
     *
771
     * @see PublicKeyCredentialCreationOptions#getAttestation()
772
     * @see <a href="https://www.w3.org/TR/2021/REC-webauthn-2-20210408/#sctn-attestation">§6.4.
773
     *     Attestation</a>
774
     */
775
    public RelyingPartyBuilder attestationTrustSource(
776 1 1. attestationTrustSource : negated conditional → KILLED
        @NonNull AttestationTrustSource attestationTrustSource) {
777 1 1. attestationTrustSource : replaced return value with null for com/yubico/webauthn/RelyingParty$RelyingPartyBuilder::attestationTrustSource → KILLED
      return this.attestationTrustSource(Optional.of(attestationTrustSource));
778
    }
779
  }
780
}

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

498

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

499

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

505

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

519

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

531

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

536

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

544

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

546

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

564

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

578

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

582

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

602

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

614

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

634

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

665

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

667

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

696

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

697

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

719

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

721

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

743

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

744

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

759

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

761

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

776

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

777

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