All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.yubico.webauthn.RelyingParty Maven / Gradle / Ivy

The newest version!
// Copyright (c) 2018, Yubico AB
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
//    list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

package com.yubico.webauthn;

import com.yubico.internal.util.CollectionUtil;
import com.yubico.internal.util.OptionalUtil;
import com.yubico.webauthn.attestation.AttestationTrustSource;
import com.yubico.webauthn.data.AssertionExtensionInputs;
import com.yubico.webauthn.data.AttestationConveyancePreference;
import com.yubico.webauthn.data.AuthenticatorData;
import com.yubico.webauthn.data.ByteArray;
import com.yubico.webauthn.data.CollectedClientData;
import com.yubico.webauthn.data.PublicKeyCredentialCreationOptions;
import com.yubico.webauthn.data.PublicKeyCredentialCreationOptions.PublicKeyCredentialCreationOptionsBuilder;
import com.yubico.webauthn.data.PublicKeyCredentialParameters;
import com.yubico.webauthn.data.PublicKeyCredentialRequestOptions;
import com.yubico.webauthn.data.PublicKeyCredentialRequestOptions.PublicKeyCredentialRequestOptionsBuilder;
import com.yubico.webauthn.data.RegistrationExtensionInputs;
import com.yubico.webauthn.data.RelyingPartyIdentity;
import com.yubico.webauthn.exception.AssertionFailedException;
import com.yubico.webauthn.exception.InvalidSignatureCountException;
import com.yubico.webauthn.exception.RegistrationFailedException;
import com.yubico.webauthn.extension.appid.AppId;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.Signature;
import java.time.Clock;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import lombok.Builder;
import lombok.NonNull;
import lombok.Value;
import lombok.extern.slf4j.Slf4j;

/**
 * Encapsulates the four basic Web Authentication operations - start/finish registration,
 * start/finish authentication - along with overall operational settings for them.
 *
 * 

This class has no mutable state. An instance of this class may therefore be thought of as a * container for specialized versions (function closures) of these four operations rather than a * stateful object. */ @Slf4j @Builder(toBuilder = true) @Value public class RelyingParty { private static final SecureRandom random = new SecureRandom(); /** * The {@link RelyingPartyIdentity} that will be set as the {@link * PublicKeyCredentialCreationOptions#getRp() rp} parameter when initiating registration * operations, and which {@link AuthenticatorData#getRpIdHash()} will be compared against. This is * a required parameter. * *

A successful registration or authentication operation requires {@link * AuthenticatorData#getRpIdHash()} to exactly equal the SHA-256 hash of this member's {@link * RelyingPartyIdentity#getId() id} member. Alternatively, it may instead equal the SHA-256 hash * of {@link #getAppId() appId} if the latter is present. * * @see #startRegistration(StartRegistrationOptions) * @see PublicKeyCredentialCreationOptions */ @NonNull private final RelyingPartyIdentity identity; /** * The allowed origins that returned authenticator responses will be compared against. * *

The default is the set containing only the string * "https://" + {@link #getIdentity()}.getId(). * *

If {@link RelyingPartyBuilder#allowOriginPort(boolean) allowOriginPort} and {@link * RelyingPartyBuilder#allowOriginSubdomain(boolean) allowOriginSubdomain} are both false * (the default), then a successful registration or authentication operation requires * {@link CollectedClientData#getOrigin()} to exactly equal one of these values. * *

If {@link RelyingPartyBuilder#allowOriginPort(boolean) allowOriginPort} is true * , then the above rule is relaxed to allow any port number in {@link * CollectedClientData#getOrigin()}, regardless of any port specified. * *

If {@link RelyingPartyBuilder#allowOriginSubdomain(boolean) allowOriginSubdomain} is * true, then the above rule is relaxed to allow any subdomain, of any depth, of any of * these values. * *

For either of the above relaxations to take effect, both the allowed origin and the client * data origin must be valid URLs. Origins that are not valid URLs are matched only by exact * string equality. * * @see #getIdentity() */ @NonNull private final Set origins; /** * An abstract database which can look up credentials, usernames and user handles from usernames, * user handles and credential IDs. This is a required parameter. * *

This is used to look up: * *

    *
  • the user handle for a user logging in via user name *
  • the user name for a user logging in via user handle *
  • the credential IDs to include in {@link * PublicKeyCredentialCreationOptions#getExcludeCredentials()} *
  • the credential IDs to include in {@link * PublicKeyCredentialRequestOptions#getAllowCredentials()} *
  • that the correct user owns the credential when verifying an assertion *
  • the public key to use to verify an assertion *
  • the stored signature counter when verifying an assertion *
*/ @NonNull private final CredentialRepository credentialRepository; /** * The extension input to set for the appid and appidExclude extensions. * *

You do not need this extension if you have not previously supported U2F. Its purpose is to * make already-registered U2F credentials forward-compatible with the WebAuthn API. It is not * needed for new registrations, even of U2F authenticators. * *

If this member is set, {@link #startAssertion(StartAssertionOptions) startAssertion} will * automatically set the appid extension input, and {@link * #finishAssertion(FinishAssertionOptions) finishAssertion} will adjust its verification logic to * also accept this AppID as an alternative to the RP ID. Likewise, {@link * #startRegistration(StartRegistrationOptions)} startRegistration} will automatically set the * appidExclude extension input. * *

By default, this is not set. * * @see AssertionExtensionInputs#getAppid() * @see RegistrationExtensionInputs#getAppidExclude() * @see §10.1. * FIDO AppID Extension (appid) * @see §10.2. * FIDO AppID Exclusion Extension (appidExclude) */ @NonNull private final Optional appId; /** * The argument for the {@link PublicKeyCredentialCreationOptions#getAttestation() attestation} * parameter in registration operations. * *

Unless your application has a concrete policy for authenticator attestation, it is * recommended to leave this parameter undefined. * *

If you set this, you may want to explicitly set {@link * RelyingPartyBuilder#allowUntrustedAttestation(boolean) allowUntrustedAttestation} and {@link * RelyingPartyBuilder#attestationTrustSource(AttestationTrustSource) attestationTrustSource} too. * *

By default, this is not set. * * @see PublicKeyCredentialCreationOptions#getAttestation() * @see §6.4. * Attestation */ @NonNull private final Optional attestationConveyancePreference; /** * An {@link AttestationTrustSource} instance to use for looking up trust roots for authenticator * attestation. This matters only if {@link #getAttestationConveyancePreference()} is non-empty * and not set to {@link AttestationConveyancePreference#NONE}. * *

By default, this is not set. * * @see PublicKeyCredentialCreationOptions#getAttestation() * @see §6.4. * Attestation */ @NonNull private final Optional attestationTrustSource; /** * The argument for the {@link PublicKeyCredentialCreationOptions#getPubKeyCredParams() * pubKeyCredParams} parameter in registration operations. * *

This is a list of acceptable public key algorithms and their parameters, ordered from most * to least preferred. * *

The default is the following list, in order: * *

    *
  1. {@link com.yubico.webauthn.data.PublicKeyCredentialParameters#ES256 ES256} *
  2. {@link com.yubico.webauthn.data.PublicKeyCredentialParameters#EdDSA EdDSA} *
  3. {@link com.yubico.webauthn.data.PublicKeyCredentialParameters#ES256 ES384} *
  4. {@link com.yubico.webauthn.data.PublicKeyCredentialParameters#ES256 ES512} *
  5. {@link com.yubico.webauthn.data.PublicKeyCredentialParameters#RS256 RS256} *
  6. {@link com.yubico.webauthn.data.PublicKeyCredentialParameters#RS384 RS384} *
  7. {@link com.yubico.webauthn.data.PublicKeyCredentialParameters#RS512 RS512} *
* * @see PublicKeyCredentialCreationOptions#getAttestation() * @see §6.4. * Attestation */ @Builder.Default @NonNull private final List preferredPubkeyParams = Collections.unmodifiableList( Arrays.asList( PublicKeyCredentialParameters.ES256, PublicKeyCredentialParameters.EdDSA, PublicKeyCredentialParameters.ES384, PublicKeyCredentialParameters.ES512, PublicKeyCredentialParameters.RS256, PublicKeyCredentialParameters.RS384, PublicKeyCredentialParameters.RS512)); /** * If true, the origin matching rule is relaxed to allow any port number. * *

The default is false. * *

Examples with * origins: ["https://example.org", "https://accounts.example.org", "https://acme.com:8443"] * * *

    *
  • *

    allowOriginPort: false *

    Accepted: *

      *
    • https://example.org *
    • https://accounts.example.org *
    • https://acme.com:8443 *
    *

    Rejected: *

      *
    • https://example.org:8443 *
    • https://shop.example.org *
    • https://acme.com *
    • https://acme.com:9000 *
    *
  • *

    allowOriginPort: true *

    Accepted: *

      *
    • https://example.org *
    • https://example.org:8443 *
    • https://accounts.example.org *
    • https://acme.com *
    • https://acme.com:8443 *
    • https://acme.com:9000 *
    *

    Rejected: *

      *
    • https://shop.example.org *
    *
*/ @Builder.Default private final boolean allowOriginPort = false; /** * If true, the origin matching rule is relaxed to allow any subdomain, of any depth, * of the values of {@link RelyingPartyBuilder#origins(Set) origins}. * *

Please see Security * Considerations: Code injection attacks for discussion of the risks in setting this to * true. * *

The default is false. * *

Examples with origins: ["https://example.org", "https://acme.com:8443"] * *

    *
  • *

    allowOriginSubdomain: false *

    Accepted: *

      *
    • https://example.org *
    • https://acme.com:8443 *
    *

    Rejected: *

      *
    • https://example.org:8443 *
    • https://accounts.example.org *
    • https://acme.com *
    • https://eu.shop.acme.com:8443 *
    *
  • *

    allowOriginSubdomain: true *

    Accepted: *

      *
    • https://example.org *
    • https://accounts.example.org *
    • https://acme.com:8443 *
    • https://eu.shop.acme.com:8443 *
    *

    Rejected: *

      *
    • https://example.org:8443 *
    • https://acme.com *
    *
* * @see §13.4.8. * Code injection attacks */ @Builder.Default private final boolean allowOriginSubdomain = false; /** * If false, {@link #finishRegistration(FinishRegistrationOptions) * finishRegistration} will only allow registrations where the attestation signature can be linked * to a trusted attestation root. This excludes none attestation, and self attestation unless the * self attestation key is explicitly trusted. * *

Regardless of the value of this option, invalid attestation statements of supported formats * will always be rejected. For example, a "packed" attestation statement with an invalid * signature will be rejected even if this option is set to true. * *

The default is true. */ @Builder.Default private final boolean allowUntrustedAttestation = true; /** * If true, {@link #finishAssertion(FinishAssertionOptions) finishAssertion} will * succeed only if the {@link AuthenticatorData#getSignatureCounter() signature counter value} in * the response is strictly greater than the {@link RegisteredCredential#getSignatureCount() * stored signature counter value}, or if both counters are exactly zero. * *

The default is true. */ @Builder.Default private final boolean validateSignatureCounter = true; /** * A {@link Clock} which will be used to tell the current time while verifying attestation * certificate chains. * *

This is intended primarily for testing, and relevant only if {@link * RelyingPartyBuilder#attestationTrustSource(AttestationTrustSource)} is set. * *

The default is Clock.systemUTC(). */ @Builder.Default @NonNull private final Clock clock = Clock.systemUTC(); @Builder private RelyingParty( @NonNull RelyingPartyIdentity identity, Set origins, @NonNull CredentialRepository credentialRepository, @NonNull Optional appId, @NonNull Optional attestationConveyancePreference, @NonNull Optional attestationTrustSource, List preferredPubkeyParams, boolean allowOriginPort, boolean allowOriginSubdomain, boolean allowUntrustedAttestation, boolean validateSignatureCounter, Clock clock) { this.identity = identity; this.origins = origins != null ? CollectionUtil.immutableSet(origins) : Collections.singleton("https://" + identity.getId()); for (String origin : this.origins) { try { new URL(origin); } catch (MalformedURLException e) { log.warn( "Allowed origin is not a valid URL, it will match only by exact string equality: {}", origin); } } this.credentialRepository = credentialRepository; this.appId = appId; this.attestationConveyancePreference = attestationConveyancePreference; this.attestationTrustSource = attestationTrustSource; this.preferredPubkeyParams = filterAvailableAlgorithms(preferredPubkeyParams); this.allowOriginPort = allowOriginPort; this.allowOriginSubdomain = allowOriginSubdomain; this.allowUntrustedAttestation = allowUntrustedAttestation; this.validateSignatureCounter = validateSignatureCounter; this.clock = clock; } private static ByteArray generateChallenge() { byte[] bytes = new byte[32]; random.nextBytes(bytes); return new ByteArray(bytes); } /** * Filter pubKeyCredParams to only contain algorithms with a {@link KeyFactory} and a * {@link Signature} available, and log a warning for every unsupported algorithm. * * @return a new {@link List} containing only the algorithms supported in the current JCA context. */ static List filterAvailableAlgorithms( List pubKeyCredParams) { return Collections.unmodifiableList( pubKeyCredParams.stream() .filter( param -> { try { switch (param.getAlg()) { case EdDSA: KeyFactory.getInstance("EdDSA"); break; case ES256: case ES384: case ES512: KeyFactory.getInstance("EC"); break; case RS256: case RS384: case RS512: case RS1: KeyFactory.getInstance("RSA"); break; default: log.warn( "Unknown algorithm: {}. Please file a bug report.", param.getAlg()); } } catch (NoSuchAlgorithmException e) { log.warn( "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().", param.getAlg()); return false; } final String signatureAlgName; try { signatureAlgName = WebAuthnCodecs.getJavaAlgorithmName(param.getAlg()); } catch (IllegalArgumentException e) { log.warn("Unknown algorithm: {}. Please file a bug report.", param.getAlg()); return false; } try { Signature.getInstance(signatureAlgName); } catch (NoSuchAlgorithmException e) { log.warn( "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().", param.getAlg()); return false; } return true; }) .collect(Collectors.toList())); } public PublicKeyCredentialCreationOptions startRegistration( StartRegistrationOptions startRegistrationOptions) { PublicKeyCredentialCreationOptionsBuilder builder = PublicKeyCredentialCreationOptions.builder() .rp(identity) .user(startRegistrationOptions.getUser()) .challenge(generateChallenge()) .pubKeyCredParams(preferredPubkeyParams) .excludeCredentials( credentialRepository.getCredentialIdsForUsername( startRegistrationOptions.getUser().getName())) .authenticatorSelection(startRegistrationOptions.getAuthenticatorSelection()) .extensions( startRegistrationOptions .getExtensions() .merge( RegistrationExtensionInputs.builder() .appidExclude(appId) .credProps() .build())) .timeout(startRegistrationOptions.getTimeout()); attestationConveyancePreference.ifPresent(builder::attestation); return builder.build(); } public RegistrationResult finishRegistration(FinishRegistrationOptions finishRegistrationOptions) throws RegistrationFailedException { try { return _finishRegistration(finishRegistrationOptions).run(); } catch (IllegalArgumentException e) { throw new RegistrationFailedException(e); } } /** * This method is NOT part of the public API. * *

This method is called internally by {@link #finishRegistration(FinishRegistrationOptions)}. * It is a separate method to facilitate testing; users should call {@link * #finishRegistration(FinishRegistrationOptions)} instead of this method. */ FinishRegistrationSteps _finishRegistration(FinishRegistrationOptions options) { return FinishRegistrationSteps.fromV1(this, options); } public AssertionRequest startAssertion(StartAssertionOptions startAssertionOptions) { PublicKeyCredentialRequestOptionsBuilder pkcro = PublicKeyCredentialRequestOptions.builder() .challenge(generateChallenge()) .rpId(identity.getId()) .allowCredentials( OptionalUtil.orElseOptional( startAssertionOptions.getUsername(), () -> startAssertionOptions .getUserHandle() .flatMap(credentialRepository::getUsernameForUserHandle)) .map( un -> new ArrayList<>(credentialRepository.getCredentialIdsForUsername(un)))) .extensions( startAssertionOptions .getExtensions() .merge(startAssertionOptions.getExtensions().toBuilder().appid(appId).build())) .timeout(startAssertionOptions.getTimeout()); startAssertionOptions.getUserVerification().ifPresent(pkcro::userVerification); return AssertionRequest.builder() .publicKeyCredentialRequestOptions(pkcro.build()) .username(startAssertionOptions.getUsername()) .userHandle(startAssertionOptions.getUserHandle()) .build(); } /** * @throws InvalidSignatureCountException if {@link * RelyingPartyBuilder#validateSignatureCounter(boolean) validateSignatureCounter} is * true, the {@link AuthenticatorData#getSignatureCounter() signature count} in the * response is less than or equal to the {@link RegisteredCredential#getSignatureCount() * stored signature count}, and at least one of the signature count values is nonzero. * @throws AssertionFailedException if validation fails for any other reason. */ public AssertionResult finishAssertion(FinishAssertionOptions finishAssertionOptions) throws AssertionFailedException { try { return _finishAssertion(finishAssertionOptions).run(); } catch (IllegalArgumentException e) { throw new AssertionFailedException(e); } } /** * This method is NOT part of the public API. * *

This method is called internally by {@link #finishAssertion(FinishAssertionOptions)}. It is * a separate method to facilitate testing; users should call {@link * #finishAssertion(FinishAssertionOptions)} instead of this method. */ FinishAssertionSteps _finishAssertion(FinishAssertionOptions options) { return FinishAssertionSteps.fromV1(this, options); } public static RelyingPartyBuilder.MandatoryStages builder() { return new RelyingPartyBuilder.MandatoryStages(); } public static class RelyingPartyBuilder { private @NonNull Optional appId = Optional.empty(); private @NonNull Optional attestationConveyancePreference = Optional.empty(); private @NonNull Optional attestationTrustSource = Optional.empty(); public static class MandatoryStages { private final RelyingPartyBuilder builder = new RelyingPartyBuilder(); /** * {@link RelyingPartyBuilder#identity(RelyingPartyIdentity) identity} is a required * parameter. * * @see RelyingPartyBuilder#identity(RelyingPartyIdentity) */ public Step2 identity(RelyingPartyIdentity identity) { builder.identity(identity); return new Step2(); } public class Step2 { /** * {@link RelyingPartyBuilder#credentialRepository(CredentialRepository) * credentialRepository} is a required parameter. * * @see RelyingPartyBuilder#credentialRepository(CredentialRepository) * @see #credentialRepositoryV2(CredentialRepositoryV2) */ public RelyingPartyBuilder credentialRepository(CredentialRepository credentialRepository) { return builder.credentialRepository(credentialRepository); } /** * {@link RelyingPartyBuilder#credentialRepository(CredentialRepository) * credentialRepository} is a required parameter. This setter differs from {@link * #credentialRepository(CredentialRepository)} in that it takes an instance of {@link * CredentialRepositoryV2} and converts the builder's return type to {@link RelyingPartyV2}. * {@link CredentialRepositoryV2} does not require the application to support usernames, * unless {@link RelyingPartyV2.RelyingPartyV2Builder#usernameRepository(UsernameRepository) * usernameRepository} is also set in a subsequent builder step. * * @see #credentialRepository(CredentialRepository) * @deprecated EXPERIMENTAL: This is an experimental feature. It is likely to change or be * deleted before reaching a mature release. */ @Deprecated public RelyingPartyV2.RelyingPartyV2Builder credentialRepositoryV2( CredentialRepositoryV2 credentialRepository) { return RelyingPartyV2.builder(builder.identity, credentialRepository); } } } /** * The extension input to set for the appid and appidExclude * extensions. * *

You do not need this extension if you have not previously supported U2F. Its purpose is to * make already-registered U2F credentials forward-compatible with the WebAuthn API. It is not * needed for new registrations, even of U2F authenticators. * *

If this member is set, {@link #startAssertion(StartAssertionOptions) startAssertion} will * automatically set the appid extension input, and {@link * #finishAssertion(FinishAssertionOptions) finishAssertion} will adjust its verification logic * to also accept this AppID as an alternative to the RP ID. Likewise, {@link * #startRegistration(StartRegistrationOptions)} startRegistration} will automatically set the * appidExclude extension input. * *

By default, this is not set. * * @see AssertionExtensionInputs#getAppid() * @see RegistrationExtensionInputs#getAppidExclude() * @see §10.1. * FIDO AppID Extension (appid) * @see §10.2. * FIDO AppID Exclusion Extension (appidExclude) */ public RelyingPartyBuilder appId(@NonNull Optional appId) { this.appId = appId; return this; } /** * The extension input to set for the appid and appidExclude * extensions. * *

You do not need this extension if you have not previously supported U2F. Its purpose is to * make already-registered U2F credentials forward-compatible with the WebAuthn API. It is not * needed for new registrations, even of U2F authenticators. * *

If this member is set, {@link #startAssertion(StartAssertionOptions) startAssertion} will * automatically set the appid extension input, and {@link * #finishAssertion(FinishAssertionOptions) finishAssertion} will adjust its verification logic * to also accept this AppID as an alternative to the RP ID. Likewise, {@link * #startRegistration(StartRegistrationOptions)} startRegistration} will automatically set the * appidExclude extension input. * *

By default, this is not set. * * @see AssertionExtensionInputs#getAppid() * @see RegistrationExtensionInputs#getAppidExclude() * @see §10.1. * FIDO AppID Extension (appid) * @see §10.2. * FIDO AppID Exclusion Extension (appidExclude) */ public RelyingPartyBuilder appId(@NonNull AppId appId) { return this.appId(Optional.of(appId)); } /** * The argument for the {@link PublicKeyCredentialCreationOptions#getAttestation() attestation} * parameter in registration operations. * *

Unless your application has a concrete policy for authenticator attestation, it is * recommended to leave this parameter undefined. * *

If you set this, you may want to explicitly set {@link * RelyingPartyBuilder#allowUntrustedAttestation(boolean) allowUntrustedAttestation} and {@link * RelyingPartyBuilder#attestationTrustSource(AttestationTrustSource) attestationTrustSource} * too. * *

By default, this is not set. * * @see PublicKeyCredentialCreationOptions#getAttestation() * @see §6.4. * Attestation */ public RelyingPartyBuilder attestationConveyancePreference( @NonNull Optional attestationConveyancePreference) { this.attestationConveyancePreference = attestationConveyancePreference; return this; } /** * The argument for the {@link PublicKeyCredentialCreationOptions#getAttestation() attestation} * parameter in registration operations. * *

Unless your application has a concrete policy for authenticator attestation, it is * recommended to leave this parameter undefined. * *

If you set this, you may want to explicitly set {@link * RelyingPartyBuilder#allowUntrustedAttestation(boolean) allowUntrustedAttestation} and {@link * RelyingPartyBuilder#attestationTrustSource(AttestationTrustSource) attestationTrustSource} * too. * *

By default, this is not set. * * @see PublicKeyCredentialCreationOptions#getAttestation() * @see §6.4. * Attestation */ public RelyingPartyBuilder attestationConveyancePreference( @NonNull AttestationConveyancePreference attestationConveyancePreference) { return this.attestationConveyancePreference(Optional.of(attestationConveyancePreference)); } /** * An {@link AttestationTrustSource} instance to use for looking up trust roots for * authenticator attestation. This matters only if {@link #getAttestationConveyancePreference()} * is non-empty and not set to {@link AttestationConveyancePreference#NONE}. * *

By default, this is not set. * * @see PublicKeyCredentialCreationOptions#getAttestation() * @see §6.4. * Attestation */ public RelyingPartyBuilder attestationTrustSource( @NonNull Optional attestationTrustSource) { this.attestationTrustSource = attestationTrustSource; return this; } /** * An {@link AttestationTrustSource} instance to use for looking up trust roots for * authenticator attestation. This matters only if {@link #getAttestationConveyancePreference()} * is non-empty and not set to {@link AttestationConveyancePreference#NONE}. * *

By default, this is not set. * * @see PublicKeyCredentialCreationOptions#getAttestation() * @see §6.4. * Attestation */ public RelyingPartyBuilder attestationTrustSource( @NonNull AttestationTrustSource attestationTrustSource) { return this.attestationTrustSource(Optional.of(attestationTrustSource)); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy