com.yubico.webauthn.RelyingParty Maven / Gradle / Ivy
Show all versions of webauthn-server-core Show documentation
// 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:
*
*
* - {@link com.yubico.webauthn.data.PublicKeyCredentialParameters#ES256 ES256}
*
- {@link com.yubico.webauthn.data.PublicKeyCredentialParameters#EdDSA EdDSA}
*
- {@link com.yubico.webauthn.data.PublicKeyCredentialParameters#ES256 ES384}
*
- {@link com.yubico.webauthn.data.PublicKeyCredentialParameters#ES256 ES512}
*
- {@link com.yubico.webauthn.data.PublicKeyCredentialParameters#RS256 RS256}
*
- {@link com.yubico.webauthn.data.PublicKeyCredentialParameters#RS384 RS384}
*
- {@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));
}
}
}