com.yubico.webauthn.data.PublicKeyCredentialRequestOptions 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.data;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.yubico.internal.util.CollectionUtil;
import com.yubico.internal.util.JacksonCodecs;
import java.util.List;
import java.util.Optional;
import lombok.Builder;
import lombok.NonNull;
import lombok.Value;
/**
* The PublicKeyCredentialRequestOptions dictionary supplies get() with the data it needs to
* generate an assertion.
*
* Its `challenge` member must be present, while its other members are optional.
*
* @see §5.5.
* Options for Assertion Generation (dictionary PublicKeyCredentialRequestOptions)
*/
@Value
@Builder(toBuilder = true)
public class PublicKeyCredentialRequestOptions {
/**
* A challenge that the selected authenticator signs, along with other data, when producing an
* authentication assertion. See the §13.1
* Cryptographic Challenges security consideration.
*/
@NonNull private final ByteArray challenge;
/**
* Specifies a time, in milliseconds, that the caller is willing to wait for the call to complete.
*
*
This is treated as a hint, and MAY be overridden by the client.
*/
private final Long timeout;
/**
* Specifies the relying party identifier claimed by the caller.
*
*
If omitted, its value will be set by the client.
*/
private final String rpId;
/**
* A list of {@link PublicKeyCredentialDescriptor} objects representing public key credentials
* acceptable to the caller, in descending order of the caller’s preference (the first item in the
* list is the most preferred credential, and so on down the list).
*/
private final List allowCredentials;
/**
* Describes the Relying Party's requirements regarding user
* verification for the navigator.credentials.get()
operation.
*
* Eligible authenticators are filtered to only those capable of satisfying this requirement.
*
*
By default, this is not set. When not set, the default in the browser is {@link
* UserVerificationRequirement#PREFERRED}.
*
* @see UserVerificationRequirement
* @see §5.8.6.
* User Verification Requirement Enumeration (enum UserVerificationRequirement)
* @see User
* Verification
*/
private final UserVerificationRequirement userVerification;
/**
* Additional parameters requesting additional processing by the client and authenticator.
*
*
For example, if transaction confirmation is sought from the user, then the prompt string
* might be included as an extension.
*/
@NonNull @Builder.Default
private final AssertionExtensionInputs extensions = AssertionExtensionInputs.builder().build();
@JsonCreator
private PublicKeyCredentialRequestOptions(
@NonNull @JsonProperty("challenge") ByteArray challenge,
@JsonProperty("timeout") Long timeout,
@JsonProperty("rpId") String rpId,
@JsonProperty("allowCredentials") List allowCredentials,
@JsonProperty("userVerification") UserVerificationRequirement userVerification,
@NonNull @JsonProperty("extensions") AssertionExtensionInputs extensions) {
this.challenge = challenge;
this.timeout = timeout;
this.rpId = rpId;
this.allowCredentials =
allowCredentials == null ? null : CollectionUtil.immutableList(allowCredentials);
this.userVerification = userVerification;
this.extensions = extensions;
}
public Optional getTimeout() {
return Optional.ofNullable(timeout);
}
public Optional> getAllowCredentials() {
return Optional.ofNullable(allowCredentials);
}
public Optional getUserVerification() {
return Optional.ofNullable(userVerification);
}
/**
* Serialize this {@link PublicKeyCredentialRequestOptions} value to JSON suitable for sending to
* the client.
*
* Any {@link ByteArray} values in this data structure will be {@link ByteArray#getBase64Url()
* Base64Url} encoded. Those values MUST be decoded into BufferSource
values (such as
* Uint8Array
) on the client side before calling navigator.credentials.get()
*
.
*
*
After decoding binary values, the resulting JavaScript object is suitable for passing as an
* argument to navigator.credentials.get()
.
*
* @return a JSON value suitable for sending to the client and passing as an argument to
* navigator.credentials.get()
, after decoding binary options from Base64Url strings.
* @throws JsonProcessingException if JSON serialization fails.
*/
public String toCredentialsGetJson() throws JsonProcessingException {
ObjectMapper json = JacksonCodecs.json();
ObjectNode result = json.createObjectNode();
result.set("publicKey", json.valueToTree(this));
return json.writeValueAsString(result);
}
public static PublicKeyCredentialRequestOptionsBuilder.MandatoryStages builder() {
return new PublicKeyCredentialRequestOptionsBuilder.MandatoryStages();
}
public static class PublicKeyCredentialRequestOptionsBuilder {
private Long timeout = null;
private String rpId = null;
private List allowCredentials = null;
public static class MandatoryStages {
private final PublicKeyCredentialRequestOptionsBuilder builder =
new PublicKeyCredentialRequestOptionsBuilder();
/**
* {@link PublicKeyCredentialRequestOptionsBuilder#challenge(ByteArray) challenge} is a
* required parameter.
*
* @see PublicKeyCredentialRequestOptionsBuilder#challenge(ByteArray)
*/
public PublicKeyCredentialRequestOptionsBuilder challenge(ByteArray challenge) {
return builder.challenge(challenge);
}
}
/**
* Specifies a time, in milliseconds, that the caller is willing to wait for the call to
* complete.
*
* This is treated as a hint, and MAY be overridden by the client.
*/
public PublicKeyCredentialRequestOptionsBuilder timeout(@NonNull Optional timeout) {
this.timeout = timeout.orElse(null);
return this;
}
/*
* Workaround, see: https://github.com/rzwitserloot/lombok/issues/2623#issuecomment-714816001
* Consider reverting this workaround if Lombok fixes that issue.
*/
private PublicKeyCredentialRequestOptionsBuilder timeout(Long timeout) {
return this.timeout(Optional.ofNullable(timeout));
}
/**
* Specifies a time, in milliseconds, that the caller is willing to wait for the call to
* complete.
*
* This is treated as a hint, and MAY be overridden by the client.
*/
public PublicKeyCredentialRequestOptionsBuilder timeout(long timeout) {
return this.timeout(Optional.of(timeout));
}
/**
* Specifies the relying party identifier claimed by the caller.
*
*
If omitted, its value will be set by the client.
*/
public PublicKeyCredentialRequestOptionsBuilder rpId(@NonNull Optional rpId) {
return this.rpId(rpId.orElse(null));
}
/**
* Specifies the relying party identifier claimed by the caller.
*
* If omitted, its value will be set by the client.
*/
public PublicKeyCredentialRequestOptionsBuilder rpId(String rpId) {
this.rpId = rpId;
return this;
}
/**
* A list of {@link PublicKeyCredentialDescriptor} objects representing public key credentials
* acceptable to the caller, in descending order of the caller’s preference (the first item in
* the list is the most preferred credential, and so on down the list).
*/
public PublicKeyCredentialRequestOptionsBuilder allowCredentials(
@NonNull Optional> allowCredentials) {
return this.allowCredentials(allowCredentials.orElse(null));
}
/**
* A list of {@link PublicKeyCredentialDescriptor} objects representing public key credentials
* acceptable to the caller, in descending order of the caller’s preference (the first item in
* the list is the most preferred credential, and so on down the list).
*/
public PublicKeyCredentialRequestOptionsBuilder allowCredentials(
List allowCredentials) {
this.allowCredentials = allowCredentials;
return this;
}
}
}