-
Notifications
You must be signed in to change notification settings - Fork 137
/
PublicKeyCredentialCreationOptions.java
269 lines (237 loc) · 11.7 KB
/
PublicKeyCredentialCreationOptions.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
// 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.yubico.internal.util.CollectionUtil;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.TreeSet;
import lombok.Builder;
import lombok.NonNull;
import lombok.Value;
/**
* Parameters for a call to <code>navigator.credentials.create()</code>.
*
* @see <a href="https://www.w3.org/TR/2019/PR-webauthn-20190117/#dictdef-publickeycredentialcreationoptions">§5.4.
* Options for Credential Creation (dictionary PublicKeyCredentialCreationOptions)</a>
*/
@Value
@Builder(toBuilder = true)
public class PublicKeyCredentialCreationOptions {
/**
* Contains data about the Relying Party responsible for the request.
* <p>
* Its value's {@link RelyingPartyIdentity#getId() id} member specifies the <a href="https://www.w3.org/TR/2019/PR-webauthn-20190117/#rp-id">RP
* ID</a> the credential should be scoped to. If omitted, its value will be set by the client. See {@link
* RelyingPartyIdentity} for further details.
* </p>
*/
@NonNull
private final RelyingPartyIdentity rp;
/**
* Contains data about the user account for which the Relying Party is requesting attestation.
*/
@NonNull
private final UserIdentity user;
/**
* A challenge intended to be used for generating the newly created credential’s attestation object. See the <a
* href="https://www.w3.org/TR/2019/PR-webauthn-20190117/#cryptographic-challenges">§13.1 Cryptographic
* Challenges</a> security consideration.
*/
@NonNull
private final ByteArray challenge;
/**
* Information about the desired properties of the credential to be created.
* <p>
* The sequence is ordered from most preferred to least preferred. The client makes a best-effort to create the most
* preferred credential that it can.
* </p>
*/
@NonNull
private final List<PublicKeyCredentialParameters> pubKeyCredParams;
/**
* 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.
*/
@Builder.ObtainVia(method = "wrapTimeout")
private final Long timeout;
/**
* Intended for use by Relying Parties that wish to limit the creation of multiple credentials for the same account
* on a single authenticator. The client is requested to return an error if the new credential would be created on
* an authenticator that also contains one of the credentials enumerated in this parameter.
*/
private final Set<PublicKeyCredentialDescriptor> excludeCredentials;
/**
* Intended for use by Relying Parties that wish to select the appropriate authenticators to participate in the
* create() operation.
*/
private final AuthenticatorSelectionCriteria authenticatorSelection;
/**
* Intended for use by Relying Parties that wish to express their preference for attestation conveyance. The default
* is {@link AttestationConveyancePreference#NONE}.
*/
@NonNull
private final AttestationConveyancePreference attestation;
/**
* Additional parameters requesting additional processing by the client and authenticator.
* <p>
* For example, the caller may request that only authenticators with certain capabilities be used to create the
* credential, or that particular information be returned in the attestation object. Some extensions are defined in
* <a href="https://www.w3.org/TR/2019/PR-webauthn-20190117/#extensions">§9 WebAuthn Extensions</a>; consult the
* IANA "WebAuthn Extension Identifier" registry established by
* <a href="https://tools.ietf.org/html/draft-hodges-webauthn-registries">[WebAuthn-Registries]</a> for an
* up-to-date list of registered WebAuthn Extensions.
* </p>
*/
@NonNull
private final RegistrationExtensionInputs extensions;
@JsonCreator
private PublicKeyCredentialCreationOptions(
@NonNull @JsonProperty("rp") RelyingPartyIdentity rp,
@NonNull @JsonProperty("user") UserIdentity user,
@NonNull @JsonProperty("challenge") ByteArray challenge,
@NonNull @JsonProperty("pubKeyCredParams") List<PublicKeyCredentialParameters> pubKeyCredParams,
@JsonProperty("timeout") Long timeout,
@JsonProperty("excludeCredentials") Set<PublicKeyCredentialDescriptor> excludeCredentials,
@JsonProperty("authenticatorSelection") AuthenticatorSelectionCriteria authenticatorSelection,
@JsonProperty("attestation") AttestationConveyancePreference attestation,
@JsonProperty("extensions") RegistrationExtensionInputs extensions
) {
this.rp = rp;
this.user = user;
this.challenge = challenge;
this.pubKeyCredParams = CollectionUtil.immutableList(pubKeyCredParams);
this.timeout = timeout;
this.excludeCredentials = excludeCredentials == null ? null : CollectionUtil.immutableSortedSet(new TreeSet<>(excludeCredentials));
this.authenticatorSelection = authenticatorSelection;
this.attestation = attestation == null ? AttestationConveyancePreference.NONE : attestation;
this.extensions = extensions == null ? RegistrationExtensionInputs.builder().build() : extensions;
}
public Optional<Long> getTimeout() {
return Optional.ofNullable(timeout);
}
public Optional<Set<PublicKeyCredentialDescriptor>> getExcludeCredentials() {
return Optional.ofNullable(excludeCredentials);
}
public Optional<AuthenticatorSelectionCriteria> getAuthenticatorSelection() {
return Optional.ofNullable(authenticatorSelection);
}
public static PublicKeyCredentialCreationOptionsBuilder.MandatoryStages builder() {
return new PublicKeyCredentialCreationOptionsBuilder.MandatoryStages();
}
public static class PublicKeyCredentialCreationOptionsBuilder {
private Long timeout = null;
private Set<PublicKeyCredentialDescriptor> excludeCredentials = null;
private AuthenticatorSelectionCriteria authenticatorSelection = null;
public static class MandatoryStages {
private PublicKeyCredentialCreationOptionsBuilder builder = new PublicKeyCredentialCreationOptionsBuilder();
/**
* @see PublicKeyCredentialCreationOptions#getRp()
*/
public Step2 rp(RelyingPartyIdentity rp) {
builder.rp(rp);
return new Step2();
}
/**
* @see PublicKeyCredentialCreationOptions#getUser()
*/
public class Step2 {
public Step3 user(UserIdentity user) {
builder.user(user);
return new Step3();
}
}
/**
* @see PublicKeyCredentialCreationOptions#getChallenge()
*/
public class Step3 {
public Step4 challenge(ByteArray challenge) {
builder.challenge(challenge);
return new Step4();
}
}
/**
* @see PublicKeyCredentialCreationOptions#getPubKeyCredParams()
*/
public class Step4 {
public PublicKeyCredentialCreationOptionsBuilder pubKeyCredParams(List<PublicKeyCredentialParameters> pubKeyCredParams) {
return builder.pubKeyCredParams(pubKeyCredParams);
}
}
}
/**
* 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 PublicKeyCredentialCreationOptionsBuilder timeout(@NonNull Optional<Long> timeout) {
this.timeout = timeout.orElse(null);
return this;
}
/**
* 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 PublicKeyCredentialCreationOptionsBuilder timeout(long timeout) {
return this.timeout(Optional.of(timeout));
}
/**
* Intended for use by Relying Parties that wish to limit the creation of multiple credentials for the same account
* on a single authenticator. The client is requested to return an error if the new credential would be created on
* an authenticator that also contains one of the credentials enumerated in this parameter.
*/
public PublicKeyCredentialCreationOptionsBuilder excludeCredentials(Optional<Set<PublicKeyCredentialDescriptor>> excludeCredentials) {
return this.excludeCredentials(excludeCredentials.orElse(null));
}
/**
* Intended for use by Relying Parties that wish to limit the creation of multiple credentials for the same account
* on a single authenticator. The client is requested to return an error if the new credential would be created on
* an authenticator that also contains one of the credentials enumerated in this parameter.
*/
public PublicKeyCredentialCreationOptionsBuilder excludeCredentials(Set<PublicKeyCredentialDescriptor> excludeCredentials) {
this.excludeCredentials = excludeCredentials;
return this;
}
/**
* Intended for use by Relying Parties that wish to select the appropriate authenticators to participate in the
* create() operation.
*/
public PublicKeyCredentialCreationOptionsBuilder authenticatorSelection(@NonNull Optional<AuthenticatorSelectionCriteria> authenticatorSelection) {
return this.authenticatorSelection(authenticatorSelection.orElse(null));
}
/**
* Intended for use by Relying Parties that wish to select the appropriate authenticators to participate in the
* create() operation.
*/
public PublicKeyCredentialCreationOptionsBuilder authenticatorSelection(AuthenticatorSelectionCriteria authenticatorSelection) {
this.authenticatorSelection = authenticatorSelection;
return this;
}
}
// Needed so that Lombok's .toBuilder() doesn't call .timeout(null: long)
private Optional<Long> wrapTimeout() {
return Optional.ofNullable(timeout);
}
}