You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: Sources/WebAuthn/WebAuthnClient.swift
+55-30Lines changed: 55 additions & 30 deletions
Original file line number
Diff line number
Diff line change
@@ -152,7 +152,7 @@ public struct WebAuthnClient {
152
152
/// Step 25. While lifetimeTimer has not expired, perform the following actions depending upon lifetimeTimer, and the state and response for each authenticator in authenticators:
153
153
do{
154
154
/// Let the caller do what it needs to do to coordinate with authenticators, so long as at least one of them calls the attestation callback.
155
-
letresult:AttestationObject=tryawaitwithCancellableFirstSuccessfulContinuation{[attestRegistration, publicKeyCredentialParameters] continuation in
155
+
varattestationObjectResult:AttestationObject=tryawaitwithCancellableFirstSuccessfulContinuation{[attestRegistration, publicKeyCredentialParameters] continuation in
156
156
/// → If lifetimeTimer expires,
157
157
/// For each authenticator in issuedRequests invoke the authenticatorCancel operation on authenticator and remove authenticator from issuedRequests.
158
158
Task{
@@ -213,41 +213,66 @@ public struct WebAuthnClient {
213
213
/// whose value is an AuthenticationExtensionsClientOutputs object containing extension identifier → client extension output entries. The entries are created by running each extension’s client extension processing algorithm to create the client extension outputs, for each client extension in pkOptions.extensions.
214
214
/// 3. Let constructCredentialAlg be an algorithm that takes a global object global, and whose steps are:
215
215
/// 1. If credentialCreationData.attestationConveyancePreferenceOption’s value is
216
-
/// → none
217
-
/// Replace potentially uniquely identifying information with non-identifying versions of the same:
218
-
/// 1. If the aaguid in the attested credential data is 16 zero bytes, credentialCreationData.attestationObjectResult.fmt is "packed", and "x5c" is absent from credentialCreationData.attestationObjectResult, then self attestation is being used and no further action is needed.
219
-
/// 2. Otherwise
220
-
/// 1. Replace the aaguid in the attested credential data with 16 zero bytes.
221
-
/// 2. Set the value of credentialCreationData.attestationObjectResult.fmt to "none", and set the value of credentialCreationData.attestationObjectResult.attStmt to be an empty CBOR map. (See § 8.7 None Attestation Statement Format and § 6.5.4 Generating an Attestation Object).
222
-
/// → indirect
223
-
/// The client MAY replace the aaguid and attestation statement with a more privacy-friendly and/or more easily verifiable version of the same data (for example, by employing an Anonymization CA).
224
-
/// → direct or enterprise
225
-
/// Convey the authenticator's AAGUID and attestation statement, unaltered, to the Relying Party.
216
+
switch options.attestation {
217
+
/// → none
218
+
case.none:
219
+
/// Replace potentially uniquely identifying information with non-identifying versions of the same:
220
+
/// 1. If the aaguid in the attested credential data is 16 zero bytes, credentialCreationData.attestationObjectResult.fmt is "packed", and "x5c" is absent from credentialCreationData.attestationObjectResult, then self attestation is being used and no further action is needed.
221
+
/// 2. Otherwise
222
+
if attestationObjectResult.authenticatorData.attestedData?.authenticatorAttestationGUID !=.anonymous,
/// 2. Set the value of credentialCreationData.attestationObjectResult.fmt to "none", and set the value of credentialCreationData.attestationObjectResult.attStmt to be an empty CBOR map. (See § 8.7 None Attestation Statement Format and § 6.5.4 Generating an Attestation Object).
228
+
attestationObjectResult.format =.none
229
+
attestationObjectResult.attestationStatement =[:]
230
+
}
231
+
/// → indirect
232
+
/// The client MAY replace the aaguid and attestation statement with a more privacy-friendly and/or more easily verifiable version of the same data (for example, by employing an Anonymization CA).
233
+
/// → direct or enterprise
234
+
/// Convey the authenticator's AAGUID and attestation statement, unaltered, to the Relying Party.
235
+
}
226
236
/// 5. Let attestationObject be a new ArrayBuffer, created using global’s %ArrayBuffer%, containing the bytes of credentialCreationData.attestationObjectResult’s value.
/// 7. Let pubKeyCred be a new PublicKeyCredential object associated with global whose fields are:
229
-
/// [[identifier]]
230
-
/// id
231
-
/// authenticatorAttachment
232
-
/// The AuthenticatorAttachment value matching the current authenticator attachment modality of authenticator.
233
-
/// response
234
-
/// A new AuthenticatorAttestationResponse object associated with global whose fields are:
235
-
/// clientDataJSON
236
-
/// A new ArrayBuffer, created using global’s %ArrayBuffer%, containing the bytes of credentialCreationData.clientDataJSONResult.
237
-
/// attestationObject
238
-
/// attestationObject
239
-
/// [[transports]]
240
-
/// A sequence of zero or more unique DOMStrings, in lexicographical order, that the authenticator is believed to support. The values SHOULD be members of AuthenticatorTransport, but client platforms MUST ignore unknown values.
241
-
/// If a user agent does not wish to divulge this information it MAY substitute an arbitrary sequence designed to preserve privacy. This sequence MUST still be valid, i.e. lexicographically sorted and free of duplicates. For example, it may use the empty sequence. Either way, in this case the user agent takes the risk that Relying Party behavior may be suboptimal.
242
-
/// If the user agent does not have any transport information, it SHOULD set this field to the empty sequence.
243
-
/// NOTE: How user agents discover transports supported by a given authenticator is outside the scope of this specification, but may include information from an attestation certificate (for example [FIDO-Transports-Ext]), metadata communicated in an authenticator protocol such as CTAP2, or special-case knowledge about a platform authenticator.
244
-
/// [[clientExtensionsResults]]
245
-
/// A new ArrayBuffer, created using global’s %ArrayBuffer%, containing the bytes of credentialCreationData.clientExtensionResults.
244
+
letpublicKeyCredential=RegistrationCredential(
245
+
/// [[identifier]]
246
+
/// id
247
+
id: credentialID,
248
+
/// authenticatorAttachment
249
+
/// The AuthenticatorAttachment value matching the current authenticator attachment modality of authenticator.
250
+
/// response
251
+
/// A new AuthenticatorAttestationResponse object associated with global whose fields are:
/// A new ArrayBuffer, created using global’s %ArrayBuffer%, containing the bytes of credentialCreationData.clientDataJSONResult.
255
+
clientDataJSON:Array(clientDataJSON),
256
+
/// attestationObject
257
+
/// attestationObject
258
+
attestationObject: attestationObject
259
+
/// [[transports]]
260
+
/// A sequence of zero or more unique DOMStrings, in lexicographical order, that the authenticator is believed to support. The values SHOULD be members of AuthenticatorTransport, but client platforms MUST ignore unknown values.
261
+
/// If a user agent does not wish to divulge this information it MAY substitute an arbitrary sequence designed to preserve privacy. This sequence MUST still be valid, i.e. lexicographically sorted and free of duplicates. For example, it may use the empty sequence. Either way, in this case the user agent takes the risk that Relying Party behavior may be suboptimal.
262
+
/// If the user agent does not have any transport information, it SHOULD set this field to the empty sequence.
263
+
/// NOTE: How user agents discover transports supported by a given authenticator is outside the scope of this specification, but may include information from an attestation certificate (for example [FIDO-Transports-Ext]), metadata communicated in an authenticator protocol such as CTAP2, or special-case knowledge about a platform authenticator.
264
+
)
265
+
/// [[clientExtensionsResults]]
266
+
/// A new ArrayBuffer, created using global’s %ArrayBuffer%, containing the bytes of credentialCreationData.clientExtensionResults.
267
+
)
246
268
/// 8. Return pubKeyCred.
269
+
// Returned below.
270
+
247
271
/// 4. For each remaining authenticator in issuedRequests invoke the authenticatorCancel operation on authenticator and remove it from issuedRequests.
248
-
/// 5. Return constructCredentialAlg and terminate this algorithm.
272
+
// Already performed.
249
273
250
-
throwWebAuthnError.unsupported
274
+
/// 5. Return constructCredentialAlg and terminate this algorithm.
275
+
return publicKeyCredential
251
276
}catch{
252
277
/// Step 35. Throw a "NotAllowedError" DOMException. In order to prevent information leak that could identify the user without consent, this step MUST NOT be executed before lifetimeTimer has expired. See § 14.5.1 Registration Ceremony Privacy for details.
253
278
/// During the above process, the user agent SHOULD show some UI to the user to guide them in the process of selecting and authorizing an authenticator.
0 commit comments