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
/// See https://w3c.github.io/webauthn/#sctn-discover-from-external-source
303
+
/// Step 1. Assert: options.publicKey is present.
304
+
/// Step 2. Let pkOptions be the value of options.publicKey.
305
+
/// Step 3. If options.mediation is present with the value conditional:
306
+
/// 1. Let credentialIdFilter be the value of pkOptions.allowCredentials.
307
+
/// 2. Set pkOptions.allowCredentials to empty.
308
+
/// NOTE: This prevents non-discoverable credentials from being used during conditional requests.
309
+
/// 3. Set a timer lifetimeTimer to a value of infinity.
310
+
/// NOTE: lifetimeTimer is set to a value of infinity so that the user has the entire lifetime of the Document to interact with any input form control tagged with a "webauthn" autofill detail token. For example, upon the user clicking in such an input field, the user agent can render a list of discovered credentials for the user to select from, and perhaps also give the user the option to "try another way".
311
+
/// Step 4. Else:
312
+
/// 1. Let credentialIdFilter be an empty list.
313
+
/// 2. If pkOptions.timeout is present, check if its value lies within a reasonable range as defined by the client and if not, correct it to the closest value lying within that range. Set a timer lifetimeTimer to this adjusted value. If pkOptions.timeout is not present, then set lifetimeTimer to a client-specific default.
314
+
/// See the recommended range and default for a WebAuthn ceremony timeout for guidance on deciding a reasonable range and default for pkOptions.timeout.
315
+
/// NOTE: The user agent should take cognitive guidelines into considerations regarding timeout for users with special needs.
316
+
/// Step 5. Let callerOrigin be origin. If callerOrigin is an opaque origin, throw a "NotAllowedError" DOMException.
317
+
/// Step 6. Let effectiveDomain be the callerOrigin’s effective domain. If effective domain is not a valid domain, then throw a "SecurityError" DOMException.
318
+
/// NOTE: An effective domain may resolve to a host, which can be represented in various manners, such as domain, ipv4 address, ipv6 address, opaque host, or empty host. Only the domain format of host is allowed here. This is for simplification and also is in recognition of various issues with using direct IP address identification in concert with PKI-based security.
319
+
/// Step 7. If pkOptions.rpId is not present, then set rpId to effectiveDomain.
320
+
/// Otherwise:
321
+
/// 1. If pkOptions.rpId is not a registrable domain suffix of and is not equal to effectiveDomain, throw a "SecurityError" DOMException.
322
+
/// 2. Set rpId to pkOptions.rpId.
323
+
/// NOTE: rpId represents the caller’s RP ID. The RP ID defaults to being the caller’s origin's effective domain unless the caller has explicitly set pkOptions.rpId when calling get().
324
+
/// Step 8. Let clientExtensions be a new map and let authenticatorExtensions be a new map.
325
+
/// Step 9. If pkOptions.extensions is present, then for each extensionId → clientExtensionInput of pkOptions.extensions:
326
+
/// 1. If extensionId is not supported by this client platform or is not an authentication extension, then continue.
327
+
/// 2. Set clientExtensions[extensionId] to clientExtensionInput.
328
+
/// 3. If extensionId is not an authenticator extension, then continue.
329
+
/// 4. Let authenticatorExtensionInput be the (CBOR) result of running extensionId’s client extension processing algorithm on clientExtensionInput. If the algorithm returned an error, continue.
330
+
/// 5. Set authenticatorExtensions[extensionId] to the base64url encoding of authenticatorExtensionInput.
331
+
/// Step 10. Let collectedClientData be a new CollectedClientData instance whose fields are:
332
+
/// type
333
+
/// The string "webauthn.get".
334
+
/// challenge
335
+
/// The base64url encoding of pkOptions.challenge
336
+
/// origin
337
+
/// The serialization of callerOrigin.
338
+
/// topOrigin
339
+
/// The serialization of callerOrigin’s top-level origin if the sameOriginWithAncestors argument passed to this internal method is false, else undefined.
340
+
/// crossOrigin
341
+
/// The inverse of the value of the sameOriginWithAncestors argument passed to this internal method.
342
+
/// Step 11. Let clientDataJSON be the JSON-compatible serialization of client data constructed from collectedClientData.
343
+
/// Step 12. Let clientDataHash be the hash of the serialized client data represented by clientDataJSON.
344
+
/// Step 13. If options.signal is present and aborted, throw the options.signal’s abort reason.
345
+
/// Step 14. Let issuedRequests be a new ordered set.
346
+
/// Step 15. Let savedCredentialIds be a new map.
347
+
/// Step 16. Let authenticators represent a value which at any given instant is a set of client platform-specific handles, where each item identifies an authenticator presently available on this client platform at that instant.
348
+
/// NOTE: What qualifies an authenticator as "available" is intentionally unspecified; this is meant to represent how authenticators can be hot-plugged into (e.g., via USB) or discovered (e.g., via NFC or Bluetooth) by the client by various mechanisms, or permanently built into the client.
349
+
/// Step 17. Let silentlyDiscoveredCredentials be a new map whose entries are of the form: DiscoverableCredentialMetadata → authenticator.
350
+
/// Step 18. Consider the value of hints and craft the user interface accordingly, as the user-agent sees fit.
351
+
/// Step 19. Start lifetimeTimer.
352
+
/// Step 20. While lifetimeTimer has not expired, perform the following actions depending upon lifetimeTimer, and the state and response for each authenticator in authenticators:
353
+
/// → If lifetimeTimer expires,
354
+
/// For each authenticator in issuedRequests invoke the authenticatorCancel operation on authenticator and remove authenticator from issuedRequests.
355
+
/// → If the user exercises a user agent user-interface option to cancel the process,
356
+
/// For each authenticator in issuedRequests invoke the authenticatorCancel operation on authenticator and remove authenticator from issuedRequests. Throw a "NotAllowedError" DOMException.
357
+
/// → If options.signal is present and aborted,
358
+
/// For each authenticator in issuedRequests invoke the authenticatorCancel operation on authenticator and remove authenticator from issuedRequests. Then throw the options.signal’s abort reason.
359
+
/// → If options.mediation is conditional and the user interacts with an input or textarea form control with an autocomplete attribute whose non-autofill credential type is "webauthn",
360
+
/// Note: The "webauthn" autofill detail token must appear immediately after the last autofill detail token of type "Normal" or "Contact". For example:
361
+
/// "username webauthn"
362
+
/// "current-password webauthn"
363
+
/// 1. If silentlyDiscoveredCredentials is not empty:
364
+
/// 1. Prompt the user to optionally select a DiscoverableCredentialMetadata (credentialMetadata) from silentlyDiscoveredCredentials.
365
+
/// NOTE: The prompt shown SHOULD include values from credentialMetadata’s otherUI such as name and displayName.
366
+
/// 2. If the user selects a credentialMetadata,
367
+
/// 1. Let publicKeyOptions be a temporary copy of pkOptions.
368
+
/// 2. Let authenticator be the value of silentlyDiscoveredCredentials[credentialMetadata].
369
+
/// 3. Set publicKeyOptions.allowCredentials to be a list containing a single PublicKeyCredentialDescriptor item whose id's value is set to credentialMetadata’s id's value and whoseid value is set to credentialMetadata’s type.
370
+
/// 4. Execute the issuing a credential request to an authenticator algorithm with authenticator, savedCredentialIds, publicKeyOptions, rpId, clientDataHash, and authenticatorExtensions.
371
+
/// If this returns false, continue.
372
+
/// 5. Append authenticator to issuedRequests.
373
+
/// → If options.mediation is not conditional, issuedRequests is empty, pkOptions.allowCredentials is not empty, and no authenticator will become available for any public key credentials therein,
374
+
/// Indicate to the user that no eligible credential could be found. When the user acknowledges the dialog, throw a "NotAllowedError" DOMException.
375
+
/// NOTE: One way a client platform can determine that no authenticator will become available is by examining the transports members of the present PublicKeyCredentialDescriptor items of pkOptions.allowCredentials, if any. For example, if all PublicKeyCredentialDescriptor items list only internal, but all platform authenticators have been tried, then there is no possibility of satisfying the request. Alternatively, all PublicKeyCredentialDescriptor items may list transports that the client platform does not support.
376
+
/// → If an authenticator becomes available on this client device,
377
+
/// NOTE: This includes the case where an authenticator was available upon lifetimeTimer initiation.
378
+
/// 1. If options.mediation is conditional and the authenticator supports the silentCredentialDiscovery operation:
379
+
/// 1. Let collectedDiscoveredCredentialMetadata be the result of invoking the silentCredentialDiscovery operation on authenticator with rpId as parameter.
380
+
/// 2. For each credentialMetadata of collectedDiscoveredCredentialMetadata:
381
+
/// 1. If credentialIdFilter is empty or credentialIdFilter contains an item whose id's value is set to credentialMetadata’s id, set silentlyDiscoveredCredentials[credentialMetadata] to authenticator.
382
+
/// NOTE: A request will be issued to this authenticator upon user selection of a credential via interaction with a particular UI context (see here for details).
383
+
/// 2. Else:
384
+
/// 1. Execute the issuing a credential request to an authenticator algorithm with authenticator, savedCredentialIds, pkOptions, rpId, clientDataHash, and authenticatorExtensions.
385
+
/// If this returns false, continue.
386
+
/// NOTE: This branch is taken if options.mediation is conditional and the authenticator does not support the silentCredentialDiscovery operation to allow use of such authenticators during a conditional user mediation request.
387
+
/// 2. Append authenticator to issuedRequests.
388
+
/// → If an authenticator ceases to be available on this client device,
389
+
/// Remove authenticator from issuedRequests.
390
+
/// → If any authenticator returns a status indicating that the user cancelled the operation,
391
+
/// 1. Remove authenticator from issuedRequests.
392
+
/// 2. For each remaining authenticator in issuedRequests invoke the authenticatorCancel operation on authenticator and remove it from issuedRequests.
393
+
/// NOTE: Authenticators may return an indication of "the user cancelled the entire operation". How a user agent manifests this state to users is unspecified.
394
+
/// → If any authenticator returns an error status,
395
+
/// Remove authenticator from issuedRequests.
396
+
/// → If any authenticator indicates success,
397
+
/// 1. Remove authenticator from issuedRequests.
398
+
/// 2. Let assertionCreationData be a struct whose items are:
399
+
/// credentialIdResult
400
+
/// If savedCredentialIds[authenticator] exists, set the value of credentialIdResult to be the bytes of savedCredentialIds[authenticator]. Otherwise, set the value of credentialIdResult to be the bytes of the credential ID returned from the successful authenticatorGetAssertion operation, as defined in § 6.3.3 The authenticatorGetAssertion Operation.
401
+
/// clientDataJSONResult
402
+
/// whose value is the bytes of clientDataJSON.
403
+
/// authenticatorDataResult
404
+
/// whose value is the bytes of the authenticator data returned by the authenticator.
405
+
/// signatureResult
406
+
/// whose value is the bytes of the signature value returned by the authenticator.
407
+
/// userHandleResult
408
+
/// If the authenticator returned a user handle, set the value of userHandleResult to be the bytes of the returned user handle. Otherwise, set the value of userHandleResult to null.
409
+
/// clientExtensionResults
410
+
/// 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.
411
+
/// 3. If credentialIdFilter is not empty and credentialIdFilter does not contain an item whose id's value is set to the value of credentialIdResult, continue.
412
+
/// 4. If credentialIdFilter is empty and userHandleResult is null, continue.
413
+
/// 5. Let constructAssertionAlg be an algorithm that takes a global object global, and whose steps are:
414
+
/// 1. Let pubKeyCred be a new PublicKeyCredential object associated with global whose fields are:
415
+
/// [[identifier]]
416
+
/// A new ArrayBuffer, created using global’s %ArrayBuffer%, containing the bytes of assertionCreationData.credentialIdResult.
417
+
/// authenticatorAttachment
418
+
/// The AuthenticatorAttachment value matching the current authenticator attachment modality of authenticator.
419
+
/// response
420
+
/// A new AuthenticatorAssertionResponse object associated with global whose fields are:
421
+
/// clientDataJSON
422
+
/// A new ArrayBuffer, created using global’s %ArrayBuffer%, containing the bytes of assertionCreationData.clientDataJSONResult.
423
+
/// authenticatorData
424
+
/// A new ArrayBuffer, created using global’s %ArrayBuffer%, containing the bytes of assertionCreationData.authenticatorDataResult.
425
+
/// signature
426
+
/// A new ArrayBuffer, created using global’s %ArrayBuffer%, containing the bytes of assertionCreationData.signatureResult.
427
+
/// userHandle
428
+
/// If assertionCreationData.userHandleResult is null, set this field to null. Otherwise, set this field to a new ArrayBuffer, created using global’s %ArrayBuffer%, containing the bytes of assertionCreationData.userHandleResult.
429
+
/// [[clientExtensionsResults]]
430
+
/// A new ArrayBuffer, created using global’s %ArrayBuffer%, containing the bytes of assertionCreationData.clientExtensionResults.
431
+
/// 2. Return pubKeyCred.
432
+
/// 6. For each remaining authenticator in issuedRequests invoke the authenticatorCancel operation on authenticator and remove it from issuedRequests.
433
+
/// 7. Return constructAssertionAlg and terminate this algorithm.
434
+
/// Step 31. 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.2 Authentication Ceremony Privacy for details.
302
435
/*
303
436
1. Perform setup and massage inputs
304
437
2. Prepare callback for assertion that an authenticator can call
0 commit comments