Skip to content

Commit

Permalink
wip: Conditional UI + autofill specification.
Browse files Browse the repository at this point in the history
  • Loading branch information
nsatragno committed Oct 26, 2021
1 parent b1454fc commit 2e58c0f
Showing 1 changed file with 140 additions and 81 deletions.
221 changes: 140 additions & 81 deletions index.bs
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,11 @@ spec: html; urlPrefix: https://html.spec.whatwg.org/multipage/
text: opaque origin; url: concept-origin-opaque
text: tuple origin; url: concept-origin-tuple
text: document.domain; url:dom-document-domain
urlPrefix: input.html
text: input; url: the-input-element
urlPrefix: form-control-infrastructure
text: autocomplete; url: attr-fe-autocomplete
text: autofill hint set; url: autofill-hint-set

spec: url; urlPrefix: https://url.spec.whatwg.org
type: dfn
Expand Down Expand Up @@ -304,6 +309,7 @@ spec: BCP47; urlPrefix: https://tools.ietf.org/html/bcp47
<pre class="link-defaults">
spec:credential-management; type:dfn; text:credentials
spec:html; type:dfn; for:environment settings object; text:global object
spec:html; type:dfn; for:input; text:autocomplete
spec:infra; type:dfn; for:/; text:set
spec:infra; type:dfn; text:list
spec:infra; type:dfn; for:struct; text:item
Expand Down Expand Up @@ -1954,6 +1960,106 @@ This
{{CredentialsContainer/get()|navigator.credentials.get()}} operation can be aborted by leveraging the {{AbortController}};
see [[dom#abortcontroller-api-integration]] for detailed instructions.

#### <dfn for="PublicKeyCredential" algorithm="Issuing a request to an authenticator">Issuing a request to an authenticator</dfn> #### {#sctn-issuing-request-to-authenticator}

This algorithm accepts two arguments:

<dl dfn-type="argument" dfn-for="Issuing a request to an authenticator">
: <dfn>authenticator</dfn>
:: A [=client platform=]-specific handle identifying an [=authenticator=] presently available on this [=client platform=].

: <dfn>options</dfn>
:: This argument is a {{CredentialRequestOptions}} object whose
<code>|options|.{{CredentialRequestOptions/publicKey}}</code> member contains a {{PublicKeyCredentialRequestOptions}}
object specifying the desired attributes of the [=public key credential=] to discover.
</dl>

The steps for [=issuing a request to an |authenticator|=] are as follows:

1. If <code>|options|.{{PublicKeyCredentialRequestOptions/userVerification}}</code> is set to
{{UserVerificationRequirement/required}} and the |authenticator| is not capable of performing [=user verification=],
[=iteration/continue=].

1. Let |userVerification| be the <dfn>effective user verification requirement for assertion</dfn>, a Boolean value, as
follows. If <code>|options|.{{PublicKeyCredentialRequestOptions/userVerification}}</code>

<dl class="switch">

: is set to {{UserVerificationRequirement/required}}
:: Let |userVerification| be [TRUE].

: is set to {{UserVerificationRequirement/preferred}}
:: If the |authenticator|

<dl class="switch">
: is capable of [=user verification=]
:: Let |userVerification| be [TRUE].

: is not capable of [=user verification=]
:: Let |userVerification| be [FALSE].
</dl>

: is set to {{UserVerificationRequirement/discouraged}}
:: Let |userVerification| be [FALSE].

</dl>

1. <span id="allowCredentialDescriptorListCreation"></span>
If <code>|options|.{{PublicKeyCredentialRequestOptions/allowCredentials}}</code>
<dl class="switch">
: [=list/is not empty=]
:: 1. Let |allowCredentialDescriptorList| be a new [=list=].

1. Execute a [=client platform=]-specific procedure to determine which, if any, [=public key credentials=] described by
<code>|options|.{{PublicKeyCredentialRequestOptions/allowCredentials}}</code> are [=bound credential|bound=] to this
|authenticator|, by matching with |rpId|,
<code>|options|.{{PublicKeyCredentialRequestOptions/allowCredentials}}.{{PublicKeyCredentialDescriptor/id}}</code>,
and
<code>|options|.{{PublicKeyCredentialRequestOptions/allowCredentials}}.{{PublicKeyCredentialDescriptor/type}}</code>.
Set |allowCredentialDescriptorList| to this filtered list.

1. If |allowCredentialDescriptorList| [=list/is empty=], [=continue=].

1. Let |distinctTransports| be a new [=ordered set=].

1. If |allowCredentialDescriptorList| has exactly one value, set
<code>|savedCredentialIds|[|authenticator|]</code> to <code>|allowCredentialDescriptorList|[0].id</code>'s
value (see [here](#authenticatorGetAssertion-return-values) in [[#sctn-op-get-assertion]] for more information).

1. [=list/For each=] credential descriptor |C| in |allowCredentialDescriptorList|,
[=set/append=] each value, if any, of <code>|C|.{{transports}}</code> to |distinctTransports|.

Note: This will aggregate only distinct values of {{transports}} (for this [=authenticator=]) in
|distinctTransports| due to the properties of [=ordered sets=].

1. If |distinctTransports|
<dl class="switch">
: [=list/is not empty=]
:: The client selects one |transport| value from |distinctTransports|, possibly incorporating local
configuration knowledge of the appropriate transport to use with |authenticator| in making its
selection.

Then, using |transport|, invoke the [=authenticatorGetAssertion=] operation on
|authenticator|, with |rpId|, |clientDataHash|, |allowCredentialDescriptorList|,
|userVerification|, and |authenticatorExtensions| as parameters.

: [=list/is empty=]
:: Using local configuration knowledge of the appropriate transport to use with |authenticator|,
invoke the [=authenticatorGetAssertion=] operation on |authenticator| with |rpId|,
|clientDataHash|, |allowCredentialDescriptorList|, |userVerification|, and
|authenticatorExtensions| as parameters.
</dl>

: [=list/is empty=]
:: Using local configuration knowledge of the appropriate transport to use with |authenticator|, invoke the
[=authenticatorGetAssertion=] operation on |authenticator| with |rpId|, |clientDataHash|,
|userVerification| and |authenticatorExtensions| as parameters.

Note: In this case, the [=[RP]=] did not supply a list of acceptable credential descriptors. Thus, the
authenticator is being asked to exercise any credential it may possess that is [=scoped=] to
the [=[RP]=], as identified by |rpId|.
</dl>

#### PublicKeyCredential's <code><dfn for="PublicKeyCredential" method>\[[DiscoverFromExternalSource]](origin, options, sameOriginWithAncestors)</dfn></code> Method #### {#sctn-discover-from-external-source}

<div link-for-hint="PublicKeyCredential/[[DiscoverFromExternalSource]](origin, options, sameOriginWithAncestors)">
Expand Down Expand Up @@ -2098,6 +2204,20 @@ When this method is invoked, the user agent MUST execute the following algorithm
[=authenticators=] can be <a href="https://en.wikipedia.org/w/index.php?title=Hot_plug">hot-plugged</a> 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=].

1. Let |silentlyDiscoveredCredentials| be an empty set.

1. If |conditionalFlow| is [TRUE]:

1. [=set/For each=] |authenticator| in |authenticators|:

1. If |authenticator| is not a [=platform authenticator=], then [=continue=].

1. Invoke the [=silent credential discovery=] operation on |authenticator| with |rpId| as parameter.

1. For every |credential| returned:

1. Add |credential| to |silentlyDiscoveredCredentials|.

1. Start |lifetimeTimer|.

1. [=While=] |lifetimeTimer| has not expired, perform the following actions depending upon |lifetimeTimer|,
Expand All @@ -2113,6 +2233,23 @@ When this method is invoked, the user agent MUST execute the following algorithm
:: [=set/For each=] |authenticator| in |issuedRequests| invoke the [=authenticatorCancel=] operation on |authenticator|
and [=set/remove=] |authenticator| from |issuedRequests|. Return a {{DOMException}} whose name is "{{NotAllowedError}}".

: If |conditionalFlow| is [TRUE] and the user interacts with an [=input=] form control with a `"webauthn"`
[=autocomplete=] [=autofill hint set=],
:: 1. Prompt the user to optionally select a [=public key credential source=] from |silentlyDiscoveredCredentials|.

1. If the user selects a |credential|,

1. Let |optionsCopy| be a temporary copy of |options|.

1. Let |authenticator| be the authenticator containing |credential|.

1. Set <code>|optionsCopy|.{{PublicKeyCredentialRequestOptions/allowCredentials}}</code> to be a list with a
single [=public key credential=] |credential|.

1. Execute the [=issuing a request to an authenticator=] algorithm with |authenticator| and |optionsCopy|.

1. [=set/Append=] |authenticator| to |issuedRequests|.

: If the {{CredentialRequestOptions/signal}} member is present and the [=AbortSignal/aborted flag=] is set to
[TRUE],
:: [=set/For each=] |authenticator| in |issuedRequests| invoke the [=authenticatorCancel=] operation on |authenticator|
Expand All @@ -2127,89 +2264,11 @@ When this method is invoked, the user agent MUST execute the following algorithm
: If an |authenticator| becomes available on this [=client device=],
:: Note: This includes the case where an |authenticator| was available upon |lifetimeTimer| initiation.

1. If <code>|options|.{{PublicKeyCredentialRequestOptions/userVerification}}</code> is set to
{{UserVerificationRequirement/required}} and the |authenticator| is not capable of performing [=user verification=],
[=iteration/continue=].

1. Let |userVerification| be the <dfn>effective user verification requirement for assertion</dfn>, a Boolean value, as
follows. If <code>|options|.{{PublicKeyCredentialRequestOptions/userVerification}}</code>

<dl class="switch">

: is set to {{UserVerificationRequirement/required}}
:: Let |userVerification| be [TRUE].

: is set to {{UserVerificationRequirement/preferred}}
:: If the |authenticator|

<dl class="switch">
: is capable of [=user verification=]
:: Let |userVerification| be [TRUE].

: is not capable of [=user verification=]
:: Let |userVerification| be [FALSE].
</dl>

: is set to {{UserVerificationRequirement/discouraged}}
:: Let |userVerification| be [FALSE].

</dl>

1. <span id="allowCredentialDescriptorListCreation"></span>
If <code>|options|.{{PublicKeyCredentialRequestOptions/allowCredentials}}</code>
<dl class="switch">
: [=list/is not empty=]
:: 1. Let |allowCredentialDescriptorList| be a new [=list=].

1. Execute a [=client platform=]-specific procedure to determine which, if any, [=public key credentials=] described by
<code>|options|.{{PublicKeyCredentialRequestOptions/allowCredentials}}</code> are [=bound credential|bound=] to this
|authenticator|, by matching with |rpId|,
<code>|options|.{{PublicKeyCredentialRequestOptions/allowCredentials}}.{{PublicKeyCredentialDescriptor/id}}</code>,
and
<code>|options|.{{PublicKeyCredentialRequestOptions/allowCredentials}}.{{PublicKeyCredentialDescriptor/type}}</code>.
Set |allowCredentialDescriptorList| to this filtered list.

1. If |allowCredentialDescriptorList| [=list/is empty=], [=continue=].

1. Let |distinctTransports| be a new [=ordered set=].

1. If |allowCredentialDescriptorList| has exactly one value, set
<code>|savedCredentialIds|[|authenticator|]</code> to <code>|allowCredentialDescriptorList|[0].id</code>'s
value (see [here](#authenticatorGetAssertion-return-values) in [[#sctn-op-get-assertion]] for more information).

1. [=list/For each=] credential descriptor |C| in |allowCredentialDescriptorList|,
[=set/append=] each value, if any, of <code>|C|.{{transports}}</code> to |distinctTransports|.

Note: This will aggregate only distinct values of {{transports}} (for this [=authenticator=]) in
|distinctTransports| due to the properties of [=ordered sets=].

1. If |distinctTransports|
<dl class="switch">
: [=list/is not empty=]
:: The client selects one |transport| value from |distinctTransports|, possibly incorporating local
configuration knowledge of the appropriate transport to use with |authenticator| in making its
selection.

Then, using |transport|, invoke the [=authenticatorGetAssertion=] operation on
|authenticator|, with |rpId|, |clientDataHash|, |allowCredentialDescriptorList|,
|userVerification|, and |authenticatorExtensions| as parameters.

: [=list/is empty=]
:: Using local configuration knowledge of the appropriate transport to use with |authenticator|,
invoke the [=authenticatorGetAssertion=] operation on |authenticator| with |rpId|,
|clientDataHash|, |allowCredentialDescriptorList|, |userVerification|, and
|authenticatorExtensions| as parameters.
</dl>
1. If the |authenticator| is a [=platform authenticator=] and |conditionalFlow| is [TRUE], then [=continue=].

: [=list/is empty=]
:: Using local configuration knowledge of the appropriate transport to use with |authenticator|, invoke the
[=authenticatorGetAssertion=] operation on |authenticator| with |rpId|, |clientDataHash|,
|userVerification| and |authenticatorExtensions| as parameters.
Note: A request will be issued to this authenticator upon user selection of a {{PublicKeyCredentialSource}}.

Note: In this case, the [=[RP]=] did not supply a list of acceptable credential descriptors. Thus, the
authenticator is being asked to exercise any credential it may possess that is [=scoped=] to
the [=[RP]=], as identified by |rpId|.
</dl>
1. Execute the [=issuing a request to an authenticator=] algorithm with |authenticator| and |options|.

1. [=set/Append=] |authenticator| to |issuedRequests|.

Expand Down

0 comments on commit 2e58c0f

Please sign in to comment.