diff --git a/index.bs b/index.bs index 663a8bc..208675e 100644 --- a/index.bs +++ b/index.bs @@ -73,6 +73,12 @@ spec: promises-guide-1; urlPrefix: https://www.w3.org/2001/tag/doc/promises-guid spec: web-otp; urlPrefix: https://wicg.github.io/web-otp type: interface text: OTPCredential; url: otpcredential +spec: password-credentials; urlPrefix: https://specs.lukewarlow.dev/password-credentials/ + type: interface + text: PasswordCredential; url: passwordcredential +spec: federated-credentials; urlPrefix: https://specs.lukewarlow.dev/federated-credentials/ + type: interface + text: FederatedCredential; url: federatedcredential
@@ -107,6 +113,16 @@ spec:css-syntax-3;
"authors": [ "Marcos Cáceres", "Sam Goto" ],
"href": "https://wicg.github.io/digital-credentials/",
"title": "Digital Credentials"
+ },
+ "FEDERATED-CREDENTIALS": {
+ "authors": [ ],
+ "href": "https://specs.lukewarlow.dev/federated-credentials/",
+ "title": "Federated Credentials"
+ },
+ "PASSWORD-CREDENTIALS": {
+ "authors": [ ],
+ "href": "https://specs.lukewarlow.dev/password-credentials/",
+ "title": "Password Credentials"
}
}
@@ -212,8 +228,7 @@ spec:css-syntax-3;
obtain them.
Various [=credential type registry/credential types=] are each represented to JavaScript as an interface which
- [=interface/inherits=], either directly or indirectly, from the {{Credential}} interface. This
- document defines two such interfaces, {{PasswordCredential}} and {{FederatedCredential}}. Other
+ [=interface/inherits=], either directly or indirectly, from the {{Credential}} interface. Other
specifications, for example [[WEBAUTHN]], define other credential types.
A [=credential=] is effective for a particular [=origin=] if it
@@ -341,7 +356,7 @@ spec:css-syntax-3;
dictionary CredentialCreationOptions {
@@ -1288,770 +1302,6 @@ spec:css-syntax-3;
-
-
- # Password Credentials # {#passwords}
-
- For good or for ill, many websites rely on username/password pairs as an authentication mechanism.
- The {{PasswordCredential}} interface is a [=credential=] meant to enable this use case, storing
- both a username and password, as well as metadata that can help a user choose the right account
- from within a [=credential chooser=].
-
- ## Examples ## {#password-examples}
-
- ### Password-based Sign-in ### {#examples-password-signin}
-
-
- MegaCorp, Inc. supports passwords, and can use {{get()|navigator.credentials.get()}} to obtain
- username/password pairs from a user's [=credential store=]:
-
-
- navigator.credentials
- .get({ 'password': true })
- .then(credential => {
- if (!credential) {
- // The user either doesn't have credentials for this site, or
- // refused to share them. Insert some code here to fall back to
- // a basic login form.
- return;
- }
- if (credential.type == 'password') {
- var form = new FormData();
- form.append('username_field', credential.id);
- form.append('password_field', credential.password);
- var opt = {
- method: 'POST',
- body: form,
- credentials: 'include' // Send cookies.
- };
- fetch('https://example.com/loginEndpoint', opt)
- .then(function (response) {
- if (/* |response| indicates a successful login */) {
- // Record that the credential was effective. See note below.
- navigator.credentials.store(credential);
- // Notify the user that sign-in succeeded! Do amazing, signed-in things!
- // Maybe navigate to a landing page via location.href =
- // '/signed-in-experience'?
- } else {
- // Insert some code here to fall back to a basic login form.
- }
- });
- }
- });
-
-
- Alternatively, the website could just copy the credential data into a <{form}> and call
- {{HTMLFormElement/submit()}} on the form:
-
-
- navigator.credentials
- .get({ 'password': true })
- .then(credential => {
- if (!credential) {
- return; // as above...
- }
- if (credential.type === 'password') {
- document.querySelector('input[name=username_field]').value =
- credential.id;
- document.querySelector('input[name=password_field]').value =
- credential.password;
- document.getElementById('myform').submit();
- }
- });
-
-
- Note that the former method is much preferred, as it contains an explicit call
- to {{CredentialsContainer/store()}} and saves the credentials. The <{form}> based mechanism
- relies on form submission, which navigates the browsing context, making it difficult to
- ensure that {{store()}} is called after successful sign-in.
-
-
- Note: The [=credential chooser=] presented by the user agent could allow the user to choose
- credentials that aren't actually stored for the current origin. For instance, it might offer up
- credentials from `https://m.example.com` when signing into `https://www.example.com` (as
- described in [[#security-credential-access]]), or it might allow a user to create a new
- credential on the fly. Developers can deal gracefully with this uncertainty by calling
- {{CredentialsContainer/store()}} every time credentials are successfully used, even right after
- credentials have been retrieved from {{CredentialsContainer/get()}}: if the credentials aren't
- yet stored for the origin, the user will be given the opportunity to do so. If they are stored,
- the user won't be prompted.
-
- ### Post-sign-in Confirmation ### {#examples-post-signin}
-
- To ensure that users are offered to store new credentials after a successful sign-in, they can
- to be passed to {{CredentialsContainer/store()}}.
-
-
- If a user is signed in by submitting the credentials to a sign-in endpoint via
- fetch(), we can check the response to determine whether the user
- was signed in successfully, and notify the user agent accordingly. Given a sign-in form like the
- following:
-
-
- <form action="https://example.com/login" method="POST" id="theForm">
- <label for="username">Username</label>
- <input type="text" id="username" name="username" autocomplete="username">
- <label for="password">Password</label>
- <input type="password" id="password" name="password" autocomplete="current-password">
- <input type="submit">
- </form>
-
-
- Then the developer can handle the form submission with something like the following handler:
-
-
- document.querySelector('#theForm').addEventListener('submit', e => {
- if (window.PasswordCredential) {
- e.preventDefault();
-
- // Construct a new PasswordCredential from the HTMLFormElement
- // that fired the "submit" event: this will suck up the values of the fields
- // labeled with "username" and "current-password" autocomplete
- // attributes:
- var c = new PasswordCredential(e.target);
-
- // Fetch the form's action URL, passing that new credential object in
- // as a FormData object. If the response indicates success, tell the user agent
- // so it can ask the user to store the password for future use:
- var opt = {
- method: 'POST',
- body: new FormData(e.target),
- credentials: 'include' // Send cookies.
- };
- fetch(e.target.action, opt).then(r => {
- if (/* |r| is a "successful" Response */)
- navigator.credentials.store(c);
- });
- }
- });
-
-
-
- ### Change Password ### {#examples-change-password}
-
- This same storage mechanism can be reused for "password change" with no modifications: if the
- user changes their credentials, the website can notify the user agent that they've successfully
- signed in with new credentials. The user agent can then update the credentials it stores:
-
-
- MegaCorp Inc. allows users to change their passwords by POSTing data to
- a backend server asynchronously. After doing so successfully, they can
- update the user's credentials by calling {{CredentialsContainer/store()}}
- with the new information.
-
- Given a password change form like the following:
-
-
- <form action="https://example.com/changePassword" method="POST" id="theForm">
- <input type="hidden" name="username" autocomplete="username" value="user">
- <label for="password">New Password</label>
- <input type="password" id="password" name="password" autocomplete="new-password">
- <input type="submit">
- </form>
-
-
- The developer can handle the form submission with something like the following:
-
-
- document.querySelector('#theForm').addEventListener('submit', e => {
- if (window.PasswordCredential) {
- e.preventDefault();
-
- // Construct a new PasswordCredential from the HTMLFormElement
- // that fired the "submit" event: this will suck up the values of the fields
- // labeled with "username" and "new-password" autocomplete
- // attributes:
- var c = new PasswordCredential(e.target);
-
- // Fetch the form's action URL, passing that new credential object in
- // as a FormData object. If the response indicates success, tell the user agent
- // so it can ask the user to store the password for future use:
- var opt = {
- method: 'POST',
- body: new FormData(e.target),
- credentials: 'include' // Send cookies.
- };
- fetch(e.target.action, opt).then(r => {
- if (/* |r| is a "successful" Response */)
- navigator.credentials.store(c);
- });
- }
- });
-
-
-
- ## The `PasswordCredential` Interface ## {#passwordcredential-interface}
-
-
- [Exposed=Window,
- SecureContext]
- interface PasswordCredential : Credential {
- constructor(HTMLFormElement form);
- constructor(PasswordCredentialData data);
- readonly attribute USVString password;
- };
- PasswordCredential includes CredentialUserData;
-
- partial dictionary CredentialRequestOptions {
- boolean password = false;
- };
-
-
- : password
- :: This attribute represents the password of the credential.
-
- : {{Credential/[[type]]}}
- :: The {{PasswordCredential}} [=interface object=] has an internal slot named `[[type]]` whose
- value is "`password`".
-
- : {{Credential/[[discovery]]}}
- :: The {{PasswordCredential}} [=interface object=] has an internal slot named `[[discovery]]`
- whose value is "{{Credential/[[discovery]]/credential store}}".
-
- : PasswordCredential(form)
- :: This constructor accepts an {{HTMLFormElement}} (|form|), and runs the following steps:
-
- 1. Let |origin| be the [=current settings object=]'s [=environment settings object/origin=].
-
- 2. Let |r| be the result of executing Create a `PasswordCredential` from
- an `HTMLFormElement` given |form| and |origin|.
-
- 3. If |r| is an [=exception=], [=throw=] |r|.
-
- Otherwise, return |r|.
-
- : PasswordCredential(data)
- :: This constructor accepts a {{PasswordCredentialData}} (|data|), and runs the following steps:
-
- 1. Let |r| be the result of executing Create a `PasswordCredential` from
- `PasswordCredentialData` on |data|.
-
- 2. If |r| is an [=exception=], [=throw=] |r|.
-
- Otherwise, return |r|.
-
-
- {{PasswordCredential}} objects can be created via
- {{CredentialsContainer/create()|navigator.credentials.create()}}
- either explicitly by passing in a {{PasswordCredentialData}} dictionary, or based on the contents
- of an {{HTMLFormElement}}'s [=submittable elements=].
-
-
- dictionary PasswordCredentialData : CredentialData {
- USVString name;
- USVString iconURL;
- required USVString origin;
- required USVString password;
- };
-
- typedef (PasswordCredentialData or HTMLFormElement) PasswordCredentialInit;
-
- partial dictionary CredentialCreationOptions {
- PasswordCredentialInit password;
- };
-
-
- {{PasswordCredential}} objects are [=Credential/origin bound=].
-
- {{PasswordCredential}}'s [=interface object=] inherits {{Credential}}'s implementation of
- {{Credential/[[DiscoverFromExternalSource]](origin, options, sameOriginWithAncestors)}}, and defines
- its own implementation of
- {{PasswordCredential/[[CollectFromCredentialStore]](origin, options, sameOriginWithAncestors)}},
- {{PasswordCredential/[[Create]](origin, options, sameOriginWithAncestors)}}, and
- {{PasswordCredential/[[Store]](credential, sameOriginWithAncestors)}}.
-
- ## Algorithms ## {#passwordcredential-algorithms}
-
-
- `PasswordCredential`'s `[[CollectFromCredentialStore]](origin, options, sameOriginWithAncestors)`
-
-
- \[[CollectFromCredentialStore]](origin, options, sameOriginWithAncestors)
- is called with an [=origin=] (|origin|), a {{CredentialRequestOptions}} (|options|),
- and a boolean which is `true` if and only if the calling context is [=same-origin with its ancestors=]
- (|sameOriginWithAncestors|).
- The algorithm returns a set of {{Credential}} objects from
- the [=credential store=]. If no matching {{Credential}} objects are available, the returned set
- will be empty.
-
- The algorithm will throw a `NotAllowedError` if |sameOriginWithAncestors| is not `true`.
-
-
- 1. Assert: |options|["{{CredentialRequestOptions/password}}"] [=map/exists=].
-
- 2. If |sameOriginWithAncestors| is `false`, throw a "{{NotAllowedError}}" {{DOMException}}.
-
- Note: This restriction aims to address the concern raised in [[#security-origin-confusion]].
-
- 3. Return the empty set if |options|["{{CredentialRequestOptions/password}}"] is not `true`.
-
- 4. Return the result of retrieving
- credentials from the [=credential store=] that match the following filter:
-
- 1. The credential is a {{PasswordCredential}}
- 2. The credential's {{Credential/[[origin]]}} is the [=same origin=] as |origin|.
-
-
-
- `PasswordCredential`'s `[[Create]](origin, options, sameOriginWithAncestors)`
-
-
- \[[Create]](origin, options, sameOriginWithAncestors)
- is called with an [=origin=] (|origin|), a
- {{CredentialCreationOptions}} (|options|), and a boolean which is `true` if and only if the calling
- context is [=same-origin with its ancestors=] (|sameOriginWithAncestors|).
- The algorithm returns a {{PasswordCredential}} if one can be created,
- `null` otherwise. The {{CredentialCreationOptions}} dictionary must have a `password` member which
- holds either an {{HTMLFormElement}} or a {{PasswordCredentialData}}. If that member's value cannot be
- used to create a {{PasswordCredential}}, this algorithm will throw a {{TypeError}} [=exception=].
-
-
- 1. Assert: |options|["{{CredentialCreationOptions/password}}"] [=map/exists=], and
- |sameOriginWithAncestors| is unused.
-
- 2. If |options|["{{CredentialCreationOptions/password}}"] is an {{HTMLFormElement}}, return the
- result of executing Create a `PasswordCredential` from an
- `HTMLFormElement` given |options|["{{CredentialCreationOptions/password}}"] and |origin|.
- Rethrow any exceptions.
-
- 3. If |options|["{{CredentialCreationOptions/password}}"] is a {{PasswordCredentialData}}, return
- the result of executing Create a `PasswordCredential` from
- `PasswordCredentialData` given |options|["{{CredentialCreationOptions/password}}"].
- Rethrow any exceptions.
-
- 4. Throw a {{TypeError}} [=exception=].
-
-
-
- `PasswordCredential`'s `[[Store]](credential, sameOriginWithAncestors)`
-
-
- \[[Store]](credential, sameOriginWithAncestors) is
- called with a {{PasswordCredential}} (|credential|), and a boolean which is `true` if and only if the calling
- context is [=same-origin with its ancestors=] (|sameOriginWithAncestors|). The algorithm returns
- `undefined` once |credential| is persisted to the [=credential store=].
-
- The algorithm will return a `NotAllowedError` if |sameOriginWithAncestors| is not `true`.
-
-
- 1. Throw a "{{NotAllowedError}}" {{DOMException}} without altering the user agent's
- [=credential store=] if |sameOriginWithAncestors| is `false`.
-
- Note: This restriction aims to address the concern raised in [[#security-origin-confusion]].
-
- 2. If the user agent's [=credential store=] contains a {{PasswordCredential}} (|stored|)
- whose {{Credential/id}} attribute is |credential|'s {{Credential/id}} and whose
- {{[[origin]]}} slot is the [=same origin=] as |credential|'s {{Credential/[[origin]]}},
- then:
-
- 1. If the user grants permission to update credentials (as discussed when defining
- [=user mediation=]), then:
-
- 1. Set |stored|'s `password` to |credential|'s
- `password`.
-
- 2. Set |stored|'s {{CredentialUserData/name}} to |credential|'s
- {{CredentialUserData/name}}.
-
- 3. Set |stored|'s {{CredentialUserData/iconURL}} to |credential|'s
- {{CredentialUserData/iconURL}}.
-
- Otherwise, if the user grants permission to store credentials (as discussed when
- defining [=user mediation=], then:
-
- 1. Store a {{PasswordCredential}} in the [=credential store=] with the following
- properties:
-
- : {{Credential/id}}
- :: |credential|'s {{Credential/id}}
- : {{CredentialUserData/name}},
- :: |credential|'s {{CredentialUserData/name}}
- : {{CredentialUserData/iconURL}}
- :: |credential|'s {{CredentialUserData/iconURL}}
- : {{Credential/[[origin]]}}
- :: |credential|'s {{Credential/[[origin]]}}
- : `password`
- :: |credential|'s `password`
-
-
-
-
- Create a `PasswordCredential` from an `HTMLFormElement`
-
-
- To Create a `PasswordCredential` from an `HTMLFormElement`, given an
- {{HTMLFormElement}} (|form|) and an [=origin=] (|origin|), run these steps.
-
- Note: [[#examples-post-signin]] and [[#examples-change-password]] provide examples of the intended
- usage.
-
-
- 1. Let |data| be a new {{PasswordCredentialData}} dictionary.
-
- 2. Set |data|'s {{PasswordCredentialData/origin}} member's value to |origin|'s value.
-
- 3. Let |formData| be the result of executing the {{FormData}} constructor
- on |form|.
-
- 4. Let |elements| be a list of all the [=submittable elements=] whose [=form owner=] is |form|, in [=tree order=].
-
- 5. Let |newPasswordObserved| be `false`.
-
- 6. For each |field| in |elements|, run the following steps:
-
- 1. If |field| does not have an <{input/autocomplete}> attribute, then skip to the next
- |field|.
-
- 2. Let |name| be the value of |field|'s <{input/name}> attribute.
-
- 3. If |formData|'s {{FormData/has()}} method returns `false` when executed on |name|, then
- skip to the next |field|.
-
- 4. If |field|'s <{input/autocomplete}> attribute's value contains one or more [=autofill
- detail tokens=] (|tokens|), then:
-
- 1. For each |token| in |tokens|:
-
- 1. If |token| is an [=ASCII case-insensitive=] match for one
- of the following strings, run the associated steps:
-
- : "`new-password`"
- :: Set |data|'s {{PasswordCredentialData/password}} member's
- value to the result of executing |formData|'s
- {{FormData/get()}} method on |name|, and |newPasswordObserved| to `true`.
-
- : "`current-password`"
- :: If |newPasswordObserved| is `false`,
- set |data|'s {{PasswordCredentialData/password}} member's
- value to the result of executing |formData|'s
- {{FormData/get()}} method on |name|.
-
- Note: By checking that |newPasswordObserved| is `false`,
- `new-password` fields take precedence over
- `current-password` fields.
-
- : "`photo`"
- :: Set |data|'s {{CredentialUserData/iconURL}} member's
- value to the result of executing |formData|'s
- {{FormData/get()}} method on |name|.
-
- : "`name`"
- : "`nickname`"
- :: Set |data|'s {{CredentialUserData/name}} member's
- value to the result of executing |formData|'s
- {{FormData/get()}} method on |name|.
-
- : "`username`"
- :: Set |data|'s {{CredentialData/id}} member's value to the
- result of executing |formData|'s {{FormData/get()}} method
- on |name|.
-
- 7. Let |c| be the result of executing Create a `PasswordCredential` from
- `PasswordCredentialData` on |data|. If that threw an [=exception=], rethrow that
- exception.
-
- 8. Assert: |c| is a {{PasswordCredential}}.
-
- 9. Return |c|.
-
-
-
- Create a `PasswordCredential` from `PasswordCredentialData`
-
-
- To Create a `PasswordCredential` from `PasswordCredentialData`, given an
- {{PasswordCredentialData}} (|data|), run these steps.
-
-
- 1. Let |c| be a new {{PasswordCredential}} object.
-
- 2. If any of the following are the empty string, throw a {{TypeError}} [=exception=]:
-
- * |data|'s {{CredentialData/id}} member's value
- * |data|'s {{PasswordCredentialData/origin}} member's value
- * |data|'s {{PasswordCredentialData/password}} member's value
-
- 3. Set |c|'s properties as follows:
-
- : `password`
- :: |data|'s {{PasswordCredentialData/password}} member's value
- : {{Credential/id}}
- :: |data|'s {{CredentialData/id}} member's value
- : {{CredentialUserData/iconURL}}
- :: |data|'s {{PasswordCredentialData/iconURL}} member's value
- : {{CredentialUserData/name}}
- :: |data|'s {{PasswordCredentialData/name}} member's value
- : {{Credential/[[origin]]}}
- :: |data|'s {{PasswordCredentialData/origin}} member's value.
-
- 4. Return |c|.
-
-
-
- `CredentialRequestOptions` Matching for `PasswordCredential`
-
-
- Given a {{CredentialRequestOptions}} (|options|), the following algorithm returns "`Matches`" if
- the {{PasswordCredential}} should be available as a response to a {{CredentialsContainer/get()}}
- request, and "`Does Not Match`" otherwise.
-
- 1. If |options| has a {{CredentialRequestOptions/password}} member whose value is `true`, then
- return "`Matches`".
-
- 2. Return "`Does Not Match`".
-
-
-
-
-
- # Federated Credentials # {#federated}
-
- ## The `FederatedCredential` Interface ## {#federatedcredential-interface}
-
-
- [Exposed=Window,
- SecureContext]
- interface FederatedCredential : Credential {
- constructor(FederatedCredentialInit data);
- readonly attribute USVString provider;
- readonly attribute DOMString? protocol;
- };
- FederatedCredential includes CredentialUserData;
-
- dictionary FederatedCredentialRequestOptions {
- sequence<USVString> providers;
- sequence<DOMString> protocols;
- };
-
- partial dictionary CredentialRequestOptions {
- FederatedCredentialRequestOptions federated;
- };
-
-
- : provider
- :: The credential's federated identity provider. See [[#provider-identification]] for
- details regarding valid formats.
-
- : protocol
- :: The credential's federated identity provider's protocol (e.g. "`openidconnect`"). If the
- value is `null`, then the protocol can be inferred from the
- {{FederatedCredential/provider}}.
-
- : {{Credential/[[type]]}}
- :: The {{FederatedCredential}} [=interface object=] has an internal slot named `[[type]]` whose
- value is "`federated`".
-
- : {{Credential/[[discovery]]}}
- :: The {{FederatedCredential}} [=interface object=] has an internal slot named `[[discovery]]`
- whose value is "{{Credential/[[discovery]]/credential store}}".
-
- : FederatedCredential(data)
- :: This constructor accepts a {{FederatedCredentialInit}} (|data|), and runs the following steps:
-
- 1. Let |r| be the result of executing Create a `FederatedCredential` from
- `FederatedCredentialInit` on |data|. If that threw an [=exception=], rethrow that
- exception.
-
- 2. Return |r|.
-
-
- {{FederatedCredential}} objects can be created by passing a {{FederatedCredentialInit}} dictionary
- into {{CredentialsContainer/create()|navigator.credentials.create()}}.
-
-
- dictionary FederatedCredentialInit : CredentialData {
- USVString name;
- USVString iconURL;
- required USVString origin;
- required USVString provider;
- DOMString protocol;
- };
-
- partial dictionary CredentialCreationOptions {
- FederatedCredentialInit federated;
- };
-
-
- {{FederatedCredential}} objects are [=Credential/origin bound=].
-
- {{FederatedCredential}}'s [=interface object=] inherits {{Credential}}'s implementation of
- {{Credential/[[DiscoverFromExternalSource]](origin, options, sameOriginWithAncestors)}},
- and defines its own implementation of
- {{FederatedCredential/[[CollectFromCredentialStore]](origin, options, sameOriginWithAncestors)}},
- {{FederatedCredential/[[Create]](origin, options, sameOriginWithAncestors)}}, and
- {{FederatedCredential/[[Store]](credential, sameOriginWithAncestors)}}.
-
- Note: If, in the future, we teach the user agent to obtain authentication tokens on a user's
- behalf, we could do so by building an implementation of
- `[[DiscoverFromExternalSource]](origin, options, sameOriginWithAncestors)`.
-
- ### Identifying Providers ### {#provider-identification}
-
- Every site should use the same identifier when referring to a specific federated identity
- provider. For example,
- Facebook Login
- shouldn't be referred to as "Facebook" and "Facebook Login" and "FB" and "FBL" and "Facebook.com"
- and so on. It should have a canonical identifier which everyone can make use of, as consistent
- identification makes it possible for user agents to be helpful.
-
- For consistency, federations passed into the APIs defined in this document (e.g.
- {{FederatedCredentialRequestOptions}}'s {{FederatedCredentialRequestOptions/providers}} array, or
- {{FederatedCredential}}'s {{FederatedCredential/provider}} property) MUST be identified by the
- ASCII serialization of the origin the provider uses
- for sign in. That is, Facebook would be represented by `https://www.facebook.com` and Google by
- `https://accounts.google.com`.
-
- This serialization of an [=origin=] does _not_ include a trailing U+002F SOLIDUS ("`/`"), but
- user agents SHOULD accept them silently: `https://accounts.google.com/` is clearly
- intended to be the same as `https://accounts.google.com`.
-
- ## Algorithms ## {#federatedcredential-algorithms}
-
-
- `FederatedCredential`'s `[[CollectFromCredentialStore]](origin, options, sameOriginWithAncestors)`
-
-
- \[[CollectFromCredentialStore]](origin, options, sameOriginWithAncestors)
- is called with an [=origin=] (|origin|), a {{CredentialRequestOptions}} (|options|),
- and a boolean which is `true` if and only if the calling context is [=same-origin with its ancestors=] (|sameOriginWithAncestors|).
- The algorithm returns a set of {{Credential}} objects from
- the [=credential store=]. If no matching {{Credential}} objects are available, the returned set
- will be empty.
-
-
- 1. Assert: |options|["{{CredentialRequestOptions/federated}}"] [=map/exists=].
-
- 2. If |sameOriginWithAncestors| is `false`, throw a "{{NotAllowedError}}" {{DOMException}}.
-
- Note: This restriction aims to address the concern raised in [[#security-origin-confusion]].
-
- 3. Return the empty set if |options|["{{CredentialRequestOptions/federated}}"] is not `true`.
-
- 4. Return the result of retrieving
- credentials from the [=credential store=] that match the following filter:
-
- 1. The credential is a {{FederatedCredential}}
- 2. The credential's {{Credential/[[origin]]}} is the [=same origin=] as |origin|.
- 3. If |options|["{{CredentialRequestOptions/federated}}"]["{{FederatedCredentialRequestOptions/providers}}"]
- [=map/exists=], its value [=list/contains=] the credentials's {{FederatedCredential/provider}}.
- 4. If |options|["{{CredentialRequestOptions/federated}}"]["{{FederatedCredentialRequestOptions/protocols}}"]
- [=map/exists=], its value [=list/contains=] the credentials's {{FederatedCredential/protocol}}.
-
-
-
- `FederatedCredential`'s `[[Create]](origin, options, sameOriginWithAncestors)`
-
-
- \[[Create]](origin, options, sameOriginWithAncestors)
- is called with an [=origin=] (|origin|), a
- {{CredentialCreationOptions}} (|options|), and a boolean which is `true` if and only if the
- calling context is [=same-origin with its ancestors=] (|sameOriginWithAncestors|).
- The algorithm returns a {{FederatedCredential}} if one can be created,
- `null` otherwise, or throws an [=exception=] in exceptional circumstances:
-
-
- 1. Assert: |options|["{{CredentialCreationOptions/federated}}"] [=map/exists=], and
- |sameOriginWithAncestors| is unused.
-
- 2. Set |options|["{{CredentialCreationOptions/federated}}"]'s {{FederatedCredentialInit/origin}}
- member's value to |origin|'s value.
-
- 3. Return the result of executing Create a `FederatedCredential` from
- `FederatedCredentialInit` given |options|["{{CredentialCreationOptions/federated}}"].
- If that threw an [=exception=], then rethrow that exception.
-
-
-
- `FederatedCredential`'s `[[Store]](credential, sameOriginWithAncestors)`
-
-
- \[[Store]](credential, sameOriginWithAncestors) is
- called with a {{FederatedCredential}} (|credential|), and a boolean which is `true` if and only if the
- calling context is [=same-origin with its ancestors=] (|sameOriginWithAncestors|). The algorithm
- returns `undefined` once |credential| is persisted to the [=credential store=].
-
- The algorithm will return a `NotAllowedError` if |sameOriginWithAncestors| is not `true`.
-
-
- 1. Throw a "{{NotAllowedError}}" {{DOMException}} without altering the user agent's
- [=credential store=] if sameOriginWithAncestors is `false`.
-
- Note: This restriction aims to address the concern raised in [[#security-origin-confusion]].
-
- 2. If the user agent's [=credential store=] contains a {{FederatedCredential}} whose
- {{Credential/id}} attribute is |credential|'s {{Credential/id}} and whose {{[[origin]]}}
- slot is the [=same origin=] as |credential|'s {{Credential/[[origin]]}}, and
- whose {{FederatedCredential/provider}} is |credential|'s
- {{FederatedCredential/provider}}, then return.
-
- 3. If the user grants permission to store credentials (as discussed when defining
- [=user mediation=]), then store a {{FederatedCredential}} in the [=credential store=] with
- the following properties:
-
- : {{Credential/id}}
- :: |credential|'s {{Credential/id}}
- : {{CredentialUserData/name}},
- :: |credential|'s {{CredentialUserData/name}}
- : {{CredentialUserData/iconURL}}
- :: |credential|'s {{CredentialUserData/iconURL}}
- : {{Credential/[[origin]]}}
- :: |credential|'s {{Credential/[[origin]]}}
- : {{FederatedCredential/provider}}
- :: |credential|'s {{FederatedCredential/provider}}
- : {{FederatedCredential/protocol}}
- :: |credential|'s {{FederatedCredential/protocol}}
-
-
-
- Create a `FederatedCredential` from `FederatedCredentialInit`
-
-
-
- To Create a `FederatedCredential` from `FederatedCredentialInit`, given a
- {{FederatedCredentialInit}} (|init|), run these steps.
-
-
- 1. Let |c| be a new {{FederatedCredential}} object.
-
- 2. If any of the following are the empty string, throw a {{TypeError}} [=exception=]:
-
- * |init|.{{CredentialData/id}}'s value
- * |init|.{{FederatedCredentialInit/provider}}'s value
-
- 3. Set |c|'s properties as follows:
-
- : {{Credential/id}}
- :: |init|.{{CredentialData/id}}'s value
- : {{FederatedCredential/provider}}
- :: |init|.{{FederatedCredentialInit/provider}}'s value
- : {{CredentialUserData/iconURL}}
- :: |init|.{{CredentialUserData/iconURL}}'s value
- : {{CredentialUserData/name}}
- :: |init|.{{CredentialUserData/name}}'s value
- : {{Credential/[[origin]]}}
- :: |init|.{{FederatedCredentialInit/origin}}'s value.
-
- 4. Return |c|.
-
-
-
-