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 @@ -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; {{FederatedCredential}} null null - This specification: [[#federated]] + [[FEDERATED-CREDENTIALS]] W3C @@ -368,7 +383,7 @@ spec:css-syntax-3; {{PasswordCredential}} null null - This specification: [[#passwords]] + [[PASSWORD-CREDENTIALS]] W3C @@ -513,7 +528,7 @@ spec:css-syntax-3; Unless otherwise specified, each [=interface object=] created for interfaces which [=interface/inherit=] from {{Credential}} MUST provide implementations for at least one of these internal methods, overriding {{Credential}}'s default implementations, as appropriate for the [=credential=] type. E.g., - [[#passwordcredential-interface]], [[#federatedcredential-interface]], and [[WEBAUTHN]]. + [[PASSWORD-CREDENTIALS]], [[FEDERATED-CREDENTIALS]], and [[WEBAUTHN]].
`[[CollectFromCredentialStore]]` internal method
\[[CollectFromCredentialStore]](origin, options, sameOriginWithAncestors) @@ -945,8 +960,7 @@ spec:css-syntax-3; Note: The {{CredentialCreationOptions}} dictionary is an extension point. If and when new types of credentials are introduced, they will add to the dictionary so they can be passed into the - creation method. See [[#implementation-extension]], and the extensions introduced in this document: - [[#passwordcredential-interface]] and [[#federatedcredential-interface]]. + creation method. See [[#implementation-extension]].
     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|. -
- -
-