1. Introduction
This section is not normative.
Signing into websites is more difficult than it should be. The user agent is in a unique position to improve the experience in a number of ways, and most modern user agents have recognized this by providing some measure of credential management natively in the browser. For example, users can save usernames and passwords for websites; those credentials are later autofilled into sign-in forms, albeit with varying degrees of success.
The autocomplete
attribute offers a declarative mechanism by which websites can work
with user agents to improve the latter’s ability to detect and fill sign-in forms by marking
specific fields as "username" or "password", and user agents implement a wide variety of detection
heuristics to work with websites which haven’t taken the time to provide this detail in markup.
While this combination of heuristic and declarative detection works relatively well, the status
quo leaves some large gaps where detection is problematic. Sites with uncommon sign-in
mechanisms (submitting credentials via XMLHttpRequest
[XMLHTTPREQUEST], for instance) are
difficult to reliably detect, as is the increasingly common case in which users wish to
authenticate themselves using a federated identity provider. Allowing websites to more directly
interact with the user agent’s credential manager would allow the credential manager to be more
accurate on the one hand, and to assist users with federated sign-in on the other.
These use cases are explored in more detail in § 1.1 Use Cases and in Credential Management: Use Cases and Requirements; this specification attempts to address many of the requirements that document outlines by defining a Credential Manager API which a website can use to request credentials for a user, and to ask the user agent to persist credentials when a user signs in successfully.
Note: The API defined here is intentionally small and simple: it does not intend to provide authentication in and of itself, but is limited to providing an interface to the existing credential managers implemented by existing user agents. That functionality is valuable right now, without significant effort on the part of either vendors or authors. There’s certainly quite a bit more which could be done, of course. See § 9 Future Work for some thoughts we’ve punted for now, but which could be explored in future iterations of this API.
1.1. Use Cases
Modern user agents generally offer users the capability to save passwords when signing into a website, and likewise offer the capability to fill those passwords into sign-in forms fully- or semi-automatically when users return to a website. From the perspective of a website, this behavior is completely invisible: the website doesn’t know that passwords have been stored, and it isn’t notified that passwords have been filled. This is both good and bad. On the one hand, a user agent’s password manager works regardless of whether or not a site cooperates, which is excellent for users. On the other, the password managers' behaviors are a fragile and proprietary hodgepodge of heuristics meant to detect and fill sign-in forms, password change forms, etc.
A few problems with the status quo stand out as being particularly noteworthy:
-
User agents have an incredibly difficult time helping users with federated identity providers. While detecting a username/password form submission is fairly straightforward, detecting sign-in via a third-party is quite difficult to reliably do well. It would be nice if a website could help the user agent understand the intent behind the redirects associated with a typical federated sign-in action.
-
Likewise, user agents struggle to detect more esoteric sign-in mechanisms than simple username/password forms. Authors increasingly asynchronously sign users in via
XMLHttpRequest
or similar mechanisms in order to improve the experience and take more control over the presentation. This is good for users, but tough for user agents to integrate into their password managers. It would be nice if a website could help the user agent make sense of the sign-in mechanism they choose to use. -
Finally, changing passwords is less well-supported than it could be if the website explicitly informed the user agent that credentials had changed.
2. Core API
From a developer’s perspective, a credential is an
object which allows a developer to make an authentication decision for a particular action. This
section defines a generic and extensible Credential
interface which serves as a base class
for credentials defined in this and other documents, along with a set of APIs
hanging off of navigator.credentials.*
which enable developers to
obtain them.
Various credential types are each represented to JavaScript as an interface which inherits, either directly or indirectly, from the Credential
interface. This
document defines two such interfaces, PasswordCredential
and FederatedCredential
. Other
specifications, for example [WEBAUTHN], define other credential types.
A credential is effective for a particular origin if it is accepted as authentication on that origin. Even if a credential is effective at a particular point in time, the UA can’t assume that the same credential will be effective at any future time, for a couple reasons:
-
A password credential may stop being effective if the account holder changes their password.
-
A credential made from a token received over SMS is likely to only be effective for a single use.
Single-use credentials are generated by a credential source, which could be a private key, access to a federated account, the ability to receive SMS messages at a particular phone number, or something else. Credential sources are not exposed to Javascript or explicitly represented in this specification. To unify the model, we consider a password to be a credential source on its own, which is simply copied to create password credentials.
Even though the UA can’t assume that an effective credential will still be effective if used a
second time, or that a credential source that has generated an effective credential will be able
to generate a second effective credential in the future, the second is more likely than the first.
By recording (with store()
) which credentials have been effective in the
past, the UA has a better chance of offering effective credential
sources to the user in the future.
2.1. Infrastructure
User agents MUST internally provide a credential store, which is a vendor-specific, opaque storage mechanism to record which credentials have been effective. It offers the following capabilities for credential access and persistence:
-
Store a credential for later retrieval. This accepts a credential, and inserts it into the credential store.
-
Retrieve a list of credentials. This accepts an arbitrary filter, and returns a set of credentials that match the filter.
-
Modify a credential. This accepts a credential, and overwrites the state of an existing credential in the credential store.
Additionally, the credential store should maintain a prevent silent access
flag for origins (which is set to true
unless otherwise specified).
An origin requires user mediation if its flag is set to true
.
Note: The importance of user mediation is discussed in more detail in § 5 User Mediation.
Note: The credential store is an internal implementation detail of a user agent’s implementation of the API specified in this document, and is not exposed to the web directly. More capabilities may be specified by other documents in support of specific credential types.
This document depends on the Infra Standard for a number of foundational concepts used in its algorithms and prose [INFRA].
Each environment settings object has an associated active credential types, a set which is initially empty.
2.1.1. Infrastructure Algorithms
2.1.1.1. Same-Origin with its Ancestors
An environment settings object (settings) is same-origin with its
ancestors if the following algorithm returns true
:
-
If settings’s relevant global object has no associated Document, return
false
. -
Let document be settings’ relevant global object's associated Document.
-
If document has no browsing context, return
false
. -
Let origin be settings’ origin.
-
Let navigable be document’s node navigable.
-
While navigable has a non-null parent:
-
Set navigable to navigable’s parent.
-
If navigable’s active document's origin is not same origin with origin, return
false
.
-
-
Return
true
.
2.1.2. Credential Type Registry
This registry maps credential types (i.e., [[type]]
values) to various values associated with a given credential type. For example: the Options Member Identifier (formally, a dictionary member identifier) used in CredentialCreationOptions
and CredentialRequestOptions
(i.e., "options dictionaries")
by their specifications.
Note: This registry is used by the relevant credential interface objects algorithm.
Credential Type (in alphabetical order) | Options Member Identifier | Appropriate Interface Object | Get Permissions Policy | Create Permissions Policy | Specification | Requestor Contact |
---|---|---|---|---|---|---|
digital-credential | digital | DigitalCredential
| digital-credentials-get | null | [DIGITAL-CREDENTIALS] | WICG |
federated | federated | FederatedCredential
| null | null | This specification: § 4 Federated Credentials | W3C |
identity | identity | IdentityCredential
| identity-credentials-get | null | [FEDCM] | W3C |
otp | otp | OTPCredential
| otp-credentials | null | [WEB-OTP] | WICG |
password | password | PasswordCredential
| null | null | This specification: § 3 Password Credentials | W3C |
public-key | publicKey | PublicKeyCredential
| publickey-credentials-get | publickey-credentials-create | [WEBAUTHN] | W3C |
2.1.2.1. Registration Entry Requirements and Update Process
-
Each credential type must be unique amongst the set of credential types.
-
Each registry entry must state the dictionary member identifier (known as the Options Member Identifier in the registry) used in the credential specification’s extentions of
CredentialCreationOptions
andCredentialRequestOptions
. -
Each registry entry must state the Appropriate Interface Object identifier for the credential type.
-
Each registry entry must state the Get Permissions Policy permission used when executing Request a
Credential
for a credential type, or null if no permissions policy is specified. -
Each registry entry must state the Create Permissions Policy permission used when executing Create a
Credential
for a credential type, or null if no permissions policy is specified. -
Each registry entry must include a link that references a publicly available specification defining the credential type and the dictionary member identifier.
-
Each registry entry’s specification must include the requestor’s contact information.
An update to this registry is an addition, change or deletion of a credential type's registry entry. Any person can request an update to this registry by pull requests to the webappsec-credential-management repository. The Web Applications Security Working Group will place it on an upcoming meeting agenda and notify the requestor. Consideration and disposition of the request is by consensus of the W3C Web Applications Security Working Group. The Chair will then notify the requestor of the outcome and update the registry accordingly.
2.2. The Credential
Interface
[Exposed =Window ,SecureContext ]interface {
Credential readonly attribute USVString id ;readonly attribute DOMString type ;static Promise <boolean >isConditionalMediationAvailable ();static Promise <undefined >willRequestConditionalCreation (); };
id
, of type USVString, readonly-
The credential’s identifier. The requirements for the identifier are distinct for each type of credential. It might represent a username for username/password tuples, for example.
type
, of type DOMString, readonly-
This attribute’s getter returns the value of the object’s interface object's
[[type]]
slot, which specifies the credential type represented by this object. isConditionalMediationAvailable()
-
Returns a
Promise
that resolves withtrue
if and only if the user agent supports theconditional
approach to mediation of credential requests for the credential type,false
otherwise.Credential
's default implementation ofisConditionalMediationAvailable()
:-
Return a promise resolved with with
false
.
The specification for any credential type supporting
conditional
mediation must explicitly override this function to resolve totrue
.Note: If this function is not present,
conditional
mediation is not supported for the credential type. -
willRequestConditionalCreation()
-
Returns a
Promise
that resolves after the user agent registers the relying party’s intention to create a credential using theconditional
approach to mediation of credential creation for the credential type.Credential
's default implementation ofwillRequestConditionalCreation()
:-
Return a promise resolved with
undefined
.
Note: If this method is not present,
conditional
mediation for credential creation is not supported for the credential type. -
[[type]]
-
The
Credential
interface object has an internal slot named[[type]]
, which unsurprisingly contains a string representing the credential type. The slot’s value is the empty string unless otherwise specified. See § 2.1.2 Credential Type Registry for a list of credential types.Note: The
[[type]]
slot’s value will be the same for all credentials implementing a particular interface, which means that developers can rely onobj.type
returning a string that unambiguously represents the specific kind ofCredential
they’re dealing with. [[discovery]]
-
The
Credential
interface object has an internal slot named[[discovery]]
, representing the mechanism by which the user agent can collect credentials of a given type. Its value is either "credential store
" or "remote
". The former value means that all available credential information is stored in the user agent’s credential store, while the latter means that the user agent can discover credentials outside of those explicitly represented in the credential store via interaction with some external device or service.
Talk to Tobie/Dominic about the interface object bits, here and in § 2.5.1 Request a Credential, etc. I’m not sure I’ve gotten the terminology right. interface prototype object, maybe?
Some Credential
objects are origin bound: these contain an
internal slot named [[origin]]
, which stores the origin for which the Credential
may be effective.
2.2.1. Credential
Internal Methods
The Credential
interface object features several internal methods facilitating
retrieval and storage of Credential
objects, with default "no-op" implementations
as specified in this section, below.
Unless otherwise specified, each interface object created for interfaces which 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., § 3.2 The PasswordCredential Interface, § 4.1 The FederatedCredential Interface, and [WEBAUTHN].
2.2.1.1. [[CollectFromCredentialStore]]
internal method
[[CollectFromCredentialStore]](origin, options, sameOriginWithAncestors)
is called with an origin, a CredentialRequestOptions
, and a boolean which
is true if and only if the caller’s environment settings object is same-origin with its ancestors.
The algorithm returns a set of Credential
objects from the user agent’s credential store that
match the options provided. If no matching Credential
objects are available, the
returned set will be empty.
Credential
's default implementation of [[CollectFromCredentialStore]](origin, options, sameOriginWithAncestors)
:
-
Return an empty set.
2.2.1.2. [[DiscoverFromExternalSource]]
internal method
[[DiscoverFromExternalSource]](origin, options, sameOriginWithAncestors)
is called in parallel with an origin, a CredentialRequestOptions
object,
and a boolean which is true if and only if the caller’s environment settings object is same-origin with its ancestors.
It returns a Credential
if one can be
returned given the options provided, null
if no credential is available, or throws an
error if discovery fails (for example, incorrect options could produce a TypeError
).
If this kind of Credential
is only effective for a single use or a limited time,
this method is responsible for generating new credentials using a credential source.
Credential
's default implementation of [[DiscoverFromExternalSource]](origin, options, sameOriginWithAncestors)
:
-
Return
null
.
2.2.1.3. [[Store]]
internal method
[[Store]](credential, sameOriginWithAncestors)
is called in parallel with a Credential
, and a boolean which is true if and only if the caller’s environment settings object is same-origin with its ancestors.
The algorithm returns once Credential
is persisted to the credential store.
Credential
's default implementation of [[Store]](credential, sameOriginWithAncestors)
:
-
Throw a
NotSupportedError
.
2.2.1.4. [[Create]]
internal method
[[Create]](origin, options, sameOriginWithAncestors)
is called in parallel with an origin, a CredentialCreationOptions
,
and a boolean which is true if and only if the caller’s environment settings object is same-origin with its ancestors.
The algorithm either:
-
creates a
Credential
, or -
does not create a credential and returns
null
, or -
throws an error if creation fails due to exceptional situations (for example, incorrect options could produce a
TypeError
).
When creating a Credential
, it will return an algorithm that takes a global object and returns an interface object inheriting from Credential
. This algorithm MUST be invoked from a task.
Note: This algorithm’s steps are defined on a per-credential type basis.
Credential
's default implementation of [[Create]](origin, options, sameOriginWithAncestors)
:
-
Return
null
.
2.2.2. CredentialUserData
Mixin
Some Credential
objects contain data which aims to give users a human-readable disambiguation
mechanism in the credential chooser by providing a friendly name and icon:
[SecureContext ]interface mixin {
CredentialUserData readonly attribute USVString name ;readonly attribute USVString iconURL ; };
name
, of type USVString, readonly-
A name associated with the credential, intended as a human-understandable public name for display in a credential chooser.
iconURL
, of type USVString, readonly-
A URL pointing to an image for the credential, intended for display in a credential chooser. This URL MUST be an potentially trustworthy URL.
2.3. navigator.credentials
Developers retrieve Credential
s and interact with the user agent’s credential store via
methods exposed on the CredentialsContainer
interface, which hangs off the Navigator
object as navigator.credentials
.
partial interface Navigator { [SecureContext ,SameObject ]readonly attribute CredentialsContainer credentials ; };
The credentials
attribute MUST return the CredentialsContainer
associated with the active document's browsing context.
Note: As discussed in § 6.3 Insecure Sites, the credential management API is exposed only in Secure Contexts.
[Exposed =Window ,SecureContext ]interface {
CredentialsContainer Promise <Credential ?>get (optional CredentialRequestOptions options = {});Promise <undefined >store (Credential credential );Promise <Credential ?>create (optional