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
§ 7
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
XMLHttpRequestor 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
§ 3
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 |
| W3C |
| identity | identity |
IdentityCredential
| identity-credentials-get | null | [FEDCM] | W3C |
| otp | otp |
OTPCredential
| otp-credentials | null | [WEB-OTP] | WICG |
| password | password |
PasswordCredential
| null | null |
| 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
CredentialCreationOptionsandCredentialRequestOptions. -
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
Credentialfor 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
Credentialfor 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
Promisethat resolves withtrueif and only if the user agent supports theconditionalapproach to mediation of credential requests for the credential type ,falseotherwise.Credential’s default implementation ofisConditionalMediationAvailable():-
Return a promise resolved with with
false.
The specification for any credential type supporting
conditionalmediation must explicitly override this function to resolve totrue.Note: If this function is not present,
conditionalmediation is not supported for the credential type . -
-
willRequestConditionalCreation() -
Returns a
Promisethat resolves after the user agent registers the relying party’s intention to create a credential using theconditionalapproach 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,
conditionalmediation for credential creation is not supported for the credential type . -
-
[[type]] -
The
Credentialinterface 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.typereturning a string that unambiguously represents the specific kind ofCredentialthey’re dealing with. -
[[discovery]] -
The
Credentialinterface 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
[PASSWORD-CREDENTIALS]
,
§ 4.1
The
FederatedCredential
Interface
[FEDERATED-CREDENTIALS]
,
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
§ 4.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 CredentialCreationOptions options = {});Promise <undefined >preventSilentAccess (); };dictionary {CredentialData required USVString ; };id
-
get(options) -
When
get()is called, the user agent MUST return the result of executing Request aCredentialonoptions.Arguments for the CredentialsContainer.get(options) method. Parameter Type Nullable Optional Description optionsCredentialRequestOptions✘ ✔ The set of properties governing the scope of the request. -
store(credential) -
When
store()is called, the user agent MUST return the result of executing Store aCredentialoncredential.Arguments for the CredentialsContainer.store(credential) method. Parameter Type Nullable Optional Description credentialCredential✘ ✘ The credential to be stored. -
create(options) -
When
create()is called, the user agent MUST return the result of executing Create aCredentialonoptions.Arguments for the CredentialsContainer.create(options) method. Parameter Type Nullable Optional Description optionsCredentialCreationOptions✘ ✔ The options used to create a Credential. -
preventSilentAccess() -
When
preventSilentAccess()is called, the user agent MUST return the result of executing Prevent Silent Access on the current settings object .Note: The intent here is a signal from the origin that the user has signed out. That is, after a click on a "Sign out" button, the site updates the user’s session info, and calls
navigator.credentials.preventSilentAccess(). This sets the prevent silent access flag , meaning that credentials will not be automagically handed back to the page next time the user visits.Note: This function was previously called
requireUserMediation()which should be considered deprecated.
Navigator
object
(
navigator
)
is
created,
the
user
agent
MUST
create
a
new
CredentialsContainer
object,
using
navigator
’s
relevant
Realm
,
and
associate
it
with
navigator
.
2.3.1.
The
CredentialRequestOptions
Dictionary
In
order
to
retrieve
a
Credential
via
get()
,
the
caller
specifies
a
few
parameters
in
a
CredentialRequestOptions
object.
Note:
The
CredentialRequestOptions
dictionary
is
an
extension
point.
If
and
when
new
types
of
credentials
are
introduced
that
require
options,
their
dictionary
types
will
be
added
to
the
dictionary
so
they
can
be
passed
into
the
request.
See
§ 8.2
§ 6.2
Extension
Points
.
dictionary {CredentialRequestOptions CredentialMediationRequirement mediation = "optional";AbortSignal signal ; };
-
mediation, of type CredentialMediationRequirement , defaulting to"optional" -
This property specifies the mediation requirements for a given credential request. The meaning of each enum value is described below in
CredentialMediationRequirement. Processing details are defined in § 2.5.1 Request a Credential . -
signal, of type AbortSignal -
This property lets the developer abort an ongoing
get()operation. An aborted operation may complete normally (generally if the abort was received after the operation finished) or reject with an abort reason .
unmediated
member.
Setting
that
to
true
had
the
effect
of
setting
mediation
to
"
silent
",
and
setting
it
to
false
had
the
effect
of
setting
mediation
to
"
optional
".
unmediated
should
be
considered
deprecated;
new
code
should
instead
rely
on
mediation
.
CredentialCreationOptions
or
CredentialRequestOptions
(
options
)
is
a
set
of
interface
objects
,
collected
as
follows:
Note: This algorithm uses the Credential Type Registry .
-
Let settings be the current settings object .
-
For each optionKey → optionValue of options :
-
Let credentialInterfaceObject be the Appropriate Interface Object (on settings ’ global object ) whose Options Member Identifier is optionKey .
-
Assert: credentialInterfaceObject ’s
[[type]]slot equals the Credential Type whose Options Member Identifier is optionKey . -
Append credentialInterfaceObject to relevant interface objects .
-
-
Return relevant interface objects .
CredentialRequestOptions
(
options
)
is
matchable
a
priori
if
the
following
steps
return
true
:
-
For each interface in options ’ relevant credential interface objects :
-
If interface ’s
[[discovery]]slot’s value is not "credential store", returnfalse.
-
-
Return
true.
Note:
When
executing
get(options)
,
we
only
return
credentials
without
user
mediation
if
the
provided
CredentialRequestOptions
is
matchable
a
priori
.
If
any
credential
types
are
requested
that
could
require
discovery
from
some
external
service
(OAuth
tokens,
security
key
authenticators,
etc.),
then
user
mediation
will
be
required
in
order
to
guide
the
discovery
process
(by
choosing
a
federated
identity
provider,
BTLE
device,
etc).
2.3.2. Mediation Requirements
When
making
a
request
via
get(options)
or
create(options)
,
developers
can
set
a
case-by-case
requirement
for
user
mediation
by
choosing
the
appropriate
CredentialMediationRequirement
enum
value.
Note:
The
§ 5
§ 3
User
Mediation
section
gives
more
detail
on
the
concept
in
general,
and
its
implications
on
how
the
user
agent
deals
with
individual
requests
for
a
given
origin).
enum {CredentialMediationRequirement "silent" ,"optional" ,"conditional" ,"required" };
-
silent -
User mediation is suppressed for the given operation. If the operation can be performed without user involvement, wonderful. If user involvement is necessary, then the operation will return
nullrather than involving the user.Note: The intended usage is to support "Keep me signed-into this site" scenarios , where a developer may wish to silently obtain credentials if a user should be automatically signed in, but to delay bothering the user with a sign-in prompt until they actively choose to sign-in.
-
optional -
If credentials can be handed over for a given operation without user mediation, they will be. If user mediation is required , then the user agent will involve the user in the decision.
Note: This is the default behavior for
get(), and is intended to serve a case where a developer has reasonable confidence that a user expects to start a sign-in operation. If a user has just clicked "sign-in" for example, then they won’t be surprised or confused to see a credential chooser if necessary. -
conditional -
For
get(), discovered credentials are presented to the user in a non-modal dialog along with an indication of the origin which is requesting credentials. If the user makes a gesture outside of the dialog, the dialog closes without resolving or rejecting thePromisereturned by theget()method and without causing a user-visible error condition. If the user makes a gesture that selects a credential, that credential is returned to the caller. The prevent silent access flag is treated as beingtrueregardless of its actual value: theconditionalbehavior always involves user mediation of some sort if applicable credentials are discovered.If no credentials are discovered, the user agent MAY prompt the user to take action in a way that depends on the type of credential (e.g. to insert a device containing credentials). Either way, the
get()method MUST NOT resolve immediately withnullto avoid revealing the lack of applicable credentials to the website.Websites can only pass
conditionalinto theget()method if all of the credential interfaces it refers to have overriddenisConditionalMediationAvailable()to return aPromisethat resolves withtrue.For
create(), if a user has previously consented to credential creation and the user agent knows it recently mediated an authentication, then thecreate()call may resolve without additional prominent modal interaction. If the user agent did not recently mediate an authentication or does not have consent for credential creation, then the call must throw a "NotAllowedError"DOMException. -
required -
The user agent will not hand over credentials without user mediation , even if the prevent silent access flag is unset for an origin.
Note: This requirement is intended to support reauthentication or user-switching scenarios. Further, the requirement is tied to a specific operation, and does not affect the prevent silent access flag for the origin. To set that flag, developers should call
preventSilentAccess().
2.3.2.1. Examples
get()
for
all
non-signed
in
users
at
some
convinient
point
while
a
landing
page
is
loading,
passing
in
a
mediation
member
set
to
"
silent
".
This
ensures
that
users
who
have
opted-into
dropping
the
requirements
for
user
mediation
(as
described
in
window.addEventListener('load', async () => {
const credentials = await navigator.credentials.get({
...,
mediation: 'silent'
});
if (credentials) {
// Hooray! Let’s sign the user in using these credentials!
}
});
document.querySelector('#sign-in').addEventListener('click', async () => {
const credentials = await navigator.credentials.get({
...,
mediation: 'optional'
});
if (credentials) {
// Hooray! Let’s sign the user in using these credentials!
}
});
Note:
MegaCorp,
Inc.
could
also
have
left
off
the
mediation
member
entirely,
as
"
optional
"
is
its
default.
get()
with
a
mediation
member
set
to
"
required
":
Note: Depending on the security model of the browser or the credential type, this may require the user to authenticate themselves in some way, perhaps by entering a master password, scanning a fingerprint, etc. before a credential is handed to the website.
document.querySelector('#important-form').addEventListener('submit', async () => {
const credentials = await navigator.credentials.get({
...,
mediation: 'required'
});
if (credentials) {
// Verify that |credentials| enables access, and cancel the submission
// if it doesn’t.
} else {
e.preventDefault();
}
});
get()
with
a
mediation
member
set
to
"
required
"
in
order
to
ensure
that
that
credentials
aren’t
returned
automatically
in
response
to
clicking
on
an
"Add
account"
button:
document.querySelector('#switch-button').addEventListener('click', e => {
var c = await navigator.credentials.get({
...,
mediation: 'required'
});
if (c) {
// Sign the user in using |c|.
}
});
2.4.
The
CredentialCreationOptions
Dictionary
In
order
to
create
a
Credential
via
create()
,
the
caller
specifies
a
few
parameters
in
a
CredentialCreationOptions
object.
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
§ 8.2
§ 6.2
Extension
Points
,
and
the
extensions
introduced
in
this
document:
§ 3.2
The
PasswordCredential
Interface
and
§ 4.1
The
FederatedCredential
Interface
.
dictionary {CredentialCreationOptions CredentialMediationRequirement = "optional";mediation AbortSignal signal ; };
-
signal, of type AbortSignal -
This property lets the developer abort an ongoing
create()operation. An aborted operation may complete normally (generally if the abort was received after the operation finished) or reject with an abort reason .
2.5. Algorithms
2.5.1.
Request
a
Credential
The
Request
a
Credential
algorithm
accepts
a
CredentialRequestOptions
(
options
),
and
returns
a
Promise
that
resolves
with
a
Credential
if
one
can
be
unambigiously
obtained,
or
with
null
if
not.
-
Let settings be the current settings object .
-
Assert: settings is a secure context .
-
Let document be settings ’s relevant global object ’s associated Document .
-
If document is not fully active , then return a promise rejected with an "
InvalidStateError"DOMException. -
If
options .is aborted , then return a promise rejected withsignaloptions .’s abort reason .signal -
Let interfaces be options ’s relevant credential interface objects .
-
If interfaces is empty , then return a promise rejected with a "
NotSupportedError"DOMException. -
For each interface of interfaces :
-
If options .
mediationisconditionaland interface does not supportconditionaluser mediation , return a promise rejected with a "TypeError"DOMException. -
If settings ’ active credential types contains interface ’s
[[type]], return a promise rejected with a "NotAllowedError"DOMException. -
Append interface ’s
[[type]]to settings ’ active credential types .
-
-
Let origin be settings ’ origin .
-
Let sameOriginWithAncestors be
trueif settings is same-origin with its ancestors , andfalseotherwise. -
For each interface in options ’ relevant credential interface objects :
-
Let permission be the interface ’s
[[type]]Get Permissions Policy . -
If permission is null, continue.
-
If document is not allowed to use permission , return a promise rejected with a "
NotAllowedError"DOMException.
-
-
Let p be a new promise .
-
Run the following steps in parallel :
-
Let credentials be the result of collecting
Credentials from the credential store , given origin , options , and sameOriginWithAncestors . -
If credentials is an exception , reject p with credentials .
-
If all of the following statements are true, resolve p with credentials [0] and skip the remaining steps:
-
credentials ’ size is 1
-
origin does not require user mediation
-
options is matchable a priori .
-
options .
mediationis not "conditional".
This might be the wrong model. It would be nice to support a site that wished to accept either username/passwords or webauthn-style credentials without forcing a chooser for those users who use the former, and who wish to remain signed in.
-
-
If options ’
mediationis "silent", resolve p withnull, and skip the remaining steps. -
Let result be the result of asking the user to choose a
Credential, given options and credentials . -
If result is an interface object :
-
Set result to the result of executing result ’s
[[DiscoverFromExternalSource]](origin, options, sameOriginWithAncestors), given origin , options , and sameOriginWithAncestors .If that threw an exception :
-
Let e be the thrown exception .
-
Queue a task on global ’s DOM manipulation task source to run the following substeps:
-
Reject p with e .
-
-
Terminate these substeps.
-
-
-
Assert: result is
null, or aCredential. -
If result is a
Credential, resolve p with result . -
If result is
nulland options .mediationis notconditional, resolve p with result .Note: if options .
mediationisconditionaland anullcredential is discovered, promise p is not resolved.
-
-
React to p :
-
For each interface in interfaces :
-
Remove interface ’s
[[type]]from settings ’ active credential types .
-
-
-
Return p .
2.5.2.
Collect
Credential
s
from
the
credential
store
Given
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
user
agent
may
collect
Credential
s
from
the
credential
store
,
returning
a
set
of
Credential
objects
stored
by
the
user
agent
locally
that
match
options
’
filter.
If
no
such
Credential
objects
are
known,
the
returned
set
will
be
empty:
-
Let possible matches be an empty set.
-
For each interface in options ’ relevant credential interface objects :
-
Let r be the result of executing interface ’s
[[CollectFromCredentialStore]](origin, options, sameOriginWithAncestors)internal method on origin , options , and sameOriginWithAncestors . If that threw an exception , rethrow that exception. -
Assert: r is a list of interface objects .
-
For each c in r :
-
Append c to possible matches .
-
-
-
Return possible matches .
2.5.3.
Store
a
Credential
The
Store
a
Credential
algorithm
accepts
a
Credential
(
credential
),
and
returns
a
Promise
which
resolves
once
the
object
is
persisted
to
the
credential
store
.
-
Let settings be the current settings object .
-
Assert: settings is a secure context .
-
If settings ’s relevant global object ’s associated Document is not fully active , then return a promise rejected with an "
InvalidStateError"DOMException. -
Let sameOriginWithAncestors be
trueif the current settings object is same-origin with its ancestors , andfalseotherwise. -
Let p be a new promise .
-
If settings ’ active credential types contains credential ’s
[[type]], return a promise rejected with a "NotAllowedError"DOMException. -
Append credential ’s
[[type]]to settings ’ active credential types . -
Run the following steps in parallel :
-
Execute credential ’s interface object ’s
[[Store]](credential, sameOriginWithAncestors)internal method on credential and sameOriginWithAncestors .If that threw an exception :
-
Let e be the thrown exception .
-
Queue a task on global ’s DOM manipulation task source to run the following substeps:
-
Reject p with e .
-
Otherwise, resolve p with
undefined. -
-
-
React to p :
-
Remove credential ’s
[[type]]from settings ’ active credential types .
-
-
Return p .
2.5.4.
Create
a
Credential
The
Create
a
Credential
algorithm
accepts
a
CredentialCreationOptions
(
options
),
and
returns
a
Promise
which
resolves
with
a
Credential
if
one
can
be
created
using
the
options
provided,
or
null
if
no
Credential
can
be
created.
In
exceptional
circumstances,
the
Promise
may
reject
with
an
appropriate
exception:
-
Let settings be the current settings object .
-
Assert: settings is a secure context .
-
Let global be settings ’ global object .
-
Let document be the relevant global object ’s associated Document .
-
If document is not fully active , then return a promise rejected with an "
InvalidStateError"DOMException. -
Let sameOriginWithAncestors be
trueif the current settings object is same-origin with its ancestors , andfalseotherwise. -
Let interfaces be the set of options ’ relevant credential interface objects .
-
Return a promise rejected with
NotSupportedErrorif any of the following statements are true:-
global does not have an associated Document .
-
interfaces ’ size is greater than 1.
Note: It may be reasonable at some point in the future to loosen this restriction, and allow the user agent to help the user choose among one of many potential credential types in order to support a "sign-up" use case. For the moment, though, we’re punting on that by restricting the dictionary to a single entry.
-
-
For each interface in interfaces :
-
Let permission be the interface ’s
[[type]]Create Permissions Policy . -
If permission is null, continue.
-
If document is not allowed to use permission , return a promise rejected with a "
NotAllowedError"DOMException.
-
-
If
options .is aborted , then return a promise rejected withsignaloptions .’s abort reason .signal -
Let type be interfaces [0]'s
[[type]]. -
If settings ’ active credential types contains type , return a promise rejected with a "
NotAllowedError"DOMException. -
Append type to settings ’ active credential types .
-
Let origin be settings ’s origin .
-
Let p be a new promise .
-
Run the following steps in parallel :
-
Let r be the result of executing interfaces [0]'s
[[Create]](origin, options, sameOriginWithAncestors)internal method on origin , options , and sameOriginWithAncestors .If that threw an exception :
-
Let e be the thrown exception .
-
Queue a task on global ’s DOM manipulation task source to run the following substeps:
-
Reject p with e .
-
-
Terminate these substeps.
-
-
If r is a
Credentialornull, resolve p with r , and terminate these substeps. -
Assert: r is an algorithm (as defined in § 2.2.1.4 [[Create]] internal method ).
-
Queue a task on global ’s DOM manipulation task source to run the following substeps:
-
Resolve p with the result of promise-calling r given global .
-
-
-
React to p :
-
Remove type from settings ’ active credential types .
-
-
Return p .
2.5.5. Prevent Silent Access
The
Prevent
Silent
Access
algorithm
accepts
an
environment
settings
object
(
settings
),
and
returns
a
Promise
which
resolves
once
the
prevent
silent
access
flag
is
persisted
to
the
credential
store
.
-
Let origin be settings ’ origin .
-
If settings ’s relevant global object ’s associated Document is not fully active , then return a promise rejected with an "
InvalidStateError"DOMException. -
Let p be a new promise .
-
Run the following seps in parallel :
-
Set origin ’s prevent silent access flag in the credential store .
-
Resolve p with
undefined.
-
-
Return p .
3.
Password
Credentials
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
.
3.1.
Examples
3.1.1.
Password-based
Sign-in
MegaCorp,
Inc.
supports
passwords,
and
can
use
navigator.credentials.get()
to
obtain
username/password
pairs
from
a
user’s
credential
store
:
.': 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.') {
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.(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
submit()
on
the
form:
.': true })
.then(credential => {
if (!credential) {
return; // as above...
}
if (credential.') {
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
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
§ 6.1
Cross-domain
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
store()
every
time
credentials
are
successfully
used,
even
right
after
credentials
have
been
retrieved
from
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.
3.1.2.
Post-sign-in
Confirmation
To
ensure
that
users
are
offered
to
store
new
credentials
after
a
successful
sign-in,
they
can
to
be
passed
to
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" ">
<label for="password">Password</label>
<input type="password" id="password" name="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 () {
e.preventDefault();
// Construct a new
// that fired the "submit" event: this will suck up the values of the fields
// labeled with "username" and "current-password"
// attributes:
var c = new (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" */)
(c);
});
}
});
3.1.3.
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
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" " value="user">
<label for="password">New Password</label>
<input type="password" id="password" name="password" ">
<input type="submit">
</form>
The
developer
can
handle
the
form
submission
with
something
like
the
following:
document.querySelector('#theForm').addEventListener('submit', e => {
if () {
e.preventDefault();
// Construct a new
// that fired the "submit" event: this will suck up the values of the fields
// labeled with "username" and "new-password"
// attributes:
var c = new (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" */)
(c);
});
}
});
3.2.
The
PasswordCredential
Interface
,
]
{
);
);
;
};
;
{
;
};
password
,
of
type
USVString
,
readonly
This
attribute
represents
the
password
of
the
credential.
[[type]]
The
PasswordCredential
interface
object
has
an
internal
slot
named
[[type]]
whose
value
is
"
password
".
[[discovery]]
The
PasswordCredential
interface
object
has
an
internal
slot
named
[[discovery]]
whose
value
is
"
credential
store
".
PasswordCredential(form)
This
constructor
accepts
an
HTMLFormElement
(
form
),
and
runs
the
following
steps:
Let
origin
be
the
current
settings
object
’s
origin
.
Let
r
be
the
result
of
executing
Create
a
PasswordCredential
from
an
HTMLFormElement
given
form
and
origin
.
If
r
is
an
exception
,
throw
r
.
Otherwise,
return
r
.
PasswordCredential(data)
This
constructor
accepts
a
PasswordCredentialData
(
data
),
and
runs
the
following
steps:
Let
r
be
the
result
of
executing
Create
a
PasswordCredential
from
PasswordCredentialData
on
data
.
If
r
is
an
exception
,
throw
r
.
Otherwise,
return
r
.
PasswordCredential
objects
can
be
created
via
navigator.credentials.create()
either
explicitly
by
passing
in
a
PasswordCredentialData
dictionary,
or
based
on
the
contents
of
an
HTMLFormElement
’s
submittable
elements
.
{
;
;
;
;
};
;
{
;
};
PasswordCredential
objects
are
origin
bound
.
PasswordCredential
’s
interface
object
inherits
Credential
’s
implementation
of
[[DiscoverFromExternalSource]](origin,
options,
sameOriginWithAncestors)
,
and
defines
its
own
implementation
of
[[CollectFromCredentialStore]](origin,
options,
sameOriginWithAncestors)
,
[[Create]](origin,
options,
sameOriginWithAncestors)
,
and
[[Store]](credential,
sameOriginWithAncestors)
.
3.3.
Algorithms
3.3.1.
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
.
Assert:
options
["
password
"]
exists
.
If
sameOriginWithAncestors
is
false
,
throw
a
"
NotAllowedError
"
DOMException
.
Note:
This
restriction
aims
to
address
the
concern
raised
in
§ 6.4
Origin
Confusion
.
Return
the
empty
set
if
options
["
password
"]
is
not
true
.
Return
the
result
of
retrieving
credentials
from
the
credential
store
that
match
the
following
filter:
The
credential
is
a
PasswordCredential
The
credential’s
[[origin]]
is
the
same
origin
as
origin
.
3.3.2.
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
.
Assert:
options
["
password
"]
exists
,
and
sameOriginWithAncestors
is
unused.
If
options
["
password
"]
is
an
HTMLFormElement
,
return
the
result
of
executing
Create
a
PasswordCredential
from
an
HTMLFormElement
given
options
["
password
"]
and
origin
.
Rethrow
any
exceptions.
If
options
["
password
"]
is
a
PasswordCredentialData
,
return
the
result
of
executing
Create
a
PasswordCredential
from
PasswordCredentialData
given
options
["
password
"].
Rethrow
any
exceptions.
Throw
a
TypeError
exception
.
3.3.3.
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
.
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
§ 6.4
Origin
Confusion
.
If
the
user
agent’s
credential
store
contains
a
PasswordCredential
(
stored
)
whose
id
attribute
is
credential
’s
id
and
whose
[[origin]]
slot
is
the
same
origin
as
credential
’s
[[origin]]
,
then:
If
the
user
grants
permission
to
update
credentials
(as
discussed
when
defining
user
mediation
),
then:
Set
stored
’s
password
to
credential
’s
password
.
Set
stored
’s
name
to
credential
’s
name
.
Set
stored
’s
iconURL
to
credential
’s
iconURL
.
Otherwise,
if
the
user
grants
permission
to
store
credentials
(as
discussed
when
defining
user
mediation
,
then:
Store
a
PasswordCredential
in
the
credential
store
with
the
following
properties:
id
credential
’s
id
name
,
credential
’s
name
iconURL
credential
’s
iconURL
[[origin]]
credential
’s
[[origin]]
password
credential
’s
password
3.3.4.
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:
§ 3.1.2
Post-sign-in
Confirmation
and
§ 3.1.3
Change
Password
provide
examples
of
the
intended
usage.
Let
data
be
a
new
PasswordCredentialData
dictionary.
Set
data
’s
origin
member’s
value
to
origin
’s
value.
Let
formData
be
the
result
of
executing
the
FormData
constructor
on
form
.
Let
elements
be
a
list
of
all
the
submittable
elements
whose
form
owner
is
form
,
in
tree
order
.
Let
newPasswordObserved
be
false
.
For
each
field
in
elements
,
run
the
following
steps:
If
field
does
not
have
an
autocomplete
attribute,
then
skip
to
the
next
field
.
Let
name
be
the
value
of
field
’s
name
attribute.
If
formData
’s
has()
method
returns
false
when
executed
on
name
,
then
skip
to
the
next
field
.
If
field
’s
autocomplete
attribute’s
value
contains
one
or
more
autofill
detail
tokens
(
tokens
),
then:
For
each
token
in
tokens
:
If
token
is
an
ASCII
case-insensitive
match
for
one
of
the
following
strings,
run
the
associated
steps:
"
new-password
"
Set
data
’s
password
member’s
value
to
the
result
of
executing
formData
’s
get()
method
on
name
,
and
newPasswordObserved
to
true
.
"
current-password
"
If
newPasswordObserved
is
false
,
set
data
’s
password
member’s
value
to
the
result
of
executing
formData
’s
get()
method
on
name
.
Note:
By
checking
that
newPasswordObserved
is
false
,
new-password
fields
take
precedence
over
current-password
fields.
"
photo
"
Set
data
’s
iconURL
member’s
value
to
the
result
of
executing
formData
’s
get()
method
on
name
.
"
name
"
"
nickname
"
Set
data
’s
name
member’s
value
to
the
result
of
executing
formData
’s
get()
method
on
name
.
"
username
"
Set
data
’s
id
member’s
value
to
the
result
of
executing
formData
’s
get()
method
on
name
.
Let
c
be
the
result
of
executing
Create
a
PasswordCredential
from
PasswordCredentialData
on
data
.
If
that
threw
an
exception
,
rethrow
that
exception.
Assert:
c
is
a
PasswordCredential
.
Return
c
.
3.3.5.
Create
a
PasswordCredential
from
PasswordCredentialData
To
Create
a
PasswordCredential
from
PasswordCredentialData
,
given
an
PasswordCredentialData
(
data
),
run
these
steps.
Let
c
be
a
new
PasswordCredential
object.
If
any
of
the
following
are
the
empty
string,
throw
a
TypeError
exception
:
data
’s
id
member’s
value
data
’s
origin
member’s
value
data
’s
password
member’s
value
Set
c
’s
properties
as
follows:
password
data
’s
password
member’s
value
id
data
’s
id
member’s
value
iconURL
data
’s
iconURL
member’s
value
name
data
’s
name
member’s
value
[[origin]]
data
’s
origin
member’s
value.
Return
c
.
3.3.6.
CredentialRequestOptions
Matching
for
PasswordCredential
Given
a
CredentialRequestOptions
(
options
),
the
following
algorithm
returns
"
Matches
"
if
the
PasswordCredential
should
be
available
as
a
response
to
a
get()
request,
and
"
Does
Not
Match
"
otherwise.
If
options
has
a
password
member
whose
value
is
true
,
then
return
"
Matches
".
Return
"
Does
Not
Match
".
4.
Federated
Credentials
4.1.
The
FederatedCredential
Interface
,
]
{
);
;
;
};
;
{
;
;
};
{
;
};
provider
,
of
type
USVString
,
readonly
The
credential’s
federated
identity
provider.
See
§ 4.1.1
Identifying
Providers
for
details
regarding
valid
formats.
protocol
,
of
type
DOMString
,
readonly,
nullable
The
credential’s
federated
identity
provider’s
protocol
(e.g.
"
openidconnect
").
If
the
value
is
null
,
then
the
protocol
can
be
inferred
from
the
provider
.
[[type]]
The
FederatedCredential
interface
object
has
an
internal
slot
named
[[type]]
whose
value
is
"
federated
".
[[discovery]]
The
FederatedCredential
interface
object
has
an
internal
slot
named
[[discovery]]
whose
value
is
"
credential
store
".
FederatedCredential(data)
This
constructor
accepts
a
FederatedCredentialInit
(
data
),
and
runs
the
following
steps:
Let
r
be
the
result
of
executing
Create
a
FederatedCredential
from
FederatedCredentialInit
on
data
.
If
that
threw
an
exception
,
rethrow
that
exception.
Return
r
.
FederatedCredential
objects
can
be
created
by
passing
a
FederatedCredentialInit
dictionary
into
navigator.credentials.create()
.
{
;
;
;
;
;
};
{
;
};
FederatedCredential
objects
are
origin
bound
.
FederatedCredential
’s
interface
object
inherits
Credential
’s
implementation
of
[[DiscoverFromExternalSource]](origin,
options,
sameOriginWithAncestors)
,
and
defines
its
own
implementation
of
[[CollectFromCredentialStore]](origin,
options,
sameOriginWithAncestors)
,
[[Create]](origin,
options,
sameOriginWithAncestors)
,
and
[[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)
.
4.1.1.
Identifying
Providers
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
providers
array,
or
FederatedCredential
’s
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
.
4.2.
Algorithms
4.2.1.
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.
Assert:
options
["
federated
"]
exists
.
If
sameOriginWithAncestors
is
false
,
throw
a
"
NotAllowedError
"
DOMException
.
Note:
This
restriction
aims
to
address
the
concern
raised
in
§ 6.4
Origin
Confusion
.
Return
the
empty
set
if
options
["
federated
"]
is
not
true
.
Return
the
result
of
retrieving
credentials
from
the
credential
store
that
match
the
following
filter:
The
credential
is
a
FederatedCredential
The
credential’s
[[origin]]
is
the
same
origin
as
origin
.
If
options
["
federated
"]["
providers
"]
exists
,
its
value
contains
the
credentials’s
provider
.
If
options
["
federated
"]["
protocols
"]
exists
,
its
value
contains
the
credentials’s
protocol
.
4.2.2.
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:
Assert:
options
["
federated
"]
exists
,
and
sameOriginWithAncestors
is
unused.
Set
options
["
federated
"]'s
origin
member’s
value
to
origin
’s
value.
Return
the
result
of
executing
Create
a
FederatedCredential
from
FederatedCredentialInit
given
options
["
federated
"].
If
that
threw
an
exception
,
then
rethrow
that
exception.
4.2.3.
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
.
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
§ 6.4
Origin
Confusion
.
If
the
user
agent’s
credential
store
contains
a
FederatedCredential
whose
id
attribute
is
credential
’s
id
and
whose
[[origin]]
slot
is
the
same
origin
as
credential
’s
[[origin]]
,
and
whose
provider
is
credential
’s
provider
,
then
return.
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:
id
credential
’s
id
name
,
credential
’s
name
iconURL
credential
’s
iconURL
[[origin]]
credential
’s
[[origin]]
provider
credential
’s
provider
protocol
credential
’s
protocol
4.2.4.
Create
a
FederatedCredential
from
FederatedCredentialInit
To
Create
a
FederatedCredential
from
FederatedCredentialInit
,
given
a
FederatedCredentialInit
(
init
),
run
these
steps.
Let
c
be
a
new
FederatedCredential
object.
If
any
of
the
following
are
the
empty
string,
throw
a
TypeError
exception
:
init
.
id
’s
value
init
.
provider
’s
value
Set
c
’s
properties
as
follows:
id
init
.
id
’s
value
provider
init
.
provider
’s
value
iconURL
init
.
iconURL
’s
value
name
init
.
name
’s
value
[[origin]]
init
.
origin
’s
value.
Return
c
.
5.
User
Mediation
Exposing credential information to the web via an API has a number of potential impacts on user privacy. The user agent, therefore, MUST involve the user in a number of cases in order to ensure that they clearly understands what’s going on, and with whom their credentials are being shared.
We call a particular action user mediated if it takes place after gaining a user’s explicit consent. Consent might be expressed through a user’s direct interaction with a credential chooser interface, for example. In general, user mediated actions will involve presenting the user some sort of UI, and asking them to make a decision.
An action is unmediated if it takes place silently, without explicit user consent. For example, if a user configures their browser to grant persistent credential access to a particular origin, credentials may be provided without presenting the user with a UI requesting a decision.
Here we’ll spell out a few requirements that hold for all credential types , but note that there’s a good deal of latitude left up to the user agent (which is in a priviliged position to assist the user). Moreover, specific credential types may have distinct requirements that exceed the requirements laid out more generally here.
5.1.
3.1.
Storing
and
Updating
Credentials
Credential information is sensitive data, and users MUST remain in control of that information’s storage. Inadvertent credential storage could, for instance, unexpectedly link a user’s local profile on a particular device to a specific online persona. To mitigate the risk of surprise:
-
Credential information SHOULD NOT be stored or updated without user mediation . For example, the user agent could display a "Save this credential?" dialog box to the user in response to each call to
store().User consent MAY be inferred if a user agent chooses to offer a persistant grant of consent in the form of an "Always save passwords" option (though we’d suggest that user agents should err on the side of something more narrowly scoped: perhaps "Always save _generated_ passwords.", or "Always save passwords for this site.").
-
User agents SHOULD notify users when credentials are stored. This might take the form of an icon in the address bar, or some similar location.
-
User agents MUST allow users to manually remove stored credentials. This functionality might be implemented as a settings page, or via interaction with a notification as described above.
5.2.
3.2.
Requiring
User
Mediation
By
default,
user
mediation
is
required
for
all
origins
,
as
the
relevant
prevent
silent
access
flag
in
the
credential
store
is
set
to
true
.
Users
MAY
choose
to
grant
an
origin
persistent
access
to
credentials
(perhaps
in
the
form
of
a
"Stay
signed
into
this
site."
option),
which
would
set
this
flag
to
false
.
In
this
case,
the
user
would
always
be
signed
into
that
site,
which
is
desirable
from
the
perspective
of
usability
and
convinience,
but
which
might
nevertheless
have
surprising
implications
(consider
a
user
agent
which
syncs
this
flag’s
state
across
devices,
for
instance).
To mitigate the risk of surprise:
-
User agents MUST allow users to require user mediation for a given origin or for all origins. This functionality might be implemented as a global toggle that overrides each origin’s prevent silent access flag to return
false, or via more granular settings for specific origins (or specific credentials on specific origins). -
User agents MUST NOT set an origin ’s prevent silent access flag to
falsewithout user mediation . For example, the credential chooser described in§ 5.3§ 3.3 Credential Selection could have a checkbox which the user could toggle to mark a credential as available without mediation for the origin, or the user agent could have an onboarding process for its credential manager which asked a user for a default setting. -
User agents MUST notify users when credentials are provided to an origin. This could take the form of an icon in the address bar, or some similar location.
-
If a user clears her browsing data for an origin (cookies, localStorage, and so on), the user agent MUST set the prevent silent access flag to
truefor that origin.
5.3.
3.3.
Credential
Selection
When
responding
to
a
call
to
get()
on
an
origin
which
requires
user
mediation
,
user
agents
MUST
ask
the
user
for
permission
to
share
credential
information.
This
SHOULD
take
the
form
of
a
credential
chooser
which
presents
the
user
with
a
list
of
credentials
that
are
available
for
use
on
a
site,
allowing
them
to
select
one
which
should
be
provided
to
the
website,
or
to
abort
the
request
entirely.
The chooser’s user interface SHOULD be implemented in such a way as to be distinguishable from UI which a website could produce. For example, the chooser might overlap the user agent’s UI in some unspoofable way.
The chooser’s user interface MUST include an indication of the origin which is requesting credentials.
The
chooser’s
user
interface
SHOULD
include
all
Credential
objects
associated
with
the
origin
that
requested
credentials.
User
agents
MAY
internally
associate
information
with
each
Credential
object
beyond
the
attributes
specified
in
this
document
in
order
to
enhance
the
utility
of
such
a
chooser.
For
example,
favicons
could
help
disambiguate
identity
providers,
etc.
Any
additional
information
stored
MUST
not
be
exposed
directly
to
the
web.
The chooser’s behavior is not defined here: user agents are encouraged to experiment with UI treatments that educate users about their authentication options, and guide them through the process of choosing a credential to present. That said, the interface to the chooser is as follows:
Credential
,
given
a
CredentialRequestOptions
(
options
),
and
a
set
of
Credential
objects
from
the
credential
store
(
locally
discovered
credentials
).
This
algorithm
returns
either
null
if
the
user
chose
not
to
share
a
credential
with
the
site,
a
Credential
object
if
the
user
chose
a
specific
credential,
or
a
Credential
interface
object
if
the
user
chose
a
type
of
credential.
If the options provided is not matchable a priori , then it might also make sense for the chooser interface to list the relevant credential interface objects for options that aren’t covered by the list of explicit credentials. If, for instance, a site accepts webauthn-style authenticators, then "Security Key" might show up in the chooser list with an appropriate icon.
Also, note that in some cases the user agent may skip the chooser entirely. For example, if the only relevant credential interface objects is one that itself requires user interaction, the user agent may return that interface directly, and rely on its internal mediation flow for user consent.
6.
4.
Security
Considerations
The following sections represent guidelines for various security and privacy considerations. Individual credential types may enforce stricter or more relaxed versions of these guidelines.
6.1.
4.1.
Cross-domain
credential
access
Credentials
are
sensitive
information,
and
user
agents
need
to
exercise
caution
in
determining
when
they
can
be
safely
shared
with
a
website.
The
safest
option
is
to
restrict
credential
sharing
to
the
exact
origin
on
which
they
were
saved.
That
is
likely
too
restrictive
for
the
web,
however:
consider
sites
which
divide
functionality
into
subdomains
like
example.com
vs
admin.example.com
.
As a compromise between annoying users, and securing their credentials, user agents:
-
MUST NOT share credentials between origins whose scheme components represent a downgrade in security. That is, it may make sense to allow credentials saved on
http://example.com/to be made available tohttps://example.com/(in order to encourage developers to migrate to secure transport), but the inverse would be dangerous. -
MAY use the Public Suffix List [PSL] to determine the effective scope of a credential by comparing the registerable domain of the credential’s
[[origin]]with the origin in whichget()is called. That is: credentials saved onhttps://admin.example.com/andhttps://example.com/MAY be offered to users whenget()is called fromhttps://www.example.com/, and vice versa. -
MUST NOT offer credentials to an origin in response to
get()without user mediation if the credential’s origin is not an exact match for the calling origin. That is,Credentialobjects forhttps://example.comwould not be returned directly tohttps://www.example.com, but could be offered to the user via the chooser.
6.2.
4.2.
Credential
Leakage
Developers are well-advised to take some precautions to mitigate the risk that a cross-site scripting attack could turn into persistent access to a user’s account by setting a reasonable Content Security Policy [CSP] which restricts the endpoints to which data can be sent. In particular, developers should ensure that the following directives are set, explicitly or implicitly, in their pages' policies:
-
`script-src` and `object-src` both restrict script execution on a page, making it less likely that a cross-site scripting attack will succeed in the first place. If sites are populating
formelements, also `form-action` directives should be set. -
`connect-src` restricts the origins to which
fetch()may submit data (which mitigates the risk that credentials could be exfiltrated toevil.com. -
`child-src` restricts the nested browsing contexts which may be embedded in a page, making it more difficult to inject a malicious
postMessage()target. [HTML]
Developers should, of course, also properly escape input and output, and consider using other layers of defense, such as Subresource Integrity [SRI] to further reduce risk.
When defining specific credential types, specific credential types SHOULD give due consideration to the ways in which credential data can be transmitted over the wire. It might be reasonable, for example, to define transmission mechanisms which are restricted to same-origin endpoints.
6.3.
4.3.
Insecure
Sites
User agents MUST NOT expose the APIs defined here to environments which are not secure contexts . User agents might implement autofill mechanisms which store user credentials and fill sign-in forms on non-potentially trustworthy URLs , but those sites cannot be trusted to interact directly with the credential manager in any meaningful way, and those sites MUST NOT have access to credentials saved in secure contexts .
6.4.
4.4.
Origin
Confusion
If framed pages have access to the APIs defined here, it might be possible to confuse a user into granting access to credentials for an origin other than the top-level browsing context , which is the only security origin which users can reasonably be expected to understand.
This document exposes the Credential Management APIs to those contexts, as it’s likely that some credential types will be straightforward to make available if user agents put enough thought and context into their UI.
Specific
credential
types,
however,
will
be
difficult
to
expose
in
those
contexts
without
risk.
Those
credential
types
are
restricted
via
checks
in
their
[[Create]](origin,
options,
sameOriginWithAncestors)
,
[[CollectFromCredentialStore]](origin,
options,
sameOriginWithAncestors)
,
[[DiscoverFromExternalSource]](origin,
options,
sameOriginWithAncestors)
,
and
[[Store]](credential,
sameOriginWithAncestors)
methods,
as
appropriate.
For
example
PasswordCredential
’s
[[CollectFromCredentialStore]](origin,
options,
sameOriginWithAncestors)
method
will
immedietely
return
an
empty
set
if
called
from
inside
a
Worker
,
or
a
non-
top-level
browsing
context
.
6.5.
4.5.
Signing-Out
If
a
user
has
chosen
to
automatically
sign-in
to
websites,
as
discussed
in
§ 5.2
§ 3.2
Requiring
User
Mediation
,
then
the
user
agent
will
provide
credentials
to
an
origin
whenever
it
asks
for
them.
The
website
can
instruct
the
user
agent
to
suppress
this
behavior
by
calling
CredentialsContainer
’s
preventSilentAccess()
method,
which
will
turn
off
automatic
sign-in
for
a
given
origin.
The user agent relies on the website to do the right thing; an inattentive (or malicious) website could simply neglect to call this method, causing the user agent to continue providing credentials against the user’s apparent intention. This is marginally worse than the status-quo of a site that doesn’t clear user credentials when they click "Sign-out", as the user agent becomes complicit in the authentication.
The
user
MUST
have
some
control
over
this
behavior.
As
noted
in
§ 5.2
§ 3.2
Requiring
User
Mediation
,
clearing
cookies
for
an
origin
will
also
reset
that
origin’s
prevent
silent
access
flag
the
credential
store
to
true
.
Additionally,
the
user
agent
SHOULD
provide
some
UI
affordance
for
disabling
automatic
sign-in
for
a
particular
origin.
This
could
be
tied
to
the
notification
that
credentials
have
been
provided
to
an
origin,
for
example.
7.
5.
Privacy
Considerations
7.1.
5.1.
Timing
Attacks
If
the
user
has
no
credentials
for
an
origin,
a
call
to
get()
will
resolve
very
quickly
indeed.
A
malicious
website
could
distinguish
between
a
user
with
no
credentials
and
a
user
with
credentials
who
chooses
not
to
share
them.
User agents SHOULD also rate-limit credential requests. It’s almost certainly abusive for a page to request credentials more than a few times in a short period.
7.2.
5.2.
Chooser
Leakage
If
a
user
agent’s
credential
chooser
displays
images
supplied
by
an
origin
(for
example,
if
a
Credential
displays
a
site’s
favicon),
then,
requests
for
these
images
MUST
NOT
be
directly
tied
to
instantiating
the
chooser
in
order
to
avoid
leaking
chooser
usage.
One
option
would
be
to
fetch
the
images
in
the
background
when
saving
or
updating
a
Credential
,
and
to
cache
them
for
the
lifetime
of
the
Credential
.
These
images
MUST
be
fetched
with
the
credentials
mode
set
to
"
omit
",
the
service-workers
mode
set
to
"
none
",
the
client
set
to
null
,
the
initiator
set
to
the
empty
string,
and
the
destination
"
subresource
".
Moreover, if the user agent allows the user to change either the name or icon associated with the credential, the alterations to the data SHOULD NOT be exposed to the website (consider a user who names two credentials for an origin "My fake account" and "My real account", for instance).
7.3.
5.3.
Locally
Stored
Data
This API offers an origin the ability to store data persistently along with a user’s profile. Since most user agents treat credential data differently than "browsing data" (cookies, etc.) this might have the side effect of surprising a user who might believe that all traces of an origin have been wiped out when they clear their cookies.
User agents SHOULD provide UI that makes it clear to a user that credential data is stored for an origin, and SHOULD make it easy for users to remove such data when they’re no longer interested in keeping it around.
8.
6.
Implementation
Considerations
This section is non-normative.
8.1.
6.1.
Website
Authors
Add
some
thoughts
here
about
when
and
how
the
API
should
be
used,
especially
with
regard
to
mediation
.
[w3c/webappsec
Issue
#290]
Describe
encoding
restrictions
of
submitting
credentials
by
fetch()
with
a
FormData
body.
When
performing
feature
detection
for
a
given
credential
type,
developers
are
encouraged
to
verify
that
the
relevant
Credential
specialization
is
present,
rather
than
relying
on
the
presence
of
navigator.credentals
.
The
latter
verifies
the
existence
of
the
API
itself,
but
does
not
ensure
that
the
specific
kind
of
credential
necessary
for
a
given
site
is
supported.
For
example,
if
a
given
site
requires
passwords,
checking
if
(window.PasswordCredential)
is
the
most
effective
verification
of
support.
8.2.
6.2.
Extension
Points
This document provides a generic, high-level API that’s meant to be extended with specific types of credentials that serve specific authentication needs. Doing so is, hopefully, straightforward:
-
Define a new interface that inherits from
Credential: -
Define appropriate
[[Create]](origin, options, sameOriginWithAncestors),[[CollectFromCredentialStore]](origin, options, sameOriginWithAncestors),[[DiscoverFromExternalSource]](origin, options, sameOriginWithAncestors), and[[Store]](credential, sameOriginWithAncestors)methods onExampleCredential’s interface object .[[CollectFromCredentialStore]](origin, options, sameOriginWithAncestors)is appropriate for credentials that remain effective forever and can therefore simply be copied out of the credential store , while[[DiscoverFromExternalSource]](origin, options, sameOriginWithAncestors)is appropriate for credentials that need to be re-generated from a credential source .Long-running operations, like those in
PublicKeyCredential’s[[Create]](origin, options, sameOriginWithAncestors)and[[DiscoverFromExternalSource]](origin, options, sameOriginWithAncestors)operations are encouraged to useoptions.signalto allow developers to abort the operation. See DOM § 3.3 Using AbortController and AbortSignal objects in APIs for detailed instructions.ExampleCredential’s[[CollectFromCredentialStore]](origin, options, sameOriginWithAncestors)internal method is called with an origin (origin), a CredentialRequestOptions object (options), and a boolean which istrueif and only if the calling context is same-origin with its ancestors . The algorithm returns a set ofCredentialobjects that match the options provided. If no matchingCredentialobjects are available, the returned set will be empty.-
Assert:
options[example] exists. -
If
options[example] is not truthy, return the empty set. -
For each credential in the credential store :
-
...
-
-
-
Define the value of the
ExampleCredentialinterface object ’s[[type]]slot:TheExampleCredentialinterface object has an internal slot named[[type]]whose value is the string "example". -
Define the value of the
ExampleCredentialinterface object ’s[[discovery]]slot:TheExampleCredentialinterface object has an internal slot named[[discovery]]whose value is "credential store". -
Extend
CredentialRequestOptionswith the options the new credential type needs to respond reasonably toget(): -
Extend
CredentialCreationOptionswith the data the new credential type needs to createCredentialobjects in response tocreate(): -
If the new credential type supports
conditionaluser mediation , defineExampleCredential/isConditionalMediationAvailable()to return a promise resolved withtrue. -
Following the procedure in § 2.1.2.1 Registration Entry Requirements and Update Process , add an entry to the Credential Type Registry for the new "example" credential type and its corresponding:
-
CredentialCreationOptions' andCredentialRequestOptions' Options Member Identifier (in this case it is "example"), and -
Appropriate Interface Object identifier (in this case it is
ExampleCredential).
Note: The credential type ’s options dictionaries' Options Member Identifier must be the same in both
CredentialCreationOptionsandCredentialRequestOptions, and should be the same as the credential type value in theCredentialinterface object ’s[[type]]slot. -
You
might
also
find
that
new
primitives
are
necessary.
For
instance,
you
might
want
to
return
many
Credential
objects
rather
than
just
one
in
some
sort
of
complicated,
multi-factor
sign-in
process.
That
might
be
accomplished
in
a
generic
fashion
by
adding
a
getAll()
method
to
CredentialsContainer
which
returned
a
sequence<Credential>
,
and
defining
a
reasonable
mechanism
for
dealing
with
requesting
credentials
of
distinct
types.
For any such extension, we recommend getting in touch with public-webappsec@ for consultation and review.
8.3.
6.3.
Browser
Extensions
Ideally, user agents that implement an extension system of some sort will allow third-parties to hook into these API endpoints in order to improve the behavior of third party credential management software in the same way that user agents can improve their own via this imperative approach.
This
could
range
from
a
complex
new
API
that
the
user
agent
mediates,
or
simply
by
allowing
extensions
to
overwrite
the
get()
and
store()
endpoints
for
their
own
purposes.
9.
7.
Future
Work
This section is non-normative.
The API defined here does the bare minimum to expose user agent’s credential managers to the web, and allows the web to help those credential managers understand when federated identity providers are in use. The next logical step will be along the lines sketched in documents like [WEB-LOGIN] (and, to some extent, Mozilla’s BrowserID [BROWSERID] ).
The user agent is in the unique position of being able to effectively mediate the relationship between users, identity providers, and websites. If the user agent can remove some of the risk and confusion associated with the typical authentication flows, users will be in a significantly better position than today.
A
natural
way
to
expose
this
information
might
be
to
extend
the
FederatedCredential
interface
with
properties
like
authentication
tokens,
and
possibly
to
add
some
form
of
manifest
format
with
properties
that
declare
the
authentication
type
which
the
provider
supports.
The
API
described
here
is
designed
to
be
extensible
enough
to
support
use
cases
that
require
user
interaction,
perhaps
with
websites
other
than
the
one
which
requested
credentials.
We
hope
that
the
Promise-based
system
we’ve
settled
on
is
extensible
enough
to
support
these
kinds
of
asynchronous
flows
which
could
require
some
level
of
interaction
between
multiple
browsing
contexts
(e.g.
mediated
activity
on
idp.com
might
resolve
a
Promise
handed
back
to
rp.com
)
or
between
devices
and
user
agents
(e.g.
[WEBAUTHN]
)
in
the
future
without
redesigning
the
API
from
the
ground
up.
Baby steps.