Copyright © 2023 World Wide Web Consortium . W3C ® liability , trademark and permissive document license rules apply.
This specification defines common infrastructure that other specifications can use to interact with browser permissions. These permissions represent a user's choice to allow or deny access to "powerful features" of the platform. For developers, the specification standardizes an API to query the permission state of a powerful feature, and be notified if a permission to use a powerful feature changes state.
This section describes the status of this document at the time of its publication. A list of current W3C publications and the latest revision of this technical report can be found in the W3C technical reports index at https://www.w3.org/TR/.
This is a work in progress.
This document was published by the Web Application Security Working Group as an Editor's Draft.
Publication as an Editor's Draft does not imply endorsement by W3C and its Members.
This is a draft document and may be updated, replaced or obsoleted by other documents at any time. It is inappropriate to cite this document as other than work in progress.
This document was produced by a group operating under the W3C Patent Policy . W3C maintains a public list of any patent disclosures made in connection with the deliverables of the group; that page also includes instructions for disclosing a patent. An individual who has actual knowledge of a patent which the individual believes contains Essential Claim(s) must disclose the information in accordance with section 6 of the W3C Patent Policy .
This document is governed by the 12 June 2023 W3C Process Document .
This section is non-normative.
Specifications can define features that are explicitly identified as a powerful feature . These features are said to be "powerful" in that they can have significant privacy, security, and performance implications. As such, users rely on user agents to deny sites the ability to use these features until they have given express permission, and usually only granting this ability for a limited amount of time. Express permission to allow a site to use a powerful feature is generally given and controlled through browser UI, as illustrated below.
In this sense, a permission represents the current state of user consent for certain types of features, and particularly "powerful features". Ultimately the user retains control of these permissions and have the ability to manually grant or deny permissions through user preferences. Further, user agents assist users in managing permissions by, for example, hiding and automatically denying certain permission prompts that would otherwise be a nuisance, and automatically expiring granted permissions if a user doesn't visit a website for some time.
This section is non-normative.
This example uses the Permissions API to decide whether local news should be shown using the Geolocation API or with a button offering to add the feature.
const { state } = await navigator.permissions.query({
name: "geolocation"
});
switch (state) {
case "granted":
showLocalNewsWithGeolocation();
break;
case "prompt":
showButtonToEnableLocalNews();
break;
case "denied":
showNationalNews();
break;
}
This
example
simultaneously
checks
the
state
of
the
"geolocation"
and
"notifications"
powerful
features
:
const queryPromises = ["geolocation", "notifications"].map(
name => navigator.permissions.query({ name })
);
for await (const status of queryPromises) {
console.log(`${status.name}: ${status.state}`);
}
This example is checking the permission state of the available cameras.
const devices = await navigator.mediaDevices.enumerateDevices();
// filter on video inputs, and map to query object
const queries = devices
.filter(({ kind }) => kind === "videoinput")
.map(({ deviceId }) => ({ name: "camera", deviceId }));
const promises = queries.map((queryObj) =>
navigator.permissions.query(queryObj)
);
try {
const results = await Promise.all(promises);
// log the state of each camera
results.forEach(({ state }, i) => console.log("Camera", i, state));
} catch (error) {
console.error(error);
}
This section specifies a model for permissions to use powerful features on the Web platform.
A permission represents a user's decision to allow a web application to use a powerful feature . This decision is represented as a permission state .
Express permission refers to the user granting the web application the ability to use a powerful feature .
Conceptually, a permission for a powerful feature can be in one of the following states :
To ascertain new information about the user's intent , a user agent MAY collect and interpret information about a user's intentions. This information can come from explicit user action, aggregate behavior of both the relevant user and other users, or implicit signals this specification hasn't anticipated.
Every permission has a lifetime , which is the duration for which a particular permission remains granted before it reverts back to its default state . A lifetime could be until a particular Realm is destroyed, until a particular top-level browsing context is destroyed, a particular amount of time, or be infinite. The lifetime is negotiated between the end-user and the user agent when the user gives express permission to use a feature —usually via some permission UI or user-agent defined policy.
Every permission has a default state (usually prompt ), which is the state that the permission is in when the user has not yet given express permission to use the feature or it has been reset because its lifetime has expired.
The user agent maintains a single permission store which is a list of permission store entries . Each particular entry denoted by its descriptor and key can only appear at most once in this list.
The user agent MAY remove entries from the permission store when their respective permission 's lifetime has expired.
A
permission
store
entry
is
a
tuple
of
PermissionDescriptor
descriptor
,
permission
key
key
,
and
state
state
.
To
get
a
permission
store
entry
given
a
PermissionDescriptor
descriptor
and
permission
key
key
:
To
set
a
permission
store
entry
given
a
PermissionDescriptor
descriptor
,
a
permission
key
key
,
and
a
state
state
,
run
these
steps:
To
remove
a
permission
store
entry
given
a
PermissionDescriptor
descriptor
and
permission
key
key
,
run
these
steps:
A permission key has its type defined by a feature's permission key type .
To
determine
whether
a
permission
key
key1
is
equal
to
a
permission
key
key2
,
given
a
PermissionDescriptor
descriptor
,
run
the
following
steps:
name
,
passing
key1
and
key2
.
A powerful feature is a web platform feature (usually an API) for which a user gives express permission before the feature can be used. Except for a few notable exceptions (e.g., the Notifications API Standard ), most powerful features are also policy-controlled features . For powerful features that are also policy-controlled features , [ Permissions-Policy ] controls whether a document is allowed to use a given feature. That is, a powerful feature can only request express permission from a user if the document has permission delegated to it via the corresponding policy-controlled feature (see example below). Subsequent access to the feature is determined by the user having granted permission, or by satisfying some criteria that is equivalent to a permission grant .
A powerful feature is identified by its name , which is a string literal (e.g., "geolocation").
The user agent tracks which powerful features the user has permission to use via the environment settings object .
Each
powerful
feature
can
define
zero
or
more
additional
aspects
.
An
aspect
is
defined
as
WebIDL
dictionary
that
inherits
from
PermissionDescriptor
and
serves
as
a
WebIDL
interface's
permission
descriptor
type
.
The permissions task source is a task source used to perform permissions-related tasks in this specification.
When a conforming specification specifies a powerful feature it:
PermissionDescriptor
.
Registering the newly specified powerful features in the Permissions Registry gives this Working Group an opportunity to provide feedback and check that integration with this specification is done effectively.
PermissionDescriptor
or
one
of
its
subtypes.
If
unspecified,
this
defaults
to
PermissionDescriptor
.
The
feature
can
define
a
partial
order
on
descriptor
instances.
If
descriptorA
is
stronger
than
descriptorB
,
then
if
descriptorA
's
permission
state
is
"
granted
",
descriptorB
's
permission
state
must
also
be
"
granted
",
and
if
descriptorB
's
permission
state
is
"
denied
",
descriptorA
's
permission
state
must
also
be
"
denied
".
Some
powerful
features
have
more
information
associated
with
them
than
just
a
PermissionState
.
Each
of
these
features
defines
an
extra
permission
data
type
.
For
example,
getUserMedia
()
needs
to
determine
which
cameras
the
user
has
granted
permission
to
access.
If
a
DOMString
name
names
one
of
these
features,
then
name
's
extra
permission
data
for
an
optional
environment
settings
object
settings
is
the
result
of
the
following
algorithm:
If specified, the extra permission data algorithm is usable for this feature.
PermissionStatus
or
one
of
its
subtypes.
If
unspecified,
this
defaults
to
PermissionStatus
.
Takes
an
instance
of
the
permission
descriptor
type
and
a
new
or
existing
instance
of
the
permission
result
type
,
and
updates
the
permission
result
type
instance
with
the
query
result.
Used
by
Permissions
'
query
(
permissionDesc
)
method
and
the
PermissionStatus
update
steps
.
If
unspecified,
this
defaults
to
the
default
permission
query
algorithm
.
The
default
permission
query
algorithm
,
given
a
PermissionDescriptor
permissionDesc
and
a
PermissionStatus
status
,
runs
the
following
steps:
status
's
state
to
permissionDesc
's
permission
state
.
The type of permission key used by the feature. Defaults to origin . A feature that specifies a custom permission key type MUST also specify a permission key generation algorithm .
Takes an environment settings object , and returns a new permission key . If unspecified, this defaults to the default permission key generation algorithm . A feature that specifies a custom permission key generation algorithm MUST also specify a permission key comparison algorithm .
The default permission key generation algorithm , given an environment settings object settings , runs the following steps:
Takes two permission keys and returns a boolean that shows whether the two keys are equal. If unspecified, this defaults to the default permission key comparison algorithm .
The default permission key comparison algorithm , given permission keys key1 and key2 , runs the following steps:
Takes no arguments. Updates any other parts of the implementation that need to be kept in sync with changes in the results of permission states or extra permission data .
If unspecified, this defaults to running react to the user revoking permission .
Specifications that define one or more powerful features SHOULD suggest a permission lifetime that is best suited for the particular feature. Some guidance on determining the lifetime of a permission is noted below, with a strong emphasis on user privacy. If no lifetime is specified, the user agent provides one.
When the permission lifetime expires for an origin:
An
PermissionState
value
that
serves
as
a
permission
's
default
state
of
a
powerful
feature
.
If
not
specified,
the
permission
's
default
state
is
"
prompt
".
A default powerful feature is a powerful feature with all of the above types and algorithms defaulted.
To
get
the
current
permission
state
,
given
a
name
name
and
an
optional
environment
settings
object
settings
,
run
the
following
steps.
This
algorithm
returns
a
PermissionState
enum
value.
PermissionDescriptor
with
name
initialized
to
name
.
A
descriptor
's
permission
state
,
given
an
optional
environment
settings
object
settings
is
the
result
of
the
following
algorithm.
It
returns
a
PermissionState
enum
value:
denied
".
name
.
Document
run
the
following
step:
Document
.
denied
".
PermissionState
enum
value
from
entry
's
state
.
PermissionState
enum
value
that
represents
the
permission
state
of
feature
,
taking
into
account
any
permission
state
constraints
for
descriptor
's
name
.
As
a
shorthand,
a
DOMString
name
's
permission
state
is
the
permission
state
of
a
PermissionDescriptor
with
its
name
member
set
to
name
.
To
request
permission
to
use
a
descriptor
,
the
user
agent
must
perform
the
following
steps.
This
algorithm
returns
either
"
granted
"
or
"
denied
".
prompt
",
return
current
state
and
abort
these
steps.
granted
"
if
the
administrator
granted
permission;
otherwise
to
"
denied
".
granted
";
otherwise
to
"
denied
".
The
user's
interaction
may
provide
new
information
about
the
user's
intent
for
the
origin
.
This is intentionally vague about the details of the permission UI and how the user agent infers user intent. User agents should be able to explore lots of UI within this framework.
As
a
shorthand,
requesting
permission
to
use
a
DOMString
name
,
is
the
same
as
requesting
permission
to
use
a
PermissionDescriptor
with
its
name
member
set
to
name
.
To
prompt
the
user
to
choose
one
or
more
options
associated
with
a
given
descriptor
and
an
optional
boolean
allowMultiple
(default
false),
the
user
agent
must
perform
the
following
steps.
This
algorithm
returns
either
"
denied
"
or
the
user's
selection.
denied
",
return
"
denied
"
and
abort
these
steps.
granted
",
the
user
agent
may
return
one
(or
more
if
allowMultiple
is
true)
of
options
chosen
by
the
user
and
abort
these
steps.
If
the
user
agent
returns
without
prompting,
then
subsequent
prompts
for
the
user
to
choose
from
the
same
set
of
options
with
the
same
descriptor
must
return
the
same
option(s),
unless
the
user
agent
receives
new
information
about
the
user's
intent
.
denied
".
This is intentionally vague about the details of the permission UI and how the user agent infers user intent. User agents should be able to explore lots of UI within this framework.
As
a
shorthand,
prompting
the
user
to
choose
from
options
associated
with
a
DOMString
name
,
is
the
same
as
prompting
the
user
to
choose
from
those
options
associated
with
a
PermissionDescriptor
with
its
name
member
set
to
name
.
When
the
user
agent
learns
that
the
user
no
longer
intends
to
grant
permission
to
use
a
feature
described
by
the
PermissionDescriptor
descriptor
in
the
context
described
by
the
permission
key
key
,
react
to
the
user
revoking
permission
by
running
these
steps:
name
's
permission
revocation
algorithm
.
WebIDL[Exposed=(Window,Worker)]
interface Permissions
{
Promise<PermissionStatus
> query
(object permissionDesc);
};
dictionary PermissionDescriptor
{
required DOMString name
;
};
When
the
query()
method
is
invoked,
the
user
agent
MUST
run
the
following
query
a
permission
algorithm,
passing
the
parameter
permissionDesc
:
Window
object,
then:
Document
is
not
fully
active
,
return
a
promise
rejected
with
an
"
InvalidStateError
"
DOMException
.
PermissionDescriptor
.
name
"]
is
not
supported,
return
a
promise
rejected
with
a
TypeError
.
name
's
permission
descriptor
type
.
PermissionStatus
with
typedDescriptor
.
[[query]]
internal
slot.
name
's
permission
query
algorithm
,
passing
query
and
status
.
WebIDL[Exposed=(Window,Worker)]
interface PermissionStatus
: EventTarget {
readonly attribute PermissionState
state
;
readonly attribute DOMString name
;
attribute EventHandler onchange
;
};
enum PermissionState
{
,
,
"granted
",
"denied
",
"prompt
",
};
PermissionStatus
instances
are
created
with
a
[[query]]
internal
slot,
which
is
an
instance
of
a
feature's
permission
descriptor
type
.
The
"
granted
",
"
denied
",
and
"
prompt
"
enum
values
represent
the
concepts
of
granted
,
denied
,
and
prompt
respectively.
To
create
a
PermissionStatus
for
a
given
PermissionDescriptor
permissionDesc
:
name
.
The
name
attribute
returns
the
value
it
was
initialized
to.
The
state
attribute
returns
the
latest
value
that
was
set
on
the
current
instance.
The
onchange
attribute
is
an
event
handler
whose
corresponding
event
handler
event
type
is
change
.
Whenever
the
user
agent
is
aware
that
the
state
of
a
PermissionStatus
instance
status
has
changed,
it
asynchronously
runs
the
PermissionStatus
update
steps
:
Window
object,
then:
[[query]]
internal
slot.
name
's
permission
query
algorithm
,
passing
query
and
status
.
change
at
status
.
A
PermissionStatus
object
MUST
NOT
be
garbage
collected
if
it
has
an
event
listener
whose
type
is
change
.
As well as sections marked as non-normative, all authoring guidelines, diagrams, examples, and notes in this specification are non-normative. Everything else in this specification is normative.
The key words MAY , MUST , MUST NOT , OPTIONAL , and SHOULD in this document are to be interpreted as described in BCP 14 [ RFC2119 ] [ RFC8174 ] when, and only when, they appear in all capitals, as shown here.
Two classes of product can claim conformance to this specification: user agents and other specifications (i.e., a technical report that specifies a powerful feature in a manner that conforms to the requirements of this specification).
This section is non-normative.
Although both this specification and the Permissions Policy specification deal with "permissions", each specification serves a distinct purpose in the platform. Nevertheless, the two specifications do explicitly overlap.
On the one hand, this specification exclusively concerns itself with powerful features whose access is managed through a user-agent mediated permissions UI (i.e., permissions where the user gives express consent before that feature can be used, and where the user retains the ability to deny that permission at any time for any reason). These powerful features are registered in the Permissions Registry .
On
the
other
hand,
the
Permissions
Policy
specification
allows
developers
to
selectively
enable
and
disable
policy-controlled
features
through
a
"
permissions
policy
"
(be
it
a
HTTP
header
or
the
allow
attribute).
In
that
sense,
the
Permissions
Policy
subsumes
this
specification
in
that
Permissions
Policy
governs
whether
a
feature
is
available
at
all,
independently
of
this
specification.
These
policy-controlled
features
are
also
registered
in
the
Permissions
Registry
.
A powerful feature that has been disabled by the Permissions Policy specification always has its permission state reflected as "denied" by this specification. This occurs because reading the current permission relies on [ HTML ]'s " allowed to use " check, which itself calls into the Permissions Policy specification. Important to note here is the sharing of permission names across both specifications. Both this specification and the Permissions Policy specification rely on other specifications defining the names of the permission and name , and they are usually named the same thing (e.g., "geolocation" of the Geolocation API , and so on).
Finally, it's not possible for a powerful feature to ever become "granted" through any means provided by the Permissions Policy specification. The only way that a powerful feature can be granted is by the user giving express permission or by some user agent policy.
For the purposes of user-agent automation and application testing, this document defines the following extension commands for the [ WebDriver ] specification. It is OPTIONAL for a user agent to support extension commands commands.
WebIDLdictionary PermissionSetParameters
{
required PermissionDescriptor
descriptor
;
required PermissionState
state
;
};
HTTP Method | URI Template |
---|---|
POST | /session/{session id}/permissions |
The
Set
Permission
extension
command
simulates
user
modification
of
a
PermissionDescriptor
's
permission
state
.
The remote end steps are:
PermissionSetParameters
.
If
this
throws
an
exception,
return
an
invalid
argument
error
.
descriptor
.
rootDesc
.
name
's
permission
descriptor
type
.
If
this
throws
an
exception,
return
a
invalid
argument
error
.
state
is
an
inappropriate
permission
state
for
any
implementation-defined
reason,
return
a
invalid
argument
error
.
For
example,
user
agents
that
define
the
"midi"
powerful
feature
as
"always
on"
may
choose
to
reject
a
command
to
set
the
permission
state
to
"
denied
"
at
this
step.
state
as
if
it
were
the
result
of
an
invocation
of
permission
state
for
typedDescriptor
with
the
argument
target
made
at
this
moment.
null
.
An adversary could use a permission state as an element in creating a "fingerprint" corresponding to an end-user. Although an adversary can already determine the state of a permission by actually using the API, that often leads to a UI prompt being presented to the end-user (if the permission was not already granted ). Even though this API doesn't expose new fingerprinting information to websites, it makes it easier for an adversary to have discreet access to this information.
A user agent SHOULD provide a means for the user to review, update, and reset the permission state of powerful features associated with an origin .
Some user agents support administrators who can override user choices about permissions, either to block permissions or to allow them on certain sites. Overriding user choices in this way can be a privacy problem, so this specification requires that the user agent inform users when it happens.
These administrators might be able to configure either an individual user agent or the device it runs on, or both. It can be a privacy problem for a device-level administrator to control a powerful feature that primarily operates on a single user agent , and it can also be a privacy problem for a user-agent-level administrator to control another powerful feature that operates on the device as a whole. Implementations should take this into account when defining their administration policies, but for now the details aren't standardized.
There are no documented security considerations at this time. Readers are instead encouraged to read section C. Privacy considerations .
WebIDL[Exposed=(Window)]
partial interface Navigator {
[SameObject] readonly attribute Permissions
permissions
;
};
[Exposed=(Worker)]
partial interface WorkerNavigator {
[SameObject] readonly attribute Permissions
permissions
;
};
[Exposed=(Window,Worker)]
interface Permissions
{
Promise<PermissionStatus
> query
(object permissionDesc);
};
dictionary PermissionDescriptor
{
required DOMString name
;
};
[Exposed=(Window,Worker)]
interface PermissionStatus
: EventTarget {
readonly attribute PermissionState
state
;
readonly attribute DOMString name
;
attribute EventHandler onchange
;
};
enum PermissionState
{
,
,
"granted
",
"denied
",
"prompt
",
};
dictionary PermissionSetParameters
{
required PermissionDescriptor
descriptor
;
required PermissionState
state
;
};
This section is non-normative.
The editors would like to thank Adrienne Porter Felt, Anne van Kesteren, Domenic Denicola, Jake Archibald and Wendy Seltzer for their help with the API design and editorial work.
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in: