Copyright © 2021 W3C ® ( MIT , ERCIM , Keio , Beihang ). W3C liability , trademark and permissive document license rules apply.
The Permissions API specification defines common infrastructure that other specifications can use to interact with browser permissions that allow or deny access to powerful features on the web platform. For developers, the specification defines an API to query the permission state of a powerful feature, or be notified if a permission for 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.
Some features in this specification are supported by only one user agent, and as such, are marked as at risk .
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 1 August 2017 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 2 November 2021 W3C Process Document .
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
is
checking
whether
the
page
has
the
"
geolocation
"
and
the
"
notifications
"
permissions:
const queryPromises = ["geolocation", "notifications"].map(name => {
return 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 access a powerful feature .
Conceptually, a permission can be in one of the following states :
A user agent SHOULD provide a means for the user to review, update, and reset the permission state of powerful features associated with a realm or origin.
To ascertain new information about the user's intent , a user agent MAY collect 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.
A powerful feature is a web platform feature (usually an API) for which a user gives express permission before the feature can be used. Access to the feature is determined by the environment settings object by the user having granted permission via UI, or by satisfying some criteria that is equivalent to a permission grant .
Express permission refers to an act by the user, e.g. via user interface or host device platform features, through which the user grants permission the use of the feature by the web application.
A powerful feature is identified by its name , which is a string literal (e.g., "geolocation").
The user agent is responsible for tracking what powerful features each realm has the user's permission to use. Other specifications can use the operations defined in this section to retrieve the UA's notion of what permissions are granted or denied, and to ask the user to grant or deny more permissions.
Specifications wanting to add a new powerful feature are encouraged to coordinate with us on this specification via GitHub.
Each powerful feature has the following permission-related flags, algorithms, and types. When the defaults are not suitable for a particular powerful feature , a specification MAY override below flags, algorithms, and types below.
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
".
{name:
"
("midi-with-sysex")
is
stronger
than
midi
",
sysex:
true}
{name:
"
("midi-without-sysex"),
so
if
the
user
denies
access
to
midi-without-sysex,
the
UA
must
also
deny
access
to
midi-with-sysex,
and
similarly
if
the
user
grants
access
to
midi-with-sysex,
the
UA
must
also
grant
access
to
midi-without-sysex.
midi
",
sysex:
false}
Some
powerful
features
have
more
information
associated
with
them
than
just
a
PermissionState
.
For
example,
getUserMedia
()
needs
to
determine
which
cameras
the
user
has
granted
the
current
realm
permission
to
access.
Each
of
these
features
defines
an
extra
permission
data
type
.
If
a
PermissionName
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.
PermissionName
's
extra
permission
data
.
Defaults
to
no
constraints
beyond
the
user's
intent.
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
.state
to
permissionDesc
's
permission
state
.
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 , and then react to the user revoking permission .
If unspecified, this defaults to running react to the user revoking permission .
Every permission has a lifetime , which is the duration for which a particular permission remains granted before it reverts back to its default permission state . A lifetime could be until a particular Realm is destroyed, until a particular top-level browsing context is destroyed, an amount of time, or 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 policy.
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:
A default powerful feature is a powerful feature with all of the above types and algorithms defaulted.
Each powerful feature can define zero or more additional aspects that websites can request permission to access.
To
describe
an
aspect
,
a
specification
MUST
define
a
WebIDL
dictionary
that
inherits
from
PermissionDescriptor
,
and
have
that
interface
be
its
permission
descriptor
type
.
A
descriptor
's
permission
state
for
an
optional
environment
settings
object
settings
is
the
result
of
the
following
algorithm,
which
returns
one
of
"
granted
",
"
prompt
",
or
"
denied
":
name
isn't
allowed
in
non-secure
contexts
,
then
return
"
denied
".
name
and
settings
has
an
associated
Document
named
document
,
run
the
following
step:
name
return
"
denied
".
name
:
Safari is the only known UA that returns different results from this algorithm for different settings objects with the same origin. We should test which of the several possible settings objects it uses.
As
a
shorthand,
a
PermissionName
name
's
permission
state
is
the
permission
state
of
a
PermissionDescriptor
with
its
name
member
set
to
name
.
Spec authors, please note that algorithms in this section can wait for user input; so they shouldn't be used from other algorithms running on the main thread.
To
request
permission
to
use
a
descriptor
,
the
UA
must
perform
the
following
steps.
This
algorithm
returns
either
"
granted
"
or
"
denied
".
prompt
",
return
current
state
and
abort
these
steps.
granted
";
otherwise
return
"
denied
".
The
user's
interaction
may
provide
new
information
about
the
user's
intent
for
this
realm
and
other
realms
with
the
same
origin
.
This is intentionally vague about the details of the permission UI and how the UA infers user intent. UAs should be able to explore lots of UI within this framework.
As
a
shorthand,
requesting
permission
to
use
a
PermissionName
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
of
several
options
associated
with
a
descriptor
,
the
UA
must
perform
the
following
steps.
This
algorithm
returns
either
"
denied
"
or
one
of
the
options.
denied
",
return
"
denied
"
and
abort
these
steps.
granted
",
the
UA
may
return
one
of
options
and
abort
these
steps.
If
the
UA
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,
unless
the
UA
receives
new
information
about
the
user's
intent
.
denied
".
If
the
user's
interaction
indicates
they
intend
this
choice
to
apply
to
other
realms,
then
treat
this
this
as
new
information
about
the
user's
intent
for
other
realms
with
the
same
origin
.
This is intentionally vague about the details of the permission UI and how the UA infers user intent. UAs should be able to explore lots of UI within this framework.
As
a
shorthand,
prompting
the
user
to
choose
from
options
associated
with
a
PermissionName
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 UA learns that the user no longer intends to grant permission for a realm to use a feature , react to the user revoking permission by:
Permissions
interface
WebIDL[Exposed=(Window,Worker)]
interface Permissions {
Promise<PermissionStatus> query(object permissionDesc);
};
dictionary PermissionDescriptor {
required PermissionName name;
};
query()
method
When
the
query()
method
is
invoked,
the
user
agent
MUST
run
the
following
query
a
permission
algorithm,
passing
the
parameter
permissionDesc
:
PermissionDescriptor
.
If
this
throws
an
exception,
return
a
promise
rejected
with
that
exception
and
abort
these
steps.
name
's
permission
descriptor
type
.
If
this
throws
an
exception,
return
a
promise
rejected
with
that
exception
and
abort
these
steps.
Promise
.
PermissionStatus
for
typedDescriptor
,
and
let
status
be
the
result.
[[query]]
internal
slot.
name
's
permission
query
algorithm
,
passing
query
and
status
.
PermissionStatus
interface
WebIDL[Exposed=(Window,Worker)]
interface PermissionStatus : EventTarget {
readonly attribute PermissionState state;
readonly attribute PermissionName 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
.
When
using
the
API,
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
,
return
a
new
instance
of
the
permission
result
type
for
the
feature
named
by
permissionDesc
's
name
,
with
the
[[query]]
internal
slot
initialized
to
permissionDesc
,
and
name
initialized
to
permissionDesc
's
name
.
name
attribute
The
name
attribute
returns
the
value
it
was
initialized
to.
state
attribute
The
state
attribute
returns
the
latest
value
that
was
set
on
the
current
instance.
onchange
attribute
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
:
[[query]]
internal
slot.
name
's
permission
query
algorithm
,
passing
query
and
status
.
change
at
status
.
While
an
PermissionStatus
object
has
one
or
more
event
listeners
registered
for
"change",
there
must
be
a
strong
reference
from
the
Window
or
WorkerGlobalScope
object
that
the
PermissionStatus
object's
constructor
was
invoked
from
to
the
PermissionStatus
object
itself.
While
there
is
a
task
queued
by
an
PermissionStatus
object
on
the
permissions
task
source
,
there
must
be
a
strong
reference
from
the
Window
or
WorkerGlobalScope
object
that
the
PermissionStatus
object's
constructor
was
invoked
from
to
that
PermissionStatus
object.
WebIDLenum PermissionName {
"accelerometer",
"ambient-light-sensor",
"background-fetch",
"background-sync",
"bluetooth",
"camera",
"display-capture",
"geolocation",
"gyroscope",
"magnetometer",
"microphone",
"midi",
"nfc",
"notifications",
"persistent-storage",
"push",
"screen-wake-lock",
"speaker-selection",
"xr-spatial-tracking",
};
Each
enumeration
value
in
the
PermissionName
enum
identifies
a
powerful
feature
.
The
ambient-light-sensor
enum
value
identifies
the
Ambient
Light
Sensor
API
powerful
feature
.
The
geolocation
enum
value
identifies
the
Geolocation
API
powerful
feature
.
The
midi
enum
value
identifies
the
Web
MIDI
API
powerful
feature
.
The
push
enum
value
identifies
the
Push
API
powerful
feature
.
The
notifications
enum
value
identifies
the
Notifications
API
Standard
powerful
feature
.
It
is
a
default
powerful
feature
with
its
allowed
in
non-secure
contexts
flag
set.
The
screen-wake-lock
enum
value
identifies
the
Screen
Wake
Lock
API
API
powerful
feature
.
It
is
a
default
powerful
feature
.
This powerful feature only has a single implementation, and therefore, as per the W3C Process, it is at risk .
The
camera
,
microphone
,
and
speaker-selection
permissions
are
associated
with
permission
to
use
media
devices
as
specified
in
[
GETUSERMEDIA
]
and
[
audio-output
].
These permissions only have a single implementation, and therefore, as per the W3C Process, are at risk .
WebIDLdictionary DevicePermissionDescriptor : PermissionDescriptor {
DOMString deviceId;
};
dictionary CameraDevicePermissionDescriptor : DevicePermissionDescriptor {
boolean panTiltZoom = false;
};
A permission covers access to the device given in the associated descriptor.
If
the
descriptor
does
not
have
a
deviceId
,
its
semantic
is
that
it
queries
for
access
to
all
devices
of
that
class.
Thus,
if
a
query
for
the
"
camera
"
permission
with
no
deviceId
returns
"
granted
",
the
client
knows
that
there
will
never
be
a
permission
prompt
for
a
camera,
and
if
"
denied
"
is
returned,
it
knows
that
no
getUserMedia
request
for
a
camera
will
succeed.
If
a
permission
state
is
present
for
access
to
some,
but
not
all,
cameras,
a
query
without
the
deviceId
will
return
"
prompt
".
{name:
"camera",
panTiltZoom:
true}
is
stronger
than
{name:
"camera",
panTiltZoom:
false}
.
Note that a "granted" permission is no guarantee that getUserMedia will succeed. It only guarantees that the user will not be prompted for permission. There are many other things (such as constraints or the camera being in use) that can cause getUserMedia to fail.
deviceId
values
for
the
devices
the
user
has
made
a
non-default
decision
on
access
to.
status
.state
to
permissionDesc
's
permission
state
and
terminate
these
steps.
deviceId
member
removed.
status
.state
to
global
's
permission
state
.
name
and
deviceId
as
arguments.
If
the
descriptor
does
not
have
a
deviceId
,
then
undefined
is
passed
in
place
of
deviceId
.
The
background-fetch
enum
value
identifies
the
Background
Fetch
powerful
feature
.
This powerful feature only has a single implementation, and therefore, as per the W3C Process, it is at risk .
The
background-sync
enum
value
identifies
the
Web
Background
Synchronization
powerful
feature
.
This powerful feature only has a single implementation, and therefore, as per the W3C Process, it is at risk .
The
bluetooth
enum
value
identifies
the
Web
Bluetooth
powerful
feature
.
This powerful feature only has a single implementation, and therefore, as per the W3C Process, it is at risk .
The
persistent-storage
is
enum
value
identifies
the
Storage
Standard
powerful
feature
.
This powerful feature only has a single implementation, and therefore, as per the W3C Process, it is at risk .
The
accelerometer
enum
value
identifies
the
Accelerometer
API
powerful
feature
.
Its
permission
revocation
algorithm
is
the
result
of
calling
generic
sensor
permission
revocation
algorithm
passing
it
"
accelerometer
"
as
argument.
This powerful feature only has a single implementation, and therefore, as per the W3C Process, it is at risk .
The
gyroscope
enum
value
identifies
the
Gyroscope
API
powerful
feature
.
Its
permission
revocation
algorithm
is
the
result
of
calling
generic
sensor
permission
revocation
algorithm
passing
it
"
gyroscope
"
as
argument.
This powerful feature only has a single implementation, and therefore, as per the W3C Process, it is at risk .
The
magnetometer
enum
value
identifies
the
Magnetometer
API
powerful
feature
.
Its
permission
revocation
algorithm
is
the
result
of
calling
generic
sensor
permission
revocation
algorithm
passing
it
"
magnetometer
"
as
argument.
The
display-capture
enum
value
identifies
the
Screen
Capture
powerful
feature
.
This powerful feature only has a single implementation, and therefore, as per the W3C Process, it is at risk .
This powerful feature only has a single implementation, and therefore, as per the W3C Process, it is at risk .
The
nfc
enum
value
identifies
the
Web
NFC
API
powerful
feature
.
The
xr-spatial-tracking
enum
value
identifies
the
WebXR
Device
API
Device
API
powerful
feature
.
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
and
,
MUST
,
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.
This section is non-normative.
Although technically this specification and the Permissions Policy specification ([ Permissions-Policy ]) 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
explicitly
identified
by
this
specification's
PermissionName
enum.
On
the
other
hand,
the
Permissions
Policy
specification
allows
developers
to
selectively
enable
and
disable
powerful
features
through
a
"
permissions
policy
"
(be
it
a
HTTP
header
or
a
the
allow
attribute).
The
APIs
and
features
in
scope
for
the
Permissions
Policy
specification
go
beyond
those
identified
in
this
specification's
PermissionName
enum
(e.g.,
"sync-xhr"
and
"gamepad").
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.
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
state
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.
Where
this
specification
has
the
PermissionName
enum,
the
Permissions
Policy
specification
relies
on
other
specifications
defining
the
names
of
the
permissions
(e.g.,
the
permission
"gamepad"
is
defined
in
[
Gamepad
],
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 through a user-agent provided permission UI, or by some other user agent policy.
This section is non-normative.
Automated testing of this specification is performed using the API provided by the Permissions Automation document.
This section is non-normative.
Web
pages
often
run
more-
and
less-trusted
components
as
the
same
origin.
For
example,
a
newspaper
may
run
advertising
code
without
sandboxing
it
into
a
cross-origin
iframe.
If
the
newspaper
has
a
legitimate
reason
to
use
a
person's
location,
that
also
happens
to
grant
access
to
the
less
trusted
advertiser.
Without
the
query
()
function
in
this
specification,
to
read
the
person's
location,
an
advertisement
needs
to
risk
showing
a
prompt,
which
exposes
it
to
detection.
With
this
function,
the
advertisement
can
silently
track
just
the
people
who've
already
granted
their
location
to
the
newspaper.
The
UA
might
provide
notice
of
when
permissions
are
in
use
on
a
page
which
might
increase
the
visibility
of
abuse.
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
permission
request
UI
being
presented
to
the
end-user
(if
the
permission
was
not
already
"
granted
").
Thus,
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.
Thus,
implementations
are
encouraged
to
have
an
option
for
users
to
block
(globally
or
selectively)
the
querying
of
permission
states
.
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 PermissionName name;
};
[Exposed=(Window,Worker)]
interface PermissionStatus : EventTarget {
readonly attribute PermissionState state;
readonly attribute PermissionName name;
attribute EventHandler onchange;
};
enum PermissionState {
"granted",
"denied",
"prompt",
};
enum PermissionName {
"accelerometer",
"ambient-light-sensor",
"background-fetch",
"background-sync",
"bluetooth",
"camera",
"display-capture",
"geolocation",
"gyroscope",
"magnetometer",
"microphone",
"midi",
"nfc",
"notifications",
"persistent-storage",
"push",
"screen-wake-lock",
"speaker-selection",
"xr-spatial-tracking",
};
dictionary DevicePermissionDescriptor : PermissionDescriptor {
DOMString deviceId;
};
dictionary CameraDevicePermissionDescriptor : DevicePermissionDescriptor {
boolean panTiltZoom = false;
};
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:
Referenced in:
Referenced in:
Referenced in:
Referenced in: