Copyright © 2022 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 a Working Draft using the Recommendation track.
Publication as a Working 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:
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 algorithms and types. When the defaults are not suitable for a particular powerful feature, a specification MAY override below 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.
          
To get the current permission state, given a name name and an optional environment settings object settings:
PermissionDescriptor
          whose name is initialized with name.
          
          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":
        
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 accelerometer enum value identifies the Accelerometer API powerful feature.
      
        The ambient-light-sensor enum value identifies the Ambient Light Sensor
        powerful feature.
      
        The background-fetch enum value identifies the Background Fetch
        powerful feature.
      
        The background-sync enum value identifies the Web Background Synchronization
        powerful feature.
      
        The bluetooth enum value identifies the Web Bluetooth powerful feature.
      
        The camera and microphone enum values identify the
        Media Capture and Streams powerful features.
      
        The display-capture enum value identifies the Screen Capture powerful feature.
      
        The geolocation enum value identifies the Geolocation API powerful feature.
      
        The gyroscope enum value identifies the Gyroscope API powerful feature.
      
        The magnetometer enum value identifies the Magnetometer API powerful feature.
      
        The midi enum value identifies the Web MIDI API powerful feature.
      
        The nfc enum value identifies the Web NFC API powerful feature.
      
        The notifications enum value identifies the Notifications API Standard powerful feature.
      
        The persistent-storage enum value identifies the Storage Standard powerful feature.
      
        The push enum value identifies the Push API powerful feature.
      
        The speaker-selection enum value identifies the Audio Output Devices API powerful feature.
      
        The xr-spatial-tracking enum value identifies the WebXR Device API Device API
        powerful feature.
      
          The screen-wake-lock enum value identifies the Screen Wake Lock 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.
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, 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.
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 a realm or origin.
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 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",
};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:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in: