Abstract

The Permissions API allows a web application to be aware of the status of a given permission, to know whether it is granted, denied or if the user will be asked whether the permission should be granted.

Status of This Document

This section describes the status of this document at the time of its publication. Other documents may supersede this document. A list of current W3C publications and the latest revision of this technical report can be found in the W3C technical reports index at http://www.w3.org/TR/.

This document was published by the Web Application Security Working Group as a First Public Working Draft. This document is intended to become a W3C Recommendation. If you wish to make comments regarding this document, please send them to public-webappsec@w3.org (subscribe, archives). All comments are welcome.

Publication as a First Public Working Draft does not imply endorsement by the W3C Membership. 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 5 February 2004 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 1 August 2014 W3C Process Document.

Table of Contents

1. Conformance

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 RECOMMENDED are to be interpreted as described in [RFC2119].

This specification defines conformance criteria that apply to a single product: the user agent that implements the interfaces that it contains.

Implementations that use ECMAScript to expose the APIs defined in this specification MUST implement them in a manner consistent with the ECMAScript Bindings defined in the Web IDL specification [WEBIDL].

2. Dependencies

The following concepts and interfaces are defined in [HTML]:

Promise objects are defined in [ECMASCRIPT].

3. Scope of this document

This section is non-normative.

This document goal is to specify an API that will help developers to handle permissions on the Web platform. Web APIs have different ways to deal with permissions. The [notifications] API allows developers to request a permission and check the permission status explicitly. Others might only expose the status to web pages. Some, like [geolocation-API] will keep the page unaware of the permission associated with the feature.

Being able to know whether an API call is going to prompt is mandatory in order to provide a good user experience. Unfortunately, more often than not, those prompts can't be controlled by the developers.

The API specified in this document is meant to provide the tools so that web applications can improve their user experience when permissions are involved.

The solution described in this document is meant to be extensible but isn't meant to be applicable to all the current and future permissions available in the web platform. If you are working on a specification that has a permission model that wouldn't fit in the model described in this document, please contact the editors or file an issue. We would love to hear about it.

The initial intent of this document was to allow web applications to request and revoke permissions explicitly in addition of query the permission status. This is an aspect of the specification that was controversial thus removed from the current document in a spirit of incremental changes: settling on a small API that can be improved.

4. Permission Registry

enum PermissionName {
    "geolocation",
    "notifications",
    "push-notifications",
    "midi-sysex"
};

The PermissionName enum defines the list of known permissions. These permissions are meant to be associated with a use case instead of one API. Thus, some permissions have a 1:1 relationship with an API while some others might include more than one API or even a subset of an API.

Note

For example, push-notifications is exposing the ability for a web page to use push messages in order to show notifications. Implementations might associate it with full usage of the Push API and the Notifications API while others will force the callers to use the Push API only in order to use the Notifications API.

Specifications are welcome to request a new name to be added to this registry instead of trying to monkey patch it.

The geolocation permission is the permission associated with the usage of the [geolocation-API].

The notifications permission is the permission associated with the usage of the [notifications] API.

The push-notifications permission is the permission associated with the usage of the [push-api] in order to show notifications using the [notifications] API.

The midi-sysex permission is the permission associated with the usage of sysex messages in the [webmidi] API.

5. Permission definition

dictionary Permission {
    required PermissionName name;
};

A Permission dictionary MUST contain a name field which represents the permission's identifier.

If a permission has to be defined by more than its name, it is RECOMMENDED to inherit from Permission dictionary and add new fields.

Note
There are currently no permission defined in this specification using this dictionary. It is only specified here in order to expose the ability for the API to be extended to more complex permissions.
For example, if the [quota-api] were to have an associated permission, it could define a QuotaPermission dictionary extending Permission with type and value fields.

6. Status of a permission

enum PermissionState {
    "granted",
    "denied",
    "prompt"
};

The steps to retrieve the permission state of a global object for a given permission are as follows:

  1. If the user agent will allow the global object to try to access the features associated with the permission but will prompt the user to know whether the call should succeed or fail, the user agent MUST return prompt.
  2. Otherwise, if the user agent will allow the global object to access the features associated with the permission without prompting the user, the user agent MUST return granted .
  3. Otherwise, the user agent will not allow the global object to access the feature associated with permission and MUST return denied .

How the user agent decides whether a global object is allowed or not to access some features is left as an implementation details. However, the implementation MUST be consistent and not return different values unless something happened (user action, expiration).

It is RECOMMENDED for implementations to use the origins of the Document or Worker when making security decisions. Other factors MAY also apply like whether the permission is associated with a [powerful-features] or whether the Document is embedded.

Issue 1
The retrieve the permission state algorithm does not take into account all the theoretically possible use cases. It tries to stay inside the scope of the permissions described in this document.
There are open questions about use cases where it might not work as well: issue 8 and issue 9.
[Exposed=(Window,Worker)]
interface PermissionStatus : EventTarget {
    readonly    attribute Permission      permission;
    readonly    attribute PermissionState status;
                attribute EventHandler    onchange;
};

The steps to update the status of a PermissionStatus instance are as follow:

  1. Let status be the PermissionStatus instance being updated.
  2. Run the steps to retrieve the permission state using the status' global object and permission attribute then set the result of those steps to the status attribute.

The steps to create a PermissionStatus for a given permission are as follow:

  1. Let status be a PermissionStatus instance.
  2. Set the permission attribute to permission.
  3. Run the steps to update the status on status.
  4. Return status.

The permission attribute MUST return the Permission it was initially set to at the object creation.

The status attribute MUST return the latest value that was set while running the update the status steps 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 status of a PermissionStatus instance has changed, it MUST asynchronously run the following steps:

  1. Let permission-status be the PermissionStatus for which the status has changed.
  2. Run the steps to update the status of permission-status.
  3. Queue a task on the permission task source to fire a simple event named change at permission-status.

7. Permissions interface

[Exposed=(Window,Worker)]
interface Permissions {
    static Promise<PermissionStatus> query ((Permission or PermissionName) permission);
};

When the query() method is invoked, the user agent MUST run the following steps:

  1. Let permission be permission argument if permission is of type Permission, otherwise, create a Permission instead for which name is set to the permission argument value.
  2. Let promise be a newly-created Promise.
  3. Return promise and continue those steps asynchronously.
  4. Run the steps to create a PermissionStatus using the global object and permission and resolve promise with the result of those steps.
Note
If a developer wants to check multiple permissions at once, the editors recommend them to use Promises.all(). It should yield to the same result and allow this API to stay simple. If it happens to be a very common use case, it should be easy to extend Permissions.query() to accept a sequence<> too.

8. Examples

This section is non-normative.

This example uses the Permissions API to decide whether local news should be shown using the Geolocation API or a button offering that feature should be added.

Example 1
<script>
  Permissions.query('geolocation').then(function(result) {
    if (result.status == 'granted') {
      showLocalNewsWithGeolocation();
    } else if (result.status == 'prompt') {
      showButtonToEnableLocalNews();
    }
    // Don't do anything if the permission was denied.
  });
</script>

This example is using the notifications permission for a chat application to show a notification button depending on the permission status.

Example 2
<script>
  function updateNotificationButton(permission) {
    document.getElementById('chat-notification-button').disabled = (permission.status == 'denied');
  }

  Permissions.query('notifications').then(function(result) {
    updateNotificationButton(result);

    result.addEventListener('change', function() {
      updateNotificationButton(this);
    });
  });
</script>

A. Acknowledgments

Thanks to Adrienne Porter Felt and Jake Archibald for their early support and help.

B. References

B.1 Normative references

[ECMASCRIPT]
Allen Wirfs-Brock. ECMA-262 ECMAScript Language Specification, Edition 6. Draft. URL: http://people.mozilla.org/~jorendorff/es6-draft.html
[HTML]
Ian Hickson. HTML. Living Standard. URL: https://html.spec.whatwg.org/
[RFC2119]
S. Bradner. Key words for use in RFCs to Indicate Requirement Levels. March 1997. Best Current Practice. URL: https://tools.ietf.org/html/rfc2119
[WEBIDL]
Cameron McCormack. Web IDL. 19 April 2012. W3C Candidate Recommendation. URL: http://www.w3.org/TR/WebIDL/

B.2 Informative references

[geolocation-API]
Andrei Popescu. Geolocation API Specification. 24 October 2013. W3C Recommendation. URL: http://www.w3.org/TR/geolocation-API/
[notifications]
John Gregg; Anne van Kesteren. Web Notifications. 12 September 2013. W3C Last Call Working Draft. URL: http://www.w3.org/TR/notifications/
[powerful-features]
Mike West. Requirements for Powerful Features. 4 December 2014. W3C Working Draft. URL: http://www.w3.org/TR/powerful-features/
[push-api]
Bryan Sullivan; Eduardo Fullea; Michael van Ouwerkerk. Push API. 7 October 2014. W3C Working Draft. URL: http://www.w3.org/TR/push-api/
[quota-api]
Kinuko Yasuda. Quota Management API. 5 November 2013. W3C Working Draft. URL: http://www.w3.org/TR/quota-api/
[webmidi]
Chris Wilson; Jussi Kalliokoski. Web MIDI API. 17 March 2015. W3C Working Draft. URL: http://www.w3.org/TR/webmidi/