Skip to content

Commit

Permalink
PushManager.supportedContentEncodings updates (#36962)
Browse files Browse the repository at this point in the history
  • Loading branch information
hamishwillee authored Nov 29, 2024
1 parent a73295d commit 30b362d
Show file tree
Hide file tree
Showing 2 changed files with 98 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,62 @@ browser-compat: api.PushManager.supportedContentEncodings_static

{{APIRef("Push API")}}{{SecureContext_Header}}{{AvailableInWorkers}}

The **`supportedContentEncodings`** read-only static property of the
{{domxref("PushManager")}} interface returns an array of supported content codings that
can be used to encrypt the payload of a push message.
The **`supportedContentEncodings`** read-only static property of the {{domxref("PushManager")}} interface returns an array of supported content codings that can be used to encrypt the payload of a push message.

User agents must support the `aes128gcm` content coding defined in {{rfc("8291")}}, and may also support content codings defined from previous versions of the specification.
The returned array is frozen, and may not be modified by the recipient.

The application server requires this coding in order to encrypt push messages for sending to the push server.
The coding used for encryption is also included by the app server in the {{httpheader("Content-Encoding")}} HTTP header field of each push message.

The specification does not define how the client code should send the application server the supported codings, or the information in the {{domxref("PushSubscription")}} that it also needs in order to encrypt and send a push message.
One approach is shown in the examples section below.

## Value

An array of strings.
This usually contains just one value: `"aes128gcm"`.

## Exceptions

- `TypeError`
- : This is thrown when attempting to set a value in the returned array.

## Examples

### Sending coding information to the server

Push messages are encrypted on the application server for sending to the push server, and decrypted by the browser before being passed to the application service worker.
The public and private keys used are generated by the browser, and only the public key and an associated secret are shared with the web app, and hence the application server.
This ensures that push messages remain private as they pass through the push server infrastructure.

The [`p256dh`](/en-US/docs/Web/API/PushSubscription/getKey#p256dh) public key and [`auth`](/en-US/docs/Web/API/PushSubscription/getKey#auth) secret used for encrypting the message are provided to the service worker via its push subscription, using the {{domxref("PushSubscription.getKey()")}} method, along with the target endpoint for sending push messages in {{domxref("PushSubscription.endpoint")}}.
The coding that should be used for encryption is provided by `supportedContentEncodings`.

This information may be sent to the application server using any mechanism.
One approach is to put the needed information from {{domxref("PushSubscription")}} and `supportedContentEncodings` into a JSON object, serialize it using [`JSON.stringify()`](/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify) and post the result to the application server.

```js
// Get a PushSubscription object
const pushSubscription = await serviceWorkerRegistration.pushManager.subscribe();

// Create an object containing the information needed by the app server
const subscriptionObject = {
endpoint: pushSubscription.endpoint,
keys: {
p256dh: pushSubscription.getKeys('p256dh'),
auth: pushSubscription.getKeys('auth'),
},
encoding: PushManager.supportedContentEncodings,
/* other app-specific data, such as user identity */
};

// Stringify the object an post to the app server
fetch(`https://example.com/push/`, {
method: "post",
body: JSON.stringify(pushSubscription);
});
```

## Specifications

Expand Down
48 changes: 46 additions & 2 deletions files/en-us/web/api/pushsubscription/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ browser-compat: api.PushSubscription

{{ApiRef("Push API")}}{{SecureContext_Header}}{{AvailableInWorkers}}

The `PushSubscription` interface of the [Push API](/en-US/docs/Web/API/Push_API) provides a subscription's URL endpoint and allows unsubscribing from a push service.
The `PushSubscription` interface of the [Push API](/en-US/docs/Web/API/Push_API) provides a subscription's URL endpoint along with the public key and secrets that should be used for encrypting push messages to this subscription.
This information must be passed to the application server, using any desired application-specific method.

An instance of this interface can be serialized.
The interface also provides information about when the subscription will expire, and a method to unsubscribe from the subscription.

## Instance properties

Expand All @@ -31,8 +32,51 @@ An instance of this interface can be serialized.
- {{domxref("PushSubscription.unsubscribe()")}}
- : Starts the asynchronous process of unsubscribing from the push service, returning a {{jsxref("Promise")}} that resolves to a boolean value when the current subscription is successfully unregistered.

## Description

Each browser uses a particular push service.
A service worker can use {{domxref("PushManager.subscribe()")}} to subscribe to the supported service, and use the returned `PushSubscription` to discover the endpoint where push messages should be sent.

The `PushSubscription` is also used to get the public key and secret that the application server must use to encrypt the messages that it sends to the push service.
Note that the private keys used to decrypt push messages are not shared by the browser, and are used to decrypt messages before they are passed to the service worker.
This ensures that push messages remain private as they pass through the push server infrastructure.

The service worker doesn't need to know anything about the endpoints or encryption, other than to pass the relevant information onto the application server.
Any mechanism may be used to share the information with the application server.

## Example

### Sending coding information to the server

The [`p256dh`](/en-US/docs/Web/API/PushSubscription/getKey#p256dh) public key and [`auth`](/en-US/docs/Web/API/PushSubscription/getKey#auth) secret used for encrypting the message are provided to the service worker via its push subscription, using the {{domxref("PushSubscription.getKey()")}} method, along with the target endpoint for sending push messages in {{domxref("PushSubscription.endpoint")}}.
The coding that should be used for encryption is provided by the {{domxref("PushManager.supportedContentEncodings")}} static property.

This example shows how you might put the needed information from `PushSubscription` and `supportedContentEncodings` into a JSON object, serialize it using [`JSON.stringify()`](/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify), and post the result to the application server.

```js
// Get a PushSubscription object
const pushSubscription = await serviceWorkerRegistration.pushManager.subscribe();

// Create an object containing the information needed by the app server
const subscriptionObject = {
endpoint: pushSubscription.endpoint,
keys: {
p256dh: pushSubscription.getKeys('p256dh'),
auth: pushSubscription.getKeys('auth'),
},
encoding: PushManager.supportedContentEncodings,
/* other app-specific data, such as user identity */
};

// Stringify the object an post to the app server
fetch(`https://example.com/push/`, {
method: "post",
body: JSON.stringify(pushSubscription);
});
```

### Unsubscribing from a push manager

```js
navigator.serviceWorker.ready.then((reg) => {
reg.pushManager.getSubscription().then((subscription) => {
Expand Down

0 comments on commit 30b362d

Please sign in to comment.