Is the VAPID public key the same as applicationServerKey client-side?

Flimm picture Flimm · May 10, 2017 · Viewed 7.3k times · Source

On the client-side, to subscribe to web push notifications, you need to call subscribe with the applicationServerKey option, like this:

var serviceWorkerRegistration = ...
serviceWorkerRegistration.pushManager.subscribe({
  userVisibleOnly: true,
  applicationServerKey: urlB64ToUint8Array("......")
}).then(function(subscription) {
   ...
})

You can send the subscription object to the server, where it can be saved.

To send a push message to the subscriber, the server needs to post to the URL indicated by the key endpoint in the object subscription. The server needs to identify itself to the provider (Mozilla or Google or whoever) using VAPID. For instance, using the Python library pywebpush, this call would be made:

import pywebpush
pywebpush.webpush(
    subscription,
    data,
    vapid_private_key="path_to_private_key.pem",
    vapid_claims={"sub": "mailto:[email protected]"},
)

Here's my question:

Is the private VAPID key used to send the push message the one that corresponds to the public key passed to serviceWorkerRegistration.pushManager.subscribe on the client-side? Or does it belong to a separate keypair? My intuition tells me it should belong to the same keypair, but the term VAPID is only ever mentioned when talking about sending push messages, and not when subscribing, so I'm not confident that that assumption is correct.

Answer

Flimm picture Flimm · May 10, 2017

Yes, it belongs to the same keypair. This blog post Web Push Interoperability Wins makes it clearer:

The process is pretty simple:

  1. Your application server creates a public/private key pair. The public key is given to your web app.
  2. When the user elects to receive pushes, add the public key to the subscribe() call's options object.
  3. When your app server sends a push message, include a signed JSON Web Token along with the public key.

Depending on what library you're using on the server, you may need the private key in a different format. For instance, pywebpush for Python expects a VAPID EC2 private key PEM file, or a string in the DER format and base64.