I implemented web push notifications using service worker. I collected user subscriptions with a particular application server key. Suppose if we change the application server key, then when we get the subscription using "reg.pushManager.getSubscription()", we will get the old subscription information which was created using the old application server key. How to handle this scenario? How to get the new subscription from the user?
-
check https://w3c.github.io/push-api/#dfn-push-subscription – Pranay Kumar Sep 04 '17 at 19:28
4 Answers
Get the subscription using reg.pushManager.getSubscription()
and check whether current subscription uses the new application server key. If not, then call unsubscribe()
function on the existing subscription and resubscribe again.
-
can you ellaborate on that? I can't understand exactly where can I get the subscription object. – Adriano Bacha Mar 09 '21 at 14:55
-
take a look here: https://developer.mozilla.org/en-US/docs/Web/API/PushSubscription (the example code) – Hafnernuss Jun 26 '21 at 13:40
After properly starting the service worker and getting the permissions, call navigator.serviceWorker.ready
in order to get access to the *.pushManager
object.
From this object we call another promise to get the pushSubscription
object we actually care about.
If the user was never subscribed pushSubscription
will be null
otherwise we get the key from it and check if it's different, if that's the case we unsubscribe the user and subscribe them again.
var NEW_PUBLIC_KEY = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';
Notification.requestPermission(function (result) {
if (permissionResult == 'granted'){
subscribeUser();
}
});
function subscribeUser() {
navigator.serviceWorker.ready
.then(registration => {
registration.pushManager.getSubscription()
.then(pushSubscription => {
if(!pushSubscription){
//the user was never subscribed
subscribe(registration);
}
else{
//check if user was subscribed with a different key
let json = pushSubscription.toJSON();
let public_key = json.keys.p256dh;
console.log(public_key);
if(public_key != NEW_PUBLIC_KEY){
pushSubscription.unsubscribe().then(successful => {
// You've successfully unsubscribed
subscribe(registration);
}).catch(e => {
// Unsubscription failed
})
}
}
});
})
}
function subscribe(registration){
registration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: urlBase64ToUint8Array(NEW_PUBLIC_KEY)
})
.then(pushSubscription => {
//successfully subscribed to push
//save it to your DB etc....
});
}
function urlBase64ToUint8Array(base64String) {
var padding = '='.repeat((4 - base64String.length % 4) % 4);
var base64 = (base64String + padding)
.replace(/\-/g, '+')
.replace(/_/g, '/');
var rawData = window.atob(base64);
var outputArray = new Uint8Array(rawData.length);
for (var i = 0; i < rawData.length; ++i) {
outputArray[i] = rawData.charCodeAt(i);
}
return outputArray;
}

- 51
- 1
- 2
In my case, I managed to solve it by clearing the cache and cookies

- 1
-
Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Nov 12 '21 at 19:27
The key you get from calling sub.getKey('p256dh')
(or sub.toJSON.keys.p256dh
) is the client's public key, it will always be different from the server public key. You need to compare the new public server key and sub.options.applicationServerKey
.
sub
above is the resolved promise from reg.pushManager.getSubscription()
.
Therefore:
- Get PushSubscription interface -
reg.pushManager.getSubscription().then(sub => {...})
, if sub is null no subscription exists, therefore no worry, but if it's defined: - Inside the block get the current key in use
sub.options.applicationServerKey
- Convert it to string, because you can't compare ArrayBuffer directly -
const curKey = btoa(String.fromCharCode.apply(null, new Uint8Array(sub.options.applicationServerKey)))
- Compare it with your new key. If the keys are different call
sub.unsubscribe()
and then subscribe again by callingreg.pushManager.subscribe(subscribeOptions)
, where subscribeOptions uses your new key. You call 'unsubscribe' on PushSubscription, butsubscribe
on PushManager

- 1
- 1