I have been stuck in this problem since 3 days and searched Google, but to no success. I followed the instruction given in Push Notifications Example. But I get this nasty error when I try to implement it.
Uncaught (in promise) DOMException: Failed to execute 'atob' on 'Window': The string to be decoded is not correctly encoded.
I figured out the colon(:) is not allowed in Base64 String, but the Server Key given in Firebase in Cloud Messenging tab is
AAAA-8MWvk0:APA91bHmU8XL-rzOn9SPbpG98NSqAJcuhYBBh7oze_XhprBpK7Q9PPWm3PwBo6Llxby4zjhVtgvKPIaSAQGp-8RfMV10_d1GekzICrVX9oYO8pi6dOM4VTp52CCAzug6NYIa10tNddsgE2P5QowGAYcnRHxLkrHXsw
which contains a colon (don't worry, its just a test app so no problem with privacy).
When I tried to use the legacy server key, it simply throws an error. I tried to use other keys given in Firebase too, but to no success. Please tell me actually which server key to use and how?
I'm attaching my code snippet which actually performs the push subscription.
const API_KEY = "AIzaSyByIOl-mW0pu8SEXFeutB8jq59hhiau0wI";
var GCM_ENDPOINT = 'https://fcm.googleapis.com/fcm/send';
const legacy = 'AIzaSyDGF8t125bJ4wBvYn_UdRewkTxHGr7KpH8';
const applicationServerPublicKey = 'AAAA-8MWvk0APA91bHmU8XL-rzOn9SPbpG98NSqAJcuhYBBh7oze_XhprBpK7Q9PPWm3PwBo6Llxby4zjhVtgvKPIaSAQGp-8RfMV10_d1GekzICrVX9oYO8pi6dOM4VTp52CCAzug6NYIa10tNddsgE2P5QowGAYcnRHxLkrHXsw';
function urlB64ToUint8Array(base64String) {
const padding = '='.repeat((4 - base64String.length % 4) % 4);
const base64 = (base64String + padding)
.replace(/\-/g, '+')
.replace(/_/g, '/');
console.log(base64);
const rawData = window.atob(base64);
console.log(rawData);
const outputArray = new Uint8Array(rawData.length);
for (let i = 0; i < rawData.length; ++i) {
outputArray[i] = rawData.charCodeAt(i);
}
return outputArray;
}
function endpointWorkaround(pushSubscription) {
// Make sure we only mess with GCM
if(pushSubscription.endpoint.indexOf('https://fcm.googleapis.com/fcm/send') !== 0) {
return pushSubscription.endpoint;
}
var mergedEndpoint = pushSubscription.endpoint;
// Chrome 42 + 43 will not have the subscriptionId attached
// to the endpoint.
if (pushSubscription.subscriptionId &&
pushSubscription.endpoint.indexOf(pushSubscription.subscriptionId) === -1) {
// Handle version 42 where you have separate subId and Endpoint
mergedEndpoint = pushSubscription.endpoint + '/' +
pushSubscription.subscriptionId;
}
return mergedEndpoint;
}
function sendSubscriptionToServer(subscription) {
// TODO: Send the subscription.endpoint
// to your server and save it to send a
// push message at a later date
//
// For compatibly of Chrome 43, get the endpoint via
// endpointWorkaround(subscription)
console.log('TODO: Implement sendSubscriptionToServer()', JSON.stringify(subscription));
var mergedEndpoint = endpointWorkaround(subscription);
// This is just for demo purposes / an easy to test by
// generating the appropriate cURL command
var temp = showCurlCommand(mergedEndpoint);
return temp;
}
// NOTE: This code is only suitable for GCM endpoints,
// When another browser has a working version, alter
// this to send a PUSH request directly to the endpoint
function showCurlCommand(mergedEndpoint) {
// The curl command to trigger a push message straight from GCM
if (mergedEndpoint.indexOf(GCM_ENDPOINT) !== 0) {
console.warn('This browser isn\'t currently ' + 'supported for this demo');
return;
}
var endpointSections = mergedEndpoint.split('/');
var subscriptionId = endpointSections[endpointSections.length - 1];
var curlCommand = 'curl --header "Authorization: key=' + API_KEY + '" --header Content-Type:"application/json" ' + GCM_ENDPOINT + ' -d "{\\"registration_ids\\":[\\"' + subscriptionId + '\\"]}"';
console.log(curlCommand);
return subscriptionId;
}
function initialiseState() {
// Are Notifications supported in the service worker?
if (!('showNotification' in ServiceWorkerRegistration.prototype)) {
console.warn('Notifications aren\'t supported.');
return;
}
// Check the current Notification permission.
// If its denied, it's a permanent block until the
// user changes the permission
if (Notification.permission === 'denied') {
console.warn('The user has blocked notifications.');
return;
}
// Check if push messaging is supported
if (!('PushManager' in window)) {
console.warn('Push messaging isn\'t supported.');
return;
}
var prom = new Promise(function(resolve, reject) {
navigator.serviceWorker.ready.then(function(serviceWorkerRegistration) {
// Do we already have a push message subscription?
serviceWorkerRegistration.pushManager.getSubscription().then(function(subscription) {
// Enable any UI which subscribes / unsubscribes from
// push messages.
// var pushButton = document.querySelector('.js-push-button');
// pushButton.disabled = false;
if (!subscription) {
// We aren’t subscribed to push, so set UI
// to allow the user to enable push
subscribe();
return;
}
// Keep your server in sync with the latest subscription
var temp = sendSubscriptionToServer(subscription);
if(temp){
resolve(temp);
}else{
reject("Oops!")
}
// Set your UI to show they have subscribed for
// push messages
// pushButton.textContent = 'Disable Push Messages';
// isPushEnabled = true;
})
.catch(function(err) {
console.error('Error during getSubscription()', err);
reject(err);
});
});
});
return prom;
}
function unsubscribe() {
// var pushButton = document.querySelector('.js-push-button');
// pushButton.disabled = true;
navigator.serviceWorker.ready.then(function(serviceWorkerRegistration) {
// To unsubscribe from push messaging, you need get the
// subcription object, which you can call unsubscribe() on.
serviceWorkerRegistration.pushManager.getSubscription().then(
function(pushSubscription) {
// Check we have a subscription to unsubscribe
if (!pushSubscription) {
// No subscription object, so set the state
// to allow the user to subscribe to push
// isPushEnabled = false;
// pushButton.disabled = false;
// pushButton.textContent = 'Enable Push Messages';
return;
}
// TODO: Make a request to your server to remove
// the users data from your data store so you
// don't attempt to send them push messages anymore
// We have a subcription, so call unsubscribe on it
pushSubscription.unsubscribe().then(function() {
// pushButton.disabled = false;
// pushButton.textContent = 'Enable Push Messages';
// isPushEnabled = false;
}).catch(function(e) {
// We failed to unsubscribe, this can lead to
// an unusual state, so may be best to remove
// the subscription id from your data store and
// inform the user that you disabled push
console.log('Unsubscription error: ', e);
// pushButton.disabled = false;
});
}).catch(function(e) {
console.error('Error thrown while unsubscribing from ' + 'push messaging.', e);
});
});
}
function subscribe() {
// Disable the button so it can't be changed while
// we process the permission request
// var pushButton = document.querySelector('.js-push-button');
// pushButton.disabled = true;
navigator.serviceWorker.ready.then(function(serviceWorkerRegistration) {
const applicationServerKey = urlB64ToUint8Array(applicationServerPublicKey);
serviceWorkerRegistration.pushManager.subscribe({userVisibleOnly: true, applicationServerKey: applicationServerKey})
.then(function(subscription) {
console.log(subscription);
// The subscription was successful
// isPushEnabled = true;
// pushButton.textContent = 'Disable Push Messages';
// pushButton.disabled = false;
// TODO: Send the subscription subscription.endpoint
// to your server and save it to send a push message
// at a later date
return sendSubscriptionToServer(subscription);
})
.catch(function(e) {
if (Notification.permission === 'denied') {
// The user denied the notification permission which
// means we failed to subscribe and the user will need
// to manually change the notification permission to
// subscribe to push messages
console.log('Permission for Notifications was denied');
// pushButton.disabled = true;
} else {
// A problem occurred with the subscription, this can
// often be down to an issue or lack of the gcm_sender_id
// and / or gcm_user_visible_only
console.log('Unable to subscribe to push.', e);
// pushButton.disabled = false;
// pushButton.textContent = 'Enable Push Messages';
}
});
});
}
To generate a private key file for your service account:In the Firebase console, open Settings > Service Accounts. Click Generate New Private Key, then confirm by clicking Generate Key. Securely store the JSON file containing the key.
What is a Firebase Server Key? A Firebase Server Key and Firebase Sender ID are required in order to send push notifications to Android mobile app devices. The goal of this section is to provision your Firebase Server Key and Firebase Sender ID for use in OneSignal.
This is sadly a confusing thing with Chrome.
At the most basic level: Web Push is completely seperate from Firebase Messaging for the web.
Web push requires an application server key, this is what you pass into the subscribe call on a service worker push manager:
pushManager.subscribe({userVisibleOnly: true, applicationServerKey: MY_KEY});
In web push, the applicationServerKey
needs to be a Uint8Array (i.e. an array of 65 bytes). This key can be generated anyway you like, just make sure you keep the private key private and use the public key in your web app.
In the codelab I wrote, I instructed that you get your key from: https://web-push-codelab.appspot.com/
This page generates a set of application server keys on the fly and will store the result in local storage (So you can use the same page to send push messages - which need that application server key).
You can just as easily get your key from tools like web-push's node CLI.
The Firebase Messaging SDK for the web uses service workers to implement push on the web to, but it manages the application server keys for you. The reason for this, is that Firebase Messaging SDK sets you up to use the Firebase Cloud Message API to trigger push messages, instead of the Web Push Protocol that you'd need to use in the codelab you were working through.
The "Server Key" in the Firebase Console, is the key that you'd use when triggering a push message, it's the "Authorization" header.
https://fcm.googleapis.com/fcm/send
Content-Type: application/json
Authorization: key=<YOUR SERVER KEY HERE>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With