NAME
VAPID - Voluntary Application Server Identification
VERSION
Version 1.01
SYNOPSIS
my
(
$public
,
$private
) = generate_vapid_keys()
validate_public_key(
$public
);
validate_private_key(
$private
);
...
my
$auth_headers
= generate_vapid_header(
'mailto:email@lnation.org'
,
$public
,
$private
,
time
+ 60,
$enc
);
DESCRIPTION
VAPID, which stands for Voluntary Application Server Identity, is a new way to send and receive website push notifications. Your VAPID keys allow you to send web push campaigns without having to send them through a service like Firebase Cloud Messaging (or FCM). Instead, the application server can voluntarily identify itself to your web push provider.
EXPORT
generate_vapid_keys
Generates vapid private and public keys.
generate_vapid_header
Generates the Authorization and Crypto-Key headers that should be passed when making a request to push a notification.
generate_future_expiration_timestamp
Generates a time that is in future based upon the number of seconds if passed, the default is 12 hours.
validate_subject
Validate the subject.
validate_public_key
Validate the public key.
validate_private_key
Validate the private key.
validate_expiration
Validate the expiration key.
Example
The following is pseudo code but it should get you started.
STEP 1 - generate private and public keys
my
(
$public
,
$private
) = generate_vapid_keys()
$c
->stash({
VAPID_USER_PUBLIC_KEY
=>
$public
});
STEP 2 - main.js
var publicKey = [% VAPID_USER_PUBLIC_KEY %];
navigator.serviceWorker.getRegistrations().then(function (registrations) {
navigator.serviceWorker.register(
'/service-worker.js'
).then(function (worker) {
console.
log
(
'Service Worker Registered'
);
worker.pushManager.getSubscription().then(function(
sub
) {
if
(
sub
=== null) {
// Update UI to ask user to register
for
Push
subscribeUser();
console.
log
(
'Not subscribed to push service!'
);
}
else
{
// We have a subscription, update the database
console.
log
(
'Subscription object: '
,
sub
);
}
});
});
});
function subscribeUser() {
if
(
'serviceWorker'
in navigator) {
navigator.serviceWorker.ready.then(function(reg) {
reg.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: publicKey
}).then(function(
sub
) {
// We have a subscription, update the database
console.
log
(
'Endpoint URL: '
,
sub
.endpoint);
}).
catch
(function(e) {
if
(Notification.permission ===
'denied'
) {
console.
warn
(
'Permission for notifications was denied'
);
}
else
{
console.error(
'Unable to subscribe to push'
, e);
}
});
})
}
}
STEP 3 - service-worker.js
self.addEventListener(
'push'
, function(e) {
var body;
if
(e.data) {
body = e.data.text();
}
else
{
body =
'Push message no payload'
;
}
var options = {
body: body,
icon:
'images/notification-flat.png'
,
vibrate: [100, 50, 100],
data: {
dateOfArrival: Date.now(),
primaryKey: 1
},
};
e.waitUntil(
self.registration.showNotification(
'Push Notification'
, options)
);
});
STEP 4 - manifest.json
Required for Chrome; Firefox works even without this file:
{
"short_name"
:
"Push"
,
"name"
:
"Push Dashboard"
,
"icons"
: [
{
"src"
:
"/icon-144x144.png"
,
"type"
:
"image/png"
,
"sizes"
:
"144x144"
}
],
"display"
:
"standalone"
,
"start_url"
:
"/"
,
"background_color"
:
"#fff"
,
"theme_color"
:
"#fff"
,
"scope"
:
"/"
}
STEP 5 - generate headers
my
$notificaiton_host
= URI->new(
$subscription_url
)->host;
my
$auth_headers
= generate_vapid_header(
'mailto:email@lnation.org'
,
$public
,
$private
,
time
+ 60
);
STEP 6 - POST the push message
Curl from the command line:
curl
"{SUBSCRIPTION_URL}"
--request POST --header
"TTL: 60"
--header
"Content-Length: 0"
--header
"Authorization: {AUTHORIZATION_HEADER}"
--header
"Crypto-Key: {CRYPTO_KEY_HEADER}"
or Perl with LWP:
use
LWP::UserAgent;
my
$req
= HTTP::Request->new(
POST
=>
$subscription_url
);
$req
->header(
TTL
=> 60);
$req
->header(
'Authorization'
=>
$auth_headers
->{Authorization});
$req
->header(
'Crypto-Key'
=>
$auth_headers
->{
'Crypto-Key'
});
my
$ua
= LWP::UserAgent->new;
my
$resp
=
$ua
->request(
$req
);
if
(
$resp
->is_success) {
"Push message sent out successfully.\n"
;
}
else
{
"Push message did not get through:\n"
,
$resp
->as_string,
"\n"
;
}
AUTHOR
LNATION, <email at lnation.org>
BUGS
Please report any bugs or feature requests to bug-vapid at rt.cpan.org
, or through the web interface at https://rt.cpan.org/NoAuth/ReportBug.html?Queue=VAPID. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.
SUPPORT
You can find documentation for this module with the perldoc command.
perldoc VAPID
You can also look for information at:
RT: CPAN's request tracker (report bugs here)
CPAN Ratings
Search CPAN
ACKNOWLEDGEMENTS
LICENSE AND COPYRIGHT
This software is Copyright (c) 2020 by LNATION.
This is free software, licensed under:
The Artistic License 2.0 (GPL Compatible)