HTTP-Request-Webpush
view release on metacpan or search on metacpan
examples/send.pl view on Meta::CPAN
use warnings;
use HTTP::Request::Webpush;
use LWP::UserAgent;
my $server_key = { public => 'BCAI00zPAbxEVU5w8D1kZXVs2Ro--FmpQNMOd0S0w1_5naTLZTGTYNqIt7d97c2mUDstAWOCXkNKecqgS4jARA8',
private => 'M6xy5prDBhJNlOGnOkMekyAQnQSWKuJj1cD06SUQTow'};
my $send=HTTP::Request::Webpush->new();
$send->subscription('{"endpoint":"https://bn3p.notify.windows.com/w/?token=BQYAAACgmmGJB%2fT6GgtS%2bZsefznjZgOG1kd2d05B80MIiQ%2fn5JKOOjrE7Bep8JYJoqRiAW67%2fyoq69DRfLFaZHxhBiYbWh6HfdUd0SbAAwe6%2fvk0ClM0a4%2bEfX0fzUflmVix%2fV8uM1lFqVidtOLLs20lnWw%2bH5N...
$send->subject('mailto:esf@moller.cl');
$send->authbase64($server_key->{public}, $server_key->{private});
$send->content("Billy Jean's not my lover");
$send->encode;
$send->header('TTL' => '90');
my $ua = LWP::UserAgent->new;
my $response = $ua->request($send);
print $response->code();
lib/HTTP/Request/Webpush.pm view on Meta::CPAN
my $agent;
if (ref $subscription eq 'HASH') {
$agent=$subscription;
} else {
eval {$agent=from_json($subscription); };
}
croak "Can't process subscription object" unless ($agent);
croak "Subscription must include endpoint" unless (exists $agent->{endpoint});
$self->uri($agent->{endpoint});
$self->{subscription}=$agent;
return $agent;
}
sub auth($@) {
my $self=shift();
if (scalar @_ == 2) {
$self->{'app-pub'}=shift();
lib/HTTP/Request/Webpush.pm view on Meta::CPAN
#This method is inherited from HTTP::Message, but here only aes128gcm applies
croak 'Only aes128gcm encoding available' unless ($enc eq 'aes128gcm');
#Check prerequisites
croak 'Endpoint must be present for message encoding' unless ($self->url());
croak 'Authentication keys must be present for message encoding' unless ($self->{'app-key'});
croak 'UA auth params must be present for message encoding' unless ($self->{subscription}->{'keys'}->{'p256dh'} && $self->{subscription}->{'keys'}->{'auth'});
croak 'Message payload must be 3992 bytes or less' unless (length($self->content) <= 3992);
#This is the JWT part
my $origin=URI->new($self->{subscription}->{endpoint});
$origin->path_query('');
my $data={
'aud' => "$origin",
'exp'=> time() + 86400
};
$data->{'sub'}=$self->{'subject'} if ($self->{'subject'});
my $appk = Crypt::PK::ECC->new();
$appk->import_key_raw($self->{'app-key'},'secp256r1');
my $token = encode_jwt(payload => $data, key => $appk , alg=>'ES256');
lib/HTTP/Request/Webpush.pm view on Meta::CPAN
if ($self->{'ecc'}) {
$pk=$self->{'ecc'};
} else {
$pk=Crypt::PK::ECC->new();
$pk->generate_key('prime256v1');
}
my $pub_signkey=$pk->export_key_raw('public');
my $sec_signkey=$pk->export_key_raw('private');
my $sk=Crypt::PK::ECC->new(); #This will be the UA endpoint key, which we know from the subscription object
#The p256dh key is given to us in X9.62 format. Crypt::PK::ECC should be able
#to read it as a "raw" format. But it's important to apply the base64url variant
my $ua_public=decode_base64url($self->{subscription}->{'keys'}->{'p256dh'});
$sk->import_key_raw($ua_public, 'secp256r1');
my $ecdh_secret=$pk->shared_secret($sk);
my $auth_secret= decode_base64url($self->{subscription}->{'keys'}->{'auth'});
#An earlier draft established this header string as Content-Encoding: auth
lib/HTTP/Request/Webpush.pm view on Meta::CPAN
=head1 SYNOPSIS
use HTTP::Request::Webpush;
#This should be the application-wide VAPID key pair
#The APP_PUB part must be the same used by the user UA when requesting the subscription
use constant APP_PUB => 'BCAI...RA8';
use constant APP_KEY => 'M6x...UQTow';
#This should be previously collected from an already subscribed user UA
my $subscription='{"endpoint":"https://foo/fooer","expirationTime":null,"keys":{"p256dh":"BCNS...","auth":"dZ..."}}';
my $message=HTTP::Request::Webpush->new();
$message->auth(APP_PUB, APP_KEY);
$message->subscription($subscription);
$message->subject('mailto:bobsbeverage@some.com');
$message->content('Hello world');
#Additional headers can be applied with inherited HTTP::Response methods
$message->header('TTL' => '90');
lib/HTTP/Request/Webpush.pm view on Meta::CPAN
=over 4
=item C<$r=HTTP::Request::Webpush-E<gt>new()>
=item C<$r=HTTP::Request::Webpush-E<gt>new(auth =E<gt> $my_key, subscription =E<gt> $my_subs, content='New lager batch arrived')>
The following options can be supplied in the constructor: subscription, auth, reuseecc, subject, content.
=item C<$r-E<gt>subscription($hash_reference)>
=item C<$r-E<gt>subscription('{"endpoint":"https://foo/fooer","expirationTime":null,"keys":{"p256dh":"BCNS...","auth":"dZ..."}}');>
This sets the subscription object related to this notification service. This should be the same object
returned inside the browser environment using the browser's Push API C<PushManager.subscribe()> method. The argument can
be either a JSON string or a previously setup hash reference. The HTTP::Request uri is taken verbatim from the endpoint
of the subscription object.
=item C<$r-E<gt>auth($pk) #pk being a Crypt::PK::ECC ref>
=item C<$r-E<gt>auth($pub_bin, $priv_bin)>
=item C<$r-E<gt>authbase64('BCAI...jARA8','M6...Tow')>
This sets the authentication key for the VAPID authentication scheme related to this push service.
This can either be a (public, private) pair or an already setup L<Crypt::PK::ECC> object. The public part
t/http-request-webpush-long.t view on Meta::CPAN
my $infoHmac= hmac_sha256($info,chr(1),$key);
return substr($infoHmac,0,$len);
}
#Basic stuff
BEGIN { use_ok('HTTP::Request::Webpush') };
my $send=new_ok( 'HTTP::Request::Webpush' );
#Now setup a dummy subscription endpoint
my $ua_publicKey= "BMj40clWPSKfZTdyaQQjFoEozKUXI3aEZDBFC_2dr0I5ZWX7bvahx3iDRJjbXf6t9FuSuuAq57cEb_R48lmVzPA";
my $ua_privateKey= "ibx1ebRZyWiWNB_fHXHmiLROYXDXD_II8EZ1nqef4VA";
my $auth=random_bytes(16);
my $app_publicKey= "BDIlKk-A0gBOnZ9DWHoEzSFe_HZbDEAY6yYgN6ILmdVC3mS8laszyLPI6FJhVXZpsJPSYlBkAyYrKRVBdD9fydY";
my $app_privateKey= "cLERT3eZx0JfS0pIX6orz_uGBzf1JV0I7PWGCaGfkbg";
my $service={"endpoint"=>"https://foo",
"expirationTime" => 0,
"keys"=> {
"p256dh"=>$ua_publicKey,
"auth"=> encode_base64url($auth)}};
ok($send->subscription($service) );
ok($send->authbase64($ua_publicKey,$ua_privateKey));
my $payload= <<'EOP';
t/http-request-webpush-reuse.t view on Meta::CPAN
my $infoHmac= hmac_sha256($info,chr(1),$key);
return substr($infoHmac,0,$len);
}
#Basic stuff
BEGIN { use_ok('HTTP::Request::Webpush') };
my $send=new_ok( 'HTTP::Request::Webpush' );
#Now setup a dummy subscription endpoint
my $ua_publicKey= "BMj40clWPSKfZTdyaQQjFoEozKUXI3aEZDBFC_2dr0I5ZWX7bvahx3iDRJjbXf6t9FuSuuAq57cEb_R48lmVzPA";
my $ua_privateKey= "ibx1ebRZyWiWNB_fHXHmiLROYXDXD_II8EZ1nqef4VA";
my $auth=random_bytes(16);
my $app_publicKey= "BDIlKk-A0gBOnZ9DWHoEzSFe_HZbDEAY6yYgN6ILmdVC3mS8laszyLPI6FJhVXZpsJPSYlBkAyYrKRVBdD9fydY";
my $app_privateKey= "cLERT3eZx0JfS0pIX6orz_uGBzf1JV0I7PWGCaGfkbg";
my $service={"endpoint"=>"https://foo",
"expirationTime" => 0,
"keys"=> {
"p256dh"=>$ua_publicKey,
"auth"=> encode_base64url($auth)}};
ok($send->subscription($service) );
ok($send->authbase64($ua_publicKey,$ua_privateKey));
my $reuse=Crypt::PK::ECC->new(); #For encryption
$reuse->generate_key('prime256v1');
t/http-request-webpush.t view on Meta::CPAN
my $infoHmac= hmac_sha256($info,chr(1),$key);
return substr($infoHmac,0,$len);
}
#Basic stuff
BEGIN { use_ok('HTTP::Request::Webpush') };
my $send=new_ok( 'HTTP::Request::Webpush' );
#Now setup a dummy subscription endpoint
my $ua_publicKey= "BMj40clWPSKfZTdyaQQjFoEozKUXI3aEZDBFC_2dr0I5ZWX7bvahx3iDRJjbXf6t9FuSuuAq57cEb_R48lmVzPA";
my $ua_privateKey= "ibx1ebRZyWiWNB_fHXHmiLROYXDXD_II8EZ1nqef4VA";
my $auth=random_bytes(16);
my $app_publicKey= "BDIlKk-A0gBOnZ9DWHoEzSFe_HZbDEAY6yYgN6ILmdVC3mS8laszyLPI6FJhVXZpsJPSYlBkAyYrKRVBdD9fydY";
my $app_privateKey= "cLERT3eZx0JfS0pIX6orz_uGBzf1JV0I7PWGCaGfkbg";
my $service={"endpoint"=>ENDPOINT,
"expirationTime" => 0,
"keys"=> {
"p256dh"=>$ua_publicKey,
"auth"=> encode_base64url($auth)}};
ok($send->subscription($service) , 'Can accept subscription data');
ok($send->authbase64($ua_publicKey,$ua_privateKey), 'Can accept auth data');
my $payload="Hello world";
$send->content($payload);
( run in 1.527 second using v1.01-cache-2.11-cpan-2b1a40005be )