Acme-JWT
view release on metacpan or search on metacpan
lib/Acme/JWT.pm view on Meta::CPAN
package Acme::JWT;
use strict;
use warnings;
our $VERSION = '0.04';
use JSON qw/decode_json encode_json/;
use MIME::Base64 qw/encode_base64url decode_base64url/;
use Try::Tiny;
use Digest::SHA qw/hmac_sha256 hmac_sha384 hmac_sha512/;
use Crypt::OpenSSL::RSA;
our $has_sha2;
BEGIN {
$has_sha2 = 0;
if (UNIVERSAL::can('Crypt::OpenSSL::RSA', 'use_sha512_hash')) {
$has_sha2 = 1;
}
}
sub encode {
my $self = shift;
my ($payload, $key, $algorithm) = @_;
unless (defined($algorithm)) {
$algorithm = 'HS256';
}
unless ($algorithm) {
$algorithm = 'none';
}
my $segments = [];
my $header = {
typ => 'JWT',
alg => $algorithm,
};
push(@$segments, encode_base64url(encode_json($header)));
push(@$segments, encode_base64url(encode_json($payload)));
my $signing_input = join('.', @$segments);
unless ($algorithm eq 'none') {
my $signature = $self->sign($algorithm, $key, $signing_input);
push(@$segments, encode_base64url($signature));
} else {
push(@$segments, '');
}
return join('.', @$segments);
}
sub decode {
my $self = shift;
my ($jwt, $key, $verify) = @_;
unless (defined($verify)) {
$verify = 1;
}
my $segments = [split(/\./, $jwt)];
die 'Not enough or to many segments' unless (@$segments == 2 or @$segments == 3);
my ($header_segment, $payload_segment, $crypt_segment) = @$segments;
my $signing_input = join('.', $header_segment, $payload_segment);
my $header;
my $payload;
my $signature;
try {
$header = decode_json(decode_base64url($header_segment));
$payload = decode_json(decode_base64url($payload_segment));
$signature = decode_base64url($crypt_segment) if ($verify);
} catch {
warn $_;
};
if ($verify) {
my $algo = $header->{alg};
my $hmac = sub {
( run in 0.743 second using v1.01-cache-2.11-cpan-cdf2f3d4e48 )