Dancer2-Plugin-JWT
view release on metacpan or search on metacpan
lib/Dancer2/Plugin/JWT.pm view on Meta::CPAN
if ( exists $config->{need_nbf} && defined $config->{need_nbf} ) {
$need_nbf = $config->{need_nbf};
}
if ( exists $config->{need_exp} && defined $config->{need_exp} ) {
$need_exp = $config->{need_exp};
}
if ( exists $config->{need_leeway} && defined $config->{need_leeway} ) {
$need_leeway = $config->{need_leeway};
}
$dsl->app->add_hook(
Dancer2::Core::Hook->new(
name => 'before_template_render',
code => sub {
my $tokens = shift;
$tokens->{jwt} = $dsl->app->request->var('jwt');
}
)
);
$dsl->app->add_hook(
Dancer2::Core::Hook->new(
name => 'after',
code => sub {
if ($expose_authorization_header) {
my $response = shift;
$response = $response->isa('Dancer2::Core::Response') ? $response : $response->response;
$response->push_header('Access-Control-Expose-Headers' => 'Authorization');
}
}
)
);
$dsl->app->add_hook(
Dancer2::Core::Hook->new(
name => 'before',
code => sub {
my $app = shift;
my $encoded = $app->request->headers->authorization;
if( defined $encoded ) {
# Remove "Bearer " (sic) from the beginning of the Authorization header if present.
# "Bearer" signifies the schema and should be present
# but due to backwards compatibility we support also without it.
# https://jwt.io/introduction/ (How do JSON Web Tokens work?)
$encoded =~ m/^ (?: Bearer [[:space:]]{1} | ) (?<token> [^[:space:]]{0,} ) $/msx;
$encoded = $+{token};
}
if ($set_cookie_header && $app->request->cookies->{_jwt}) {
$encoded = $app->request->cookies->{_jwt}->value ;
}
elsif ($app->request->param('_jwt')) {
$encoded = $app->request->param('_jwt');
}
if ($encoded) {
my $decoded;
eval {
$decoded = decode_jwt( token => $encoded,
key => $secret,
verify_iat => $need_iat,
verify_nbf => $need_nbf,
verify_exp => defined $need_exp ? 1 : 0 ,
leeway => $need_leeway,
accepted_alg => $alg,
accepted_enc => $enc );
};
if ($@) {
$app->execute_hook('plugin.jwt.jwt_exception' => ($a = $@)); # this is weird, but required!
};
$app->request->var('jwt', $decoded);
$app->request->var('jwt_status' => 'present');
}
else {
## no token
$app->request->var('jwt_status' => 'missing');
}
}
)
);
$dsl->app->add_hook(
Dancer2::Core::Hook->new(
name => 'after',
code => sub {
my $response = shift;
my $decoded = $dsl->app->request->var('jwt');
if($set_authorization_header || $set_cookie_header || $set_location_header) {
# If all are disabled, then skip also encoding!
if (defined($decoded)) {
my $encoded = encode_jwt( payload => $decoded,
key => $secret,
alg => $alg,
enc => $enc,
auto_iat => $need_iat,
relative_exp => $need_exp,
relative_nbf => $need_nbf );
if($set_authorization_header) {
$response->headers->authorization($encoded);
}
if($set_cookie_header) {
my %cookie = (
value => $encoded,
name => '_jwt',
expires => time + ($need_exp // $fourWeeks),
path => '/',
http_only => 0);
$cookie{domain} = $cookie_domain if defined $cookie_domain;
$response->push_header('Set-Cookie'
=> Dancer2::Core::Cookie->new(%cookie)->to_header());
}
if ($set_location_header && $response->status =~ /^3/) {
my $u = URI->new( $response->header('Location') );
$u->query_param( _jwt => $encoded);
$response->header(Location => $u);
}
}
} # ! $set_authorization_header && ! $set_cookie_header && ! $set_location_header
}
)
);
};
register_plugin;
1;
=encoding UTF-8
=head1 NAME
Dancer2::Plugin::JWT - JSON Web Token made simple for Dancer2
=head1 SYNOPSIS
use Dancer2;
use Dancer2::Plugin::JWT;
post '/login' => sub {
if (is_valid(param("username"), param("password"))) {
jwt { username => param("username") };
template 'index';
}
else {
redirect '/';
}
( run in 0.684 second using v1.01-cache-2.11-cpan-c966e8aa7e8 )