Mojolicious-Plugin-Fondation-Auth-Token
view release on metacpan or search on metacpan
lib/Mojolicious/Plugin/Fondation/Auth/Token.pm view on Meta::CPAN
package Mojolicious::Plugin::Fondation::Auth::Token;
$Mojolicious::Plugin::Fondation::Auth::Token::VERSION = '0.03';
# ABSTRACT: Personal Access Token authentication for Fondation
use Mojo::Base 'Mojolicious::Plugin', -signatures;
use Digest::SHA qw(sha256_hex);
use Crypt::URandom qw(urandom);
use Future;
sub fondation_meta {
return {
dependencies => [
'Fondation::Model::DBIx::Async',
'Fondation::Auth',
'Fondation::Problem',
],
defaults => {
models => {
api_token => {
source => 'ApiToken',
backend => undef,
},
},
},
};
}
sub register ($self, $app, $config) {
# ââ around_dispatch: validate Bearer, set current_user, flag stash ââ
$app->hook(around_dispatch => sub ($next, $c) {
my $token = _extract_bearer($c) or return $next->();
my $hash = sha256_hex($token);
$c->model('api_token')->search(
{ token_hash => $hash },
{ rows => 1 },
)->first->then(sub ($api_token) {
unless ($api_token) {
$c->stash('fondation.bearer_invalid' => 1);
return $next->();
}
my $user_id = $api_token->user_id;
return $c->model('user')->find($user_id)->then(sub ($user) {
unless ($user) {
$app->log->error(
"[Auth::Token] User $user_id not found for valid token");
$c->stash('fondation.bearer_invalid' => 1);
return $next->();
}
$c->current_user({ $user->get_columns });
$c->stash('fondation._bearer_auth' => 1);
return $api_token->update(
{ last_used_at => \'datetime(\'now\')' }
)->then(sub {
_load_grants($c);
})->then(sub { $next->() });
});
})->on_fail(sub ($err) {
$app->log->error("[Auth::Token] Token lookup failed: $err");
$c->stash('fondation.bearer_invalid' => 1);
$next->();
})->retain;
});
# ââ around_action: enforce Bearer opt-in ââââââââââââââââââââââââââ
# ââ Route is matched, check endpoint requires ââââââââââââââââââââ
$app->hook(around_action => sub ($next, $c, $action, $captures) {
return $next->() unless $c->stash('fondation._bearer_auth');
my $endpoint = $c->match->endpoint;
my $allows = 0;
if ($endpoint) {
my $requires = $endpoint->{requires} // [];
my %conds;
for (my $i = 0; $i < @$requires; $i += 2) {
$conds{$requires->[$i]} = $requires->[$i+1] // 1;
}
$allows = 1 if $conds{'fondation.bearer'};
}
unless ($allows) {
delete $c->stash->{'current_user'};
$c->problem(
( run in 0.307 second using v1.01-cache-2.11-cpan-ad19def0cd9 )