* the endpoint will receive "type" (expires|onetime)
and "expires" (positive integer representing seconds)
* type will define the expiray method for the token;
onetime: the token expires as soon as it's used, or
after "expires" seconds if not used
expires: the token can be used multiple times until
it expires according to the "expires" param value
* login_jwt endpoint for generating the JWT token for
subscribers has been enhanced to accept the "token"
param, containing the token generated using the
/api/authtokens endpoint
* admin_login_jwt endpoint for generating the JWT token
for admins has been enhanced to accept the "token"
param, containing the token generated using the
/api/authtokens endpoint
* login_jwt and amin_login_jwt will respond with 403
"Forbidden" if the token role stored in Redis does
not match the role of the user that generated it
* /api/authtokens is hidden from documentation for now
Change-Id: I4eb76c2b08f2e24774fa84ba0ccf7412ce8670e8
(cherry picked from commit 9b422ddabf
)
mr9.5.4
parent
944823b780
commit
db8f0feff6
@ -0,0 +1,74 @@
|
||||
package NGCP::Panel::Controller::API::AuthTokens;
|
||||
|
||||
use Sipwise::Base;
|
||||
|
||||
use Data::HAL qw();
|
||||
use Data::HAL::Link qw();
|
||||
use File::Basename;
|
||||
use File::Find::Rule;
|
||||
use HTTP::Headers qw();
|
||||
use HTTP::Status qw(:constants);
|
||||
|
||||
|
||||
sub allowed_methods{
|
||||
return [qw/POST OPTIONS/];
|
||||
}
|
||||
|
||||
use parent qw/NGCP::Panel::Role::Entities NGCP::Panel::Role::API::AuthTokens/;
|
||||
|
||||
sub api_description {
|
||||
return '';
|
||||
};
|
||||
|
||||
sub query_params {
|
||||
return [
|
||||
];
|
||||
}
|
||||
|
||||
sub resource_name{
|
||||
return 'authtokens';
|
||||
}
|
||||
|
||||
sub dispatch_path{
|
||||
return '/api/authtokens/';
|
||||
}
|
||||
|
||||
sub relation{
|
||||
return 'http://purl.org/sipwise/ngcp-api/#rel-authtokens';
|
||||
}
|
||||
|
||||
__PACKAGE__->set_config({
|
||||
allowed_roles => [qw/admin reseller ccare ccareadmin subscriber subscriberadmin/],
|
||||
});
|
||||
|
||||
sub POST :Allow {
|
||||
my ($self, $c) = @_;
|
||||
|
||||
my $resource = $self->get_valid_post_data(
|
||||
c => $c,
|
||||
media_type => 'application/json',
|
||||
);
|
||||
return unless $resource;
|
||||
|
||||
my $form = $self->get_form($c);
|
||||
return unless $self->validate_form(
|
||||
c => $c,
|
||||
resource => $resource,
|
||||
form => $form,
|
||||
);
|
||||
if($c->user->roles eq "reseller") {
|
||||
$resource->{reseller_id} = $c->user->reseller_id;
|
||||
}
|
||||
|
||||
my $res = {};
|
||||
|
||||
$res->{token} = $self->generate_auth_token($c, $resource);
|
||||
|
||||
$c->response->status(HTTP_CREATED);
|
||||
$c->response->body(JSON::to_json($res));
|
||||
return;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
# vim: set tabstop=4 expandtab:
|
@ -0,0 +1,29 @@
|
||||
package NGCP::Panel::Form::AuthToken;
|
||||
|
||||
use HTML::FormHandler::Moose;
|
||||
use NGCP::Panel::Utils::Form;
|
||||
extends 'HTML::FormHandler';
|
||||
|
||||
has_field 'type' => (
|
||||
type => 'Select',
|
||||
options => [
|
||||
{ label => 'Onetime', value => 'onetime' },
|
||||
{ label => 'Expires', value => 'expires' },
|
||||
],
|
||||
label => 'Type',
|
||||
required => 1,
|
||||
);
|
||||
|
||||
has_field 'expires' => (
|
||||
type => '+NGCP::Panel::Field::PosInteger',
|
||||
required => 1,
|
||||
label => 'Expires',
|
||||
);
|
||||
|
||||
has_block 'fields' => (
|
||||
tag => 'div',
|
||||
class => [qw/modal-body/],
|
||||
render_list => [qw/type expires/],
|
||||
);
|
||||
|
||||
1;
|
@ -0,0 +1,35 @@
|
||||
package NGCP::Panel::Role::API::AuthTokens;
|
||||
|
||||
use Sipwise::Base;
|
||||
use NGCP::Panel::Utils::Redis;
|
||||
|
||||
use parent 'NGCP::Panel::Role::API';
|
||||
|
||||
use Redis;
|
||||
use UUID;
|
||||
|
||||
sub get_form {
|
||||
my ($self, $c) = @_;
|
||||
return NGCP::Panel::Form::get("NGCP::Panel::Form::AuthToken", $c);
|
||||
}
|
||||
|
||||
sub generate_auth_token {
|
||||
my ($self, $c, $resource) = @_;
|
||||
|
||||
my ($uuid_bin, $uuid_string);
|
||||
UUID::generate($uuid_bin);
|
||||
UUID::unparse($uuid_bin, $uuid_string);
|
||||
#remove '-' from the token
|
||||
$uuid_string =~ s/\-//g;
|
||||
my $redis = NGCP::Panel::Utils::Redis::get_redis_connection($c, {database => $c->config->{'Plugin::Session'}->{redis_db}});
|
||||
return unless $redis;
|
||||
$redis->hset("auth_token:$uuid_string", 'type', $resource->{type});
|
||||
$redis->hset("auth_token:$uuid_string", 'role', $c->user->roles);
|
||||
$redis->hset("auth_token:$uuid_string", 'user_id', $c->user->id);
|
||||
$redis->expire("auth_token:$uuid_string", $resource->{expires});
|
||||
|
||||
return $uuid_string;
|
||||
}
|
||||
|
||||
1;
|
||||
# vim: set tabstop=4 expandtab:
|
@ -0,0 +1,23 @@
|
||||
package NGCP::Panel::Utils::Redis;
|
||||
|
||||
use warnings;
|
||||
use strict;
|
||||
|
||||
use Redis;
|
||||
|
||||
sub get_redis_connection {
|
||||
my ($c, $params) = @_;
|
||||
my $redis = Redis->new(
|
||||
server => $c->config->{redis}->{central_url},
|
||||
reconnect => 10, every => 500000, # 500ms
|
||||
cnx_timeout => 3,
|
||||
);
|
||||
unless ($redis) {
|
||||
$c->log->error("Failed to connect to central redis url " . $c->config->{redis}->{central_url});
|
||||
return;
|
||||
}
|
||||
$redis->select($params->{database});
|
||||
return $redis;
|
||||
}
|
||||
|
||||
1;
|
Loading…
Reference in new issue