Akamai-Open-Client
view release on metacpan or search on metacpan
lib/Akamai/Open/Request/EdgeGridV1.pm view on Meta::CPAN
package Akamai::Open::Request::EdgeGridV1;
BEGIN {
$Akamai::Open::Request::EdgeGridV1::AUTHORITY = 'cpan:PROBST';
}
# ABSTRACT: Creates the signed authentication header for the Akamai Open API Perl clients
$Akamai::Open::Request::EdgeGridV1::VERSION = '0.03';
use strict;
use warnings;
use Moose;
use Digest::SHA qw(sha256 hmac_sha256 hmac_sha256_base64);
use MIME::Base64;
use URL::Encode qw/:all/;
use URI;
use constant {
EDGEGRIDV1ALGO => 'EG1-HMAC-SHA256',
HEADER_NAME => 'Authorization',
CLIENT_TOKEN => 'client_token=',
ACCESS_TOKEN => 'access_token=',
TIMESTAMP_TOKEN => 'timestamp=',
NONCE_TOKEN => 'nonce=',
SIGNATURE_TOKEN => 'signature='
};
extends 'Akamai::Open::Request';
has 'client' => (is => 'rw', trigger => \&Akamai::Open::Debug::debugger);
has 'signed_headers' => (is => 'rw', trigger => \&Akamai::Open::Debug::debugger);
has 'signature' => (is => 'rw', trigger => \&Akamai::Open::Debug::debugger);
has 'signing_key' => (is => 'rw', isa => 'Str', trigger => \&Akamai::Open::Debug::debugger);
before 'sign_request' => sub {
my $self = shift;
my $tmp_key;
$self->debug->logger->debug(sprintf('Calculating signing key from %s and %s', $self->timestamp(),$self->client->client_secret()));
$tmp_key = encode_base64(hmac_sha256($self->timestamp(),$self->client->client_secret()));
chomp($tmp_key);
$self->signing_key($tmp_key);
return;
};
after 'sign_request' => sub {
my $self = shift;
if(defined($self->signature)) {
my $header_name = HEADER_NAME;
my $auth_header = sprintf('%s %s', EDGEGRIDV1ALGO,
join(';', CLIENT_TOKEN . $self->client->client_token(),
ACCESS_TOKEN . $self->client->access_token(),
TIMESTAMP_TOKEN . $self->timestamp(),
NONCE_TOKEN . $self->nonce(),
SIGNATURE_TOKEN . $self->signature()));
$self->debug->logger->debug("Setting Authorization header to $auth_header");
$self->request->header($header_name => $auth_header);
}
if(defined($self->signed_headers)) {
my $headers = $self->signed_headers;
$self->request->header($_ => $headers->{$_}) foreach(keys(%{$headers}));
}
};
sub sign_request {
my $self = shift;
# to create a valid auth header, we'll need
# the http request method (i.e. GET, POST, PUT)
my $http_method = $self->request->method;
# the http scheme in lowercases (i.e. http or https)
my $http_scheme = $self->request->uri->scheme;
# the http host header
my $http_host = $self->request->uri->host;
# the encoded uri including the query string if present
my $http_uri = $self->request->uri->path_query;
# the canonicalized headers which are choosed for signing
my $http_headers = $self->canonicalize_headers;
# the content hash for POST/PUT requests
my $content_hash = $self->content_hash;
# and the authorization header content
my $auth_header = sprintf('%s %s;', EDGEGRIDV1ALGO,
join(';', CLIENT_TOKEN . $self->client->client_token,
ACCESS_TOKEN . $self->client->access_token,
TIMESTAMP_TOKEN . $self->timestamp,
NONCE_TOKEN . $self->nonce));
# now create the token to sign
my $token = join("\t", $http_method, $http_scheme, $http_host, $http_uri, $http_headers, $content_hash, $auth_header);
$self->debug->logger->info("Signing token is $token");
if($self->debug->logger->is_debug()) {
my $dbg = $token;
$dbg =~ s#\t#\\t#g;
$self->debug->logger->debug("Quoted sigining token is $dbg");
}
# and sign the token
$self->debug->logger->info(sprintf('signing with key %s', $self->signing_key()));
my $tmp_stoken = encode_base64(hmac_sha256($token, $self->signing_key()));
chomp($tmp_stoken);
$self->signature($tmp_stoken);
return;
}
sub content_hash {
my $self = shift;
my $content_hash = '';
if($self->request->method eq 'POST' && length($self->request->content) > 0) {
$content_hash = encode_base64(sha256($self->request->content));
chomp($content_hash);
}
return($content_hash);
}
sub canonicalize_headers {
my $self = shift;
my $sign_headers = $self->signed_headers || {};
return(join("\t", map {
my $header = lc($_);
my $value = $sign_headers->{$_};
# trim leading and trailing whitespaces
$value =~ s{^\s+}{};
$value =~ s{\s$}{};
# replace repeated whitespaces
$value =~ s/\s{2,}/ /g;
"$header:$value";
} sort(keys(%{$sign_headers}))));
}
1;
__END__
=pod
=encoding utf-8
=head1 NAME
Akamai::Open::Request::EdgeGridV1 - Creates the signed authentication header for the Akamai Open API Perl clients
=head1 VERSION
version 0.03
=head1 ABOUT
I<Akamai::Open::Request::EdgeGridV1> provides the signing functionality,
which is needed to authenticated the client against the I<Akamai::Open>
API.
The algorithm to sign a header for a request against the API, is
provided and described by Akamai and can be found L<here|https://developer.akamai.com/stuff/Getting_Started_with_OPEN_APIs/Client_Auth.html>.
( run in 1.802 second using v1.01-cache-2.11-cpan-39bf76dae61 )