GOOGLE-ADWORDS-PERL-CLIENT
view release on metacpan or search on metacpan
lib/Google/Ads/Common/OAuth2ServiceAccountsHandler.pm view on Meta::CPAN
use Google::Ads::Common::Constants; our $VERSION = ${Google::Ads::Common::Constants::VERSION};
use Crypt::OpenSSL::RSA;
use HTTP::Request;
use LWP::UserAgent;
use MIME::Base64 qw(encode_base64 decode_base64);
use utf8;
use constant OAUTH2_BASE_URL => "https://accounts.google.com/o/oauth2";
# Class::Std-style attributes. Need to be kept in the same line.
# These need to go in the same line for older Perl interpreters to understand.
my %email_address_of : ATTR(:name<email_address> :default<>);
my %delegated_email_address_of : ATTR(:name<delegated_email_address> :default<>);
my %pem_file_of : ATTR(:name<pem_file> :default<>);
my %__crypt_module_of : ATTR(:name<__crypt_module> :default<>);
# Constructor
sub START {
my ($self, $ident) = @_;
$__crypt_module_of{$ident} ||= "Crypt::OpenSSL::RSA";
}
sub initialize :CUMULATIVE(BASE FIRST) {
my ($self, $api_client, $properties) = @_;
my $ident = ident $self;
$email_address_of{$ident} = $properties->{oAuth2ServiceAccountEmailAddress} ||
$email_address_of{$ident};
$delegated_email_address_of{$ident} =
$properties->{oAuth2ServiceAccountDelegateEmailAddress} ||
$delegated_email_address_of{$ident};
$pem_file_of{$ident} = $properties->{oAuth2ServiceAccountPEMFile} ||
$pem_file_of{$ident};
}
sub _refresh_access_token {
my $self = shift;
my $iat = time;
my $exp = $iat + 3600;
my $iss = $self->get_email_address();
my $delegated_email_address = $self->get_delegated_email_address();
my $scope = $self->_scope();
my $file = $self->__read_certificate_file() || return 0;
my $header= '{"alg":"RS256","typ":"JWT"}';
my $claims = "{
\"iss\":\"${iss}\",
\"prn\":\"${delegated_email_address}\",
\"scope\":\"${scope}\",
\"aud\":\"" . OAUTH2_BASE_URL . "/token\",
\"exp\":${exp},
\"iat\":${iat}
}";
my $encoded_header = __encode_base64_url($header);
my $encoded_claims = __encode_base64_url($claims);
my $key = $self->get___crypt_module()->new_private_key($file) || return 0;
$key->use_pkcs1_padding();
$key->use_sha256_hash();
my $signature = $key->sign("${encoded_header}.${encoded_claims}");
my $encoded_signature = __encode_base64_url($signature);
my $assertion = "${encoded_header}.${encoded_claims}.${encoded_signature}";
my $body = "grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer" .
"&assertion=" . $assertion;
push my @headers, "Content-Type" => "application/x-www-form-urlencoded";
my $request = HTTP::Request->new("POST", OAUTH2_BASE_URL . "/token",
\@headers, $body);
my $user_agent = $self->get___user_agent();
my $res = $user_agent->request($request);
if (!$res->is_success()) {
warn($res->decoded_content());
return 0;
}
my $content_hash = $self->__parse_auth_response($res->decoded_content());
$self->set_access_token($content_hash->{access_token});
$self->set_access_token_expires($iat + $content_hash->{expires_in});
}
sub __read_certificate_file {
my $self = shift;
my $file_str;
$self->get_pem_file() || return 0;
open (MYFILE, $self->get_pem_file()) || return 0;
while (<MYFILE>) {
$file_str .= $_;
}
close(MYFILE);
return $file_str;
}
sub __encode_base64_url($) {
my ($s) = shift;
$s = encode_base64($s);
$s =~ tr{+/}{-_};
$s =~ s/=*$//;
$s =~ s/\n//g;
return $s;
}
sub _scope {
my $self = shift;
die "Need to be implemented by subclass";
}
sub _throw_error {
my ($self, $err_msg) = @_;
$self->get_api_client()->get_die_on_faults() ? die($err_msg) : warn($err_msg);
}
1;
( run in 2.621 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )