Google-Ads-AdWords-Client
view release on metacpan or search on metacpan
lib/Google/Ads/Common/OAuth2ServiceAccountsHandler.pm view on Meta::CPAN
ATTR(:name<delegated_email_address> :default<>);
my %additional_scopes_of : ATTR(:name<additional_scopes> :default<>);
my %pem_file_of : ATTR(:name<pem_file> :default<>);
my %json_file_of : ATTR(:name<json_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};
$json_file_of{$ident} = $properties->{oAuth2ServiceAccountJSONFile}
|| $json_file_of{$ident};
$additional_scopes_of{$ident} = $properties->{oAuth2AdditionalScopes}
|| $additional_scopes_of{$ident};
}
sub _refresh_access_token {
my $self = shift;
if ($self->get_json_file() and $self->get_pem_file()) {
warn("Only one of oAuth2ServiceAccountPEMFile or " .
"oAuth2ServiceAccountJSONFile can be specified in adwords.properties.");
return 0;
}
my $file = $self->__read_certificate_file() || return 0;
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->_formatted_scopes();
my $header = '{"alg":"RS256","typ":"JWT"}';
my $claims = "{
\"iss\":\"${iss}\",
\"sub\":\"${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()) {
my $err_msg = $res->decoded_content();
$self->get_api_client()->get_die_on_faults()
? die($err_msg)
: warn($err_msg);
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});
}
# Return the private key string from either the PEM file or JSON file specified.
sub __read_certificate_file {
my $self = shift;
my $private_key;
if (!$self->get_pem_file() and !$self->get_json_file()) {
return 0;
}
# JSON File
if ($self->get_json_file()) {
my $file_str;
open(MYFILE, $self->get_json_file()) || return 0;
while (<MYFILE>) {
$file_str .= $_;
}
my $json_values = parse_json ($file_str);
$private_key = $json_values->{'private_key'};
$self->set_email_address($json_values->{'client_email'});
close(MYFILE);
}
# PEM File
else {
open(MYFILE, $self->get_pem_file()) || return 0;
while (<MYFILE>) {
$private_key .= $_;
}
close(MYFILE);
}
return $private_key;
}
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 _formatted_scopes {
my $self = shift;
die "Need to be implemented by subclass";
}
1;
=pod
=head1 NAME
Google::Ads::Common::OAuth2ServiceAccountsHandler
=head1 DESCRIPTION
A generic abstract implementation of L<Google::Ads::Common::OAuth2BaseHandler>
that supports OAuth2 for Service Accounts semantics.
It is meant to be specialized and its L<_scope> and L<_formatted_scopes> methods
be properly implemented.
=head1 ATTRIBUTES
Each of these attributes can be set via
Google::Ads::Common::OAuth2ServiceAccountsHandler->new().
Alternatively, there is a get_ and set_ method associated with each attribute
for retrieving or setting them dynamically.
=head2 api_client
A reference to the API client used to send requests.
=head2 client_id
OAuth2 client id obtained from the Google APIs Console.
=head2 email_address
Service account email address as found in the Google API Console.
=head2 delegated_email_address
Delegated email address of the accounts that has access to the API.
( run in 0.658 second using v1.01-cache-2.11-cpan-13bb782fe5a )