Google-Ads-AdWords-Client

 view release on metacpan or  search on metacpan

lib/Google/Ads/Common/OAuth2BaseHandler.pm  view on Meta::CPAN

#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

package Google::Ads::Common::OAuth2BaseHandler;

use strict;
use warnings;
use version;
use base qw(Google::Ads::Common::AuthHandlerInterface);

# The following needs to be on one line because CPAN uses a particularly hacky
# eval() to determine module versions.
use Google::Ads::Common::Constants; our $VERSION = ${Google::Ads::Common::Constants::VERSION};

use Class::Std::Fast;
use HTTP::Request::Common;
use LWP::UserAgent;
use URI::Escape;

use constant OAUTH2_TOKEN_INFO_URL =>
  "https://www.googleapis.com/oauth2/v1/tokeninfo";

# 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 %api_client_of : ATTR(:name<api_client> :default<>);
my %client_id_of : ATTR(:name<client_id> :default<>);
my %access_token_of : ATTR(:init_arg<access_token> :default<>);
my %access_token_expires_of : ATTR(:name<access_token_expires> :default<>);
my %__user_agent_of : ATTR(:name<__user_agent> :default<>);

# Constructor
sub START {
  my ($self, $ident) = @_;

  $__user_agent_of{$ident} ||= LWP::UserAgent->new();
}

# Methods from Google::Ads::Common::AuthHandlerInterface
sub initialize : CUMULATIVE(BASE FIRST) {
  my ($self, $api_client, $properties) = @_;
  my $ident = ident $self;

  $api_client_of{$ident} = $api_client;
  $client_id_of{$ident}  = $properties->{oAuth2ClientId}
    || $client_id_of{$ident};
  $access_token_of{$ident} = $properties->{oAuth2AccessToken}
    || $access_token_of{$ident};
}

sub prepare_request {
  my ($self, $endpoint, $http_headers, $envelope) = @_;

  my $access_token = $self->get_access_token();

  if (!$access_token) {
    my $api_client = $self->get_api_client();
    my $err_msg =
      "Unable to prepare a request, authorization info is " .
      "incomplete or invalid.";
    $api_client->get_die_on_faults() ? die($err_msg) : warn($err_msg);
    return;
  }

  push @{$http_headers}, ("Authorization", "Bearer ${access_token}");

  return HTTP::Request->new('POST', $endpoint, $http_headers, $envelope);
}

sub is_auth_enabled {
  my ($self) = @_;

  return $self->get_access_token();
}

# Custom getters and setters for the access token with logic to auto-refresh.
sub get_access_token {
  my $self  = shift;
  my $ident = ident $self;

  if (!$self->_is_access_token_valid()) {
    if (!$self->_refresh_access_token()) {
      return undef;
    }

    return $access_token_of{$ident};
  }

  return $access_token_of{$ident};
}

sub set_access_token {
  my ($self, $token) = @_;

  $access_token_of{ident $self}         = $token;
  $access_token_expires_of{ident $self} = undef;
}

# Internal methods

# Checks if:
#   - the access token is set
#   - if the token has no expiration set then assumes it was manually set and:
#       - checks the token info, if it is valid then set its expiration
#       - checks the token scopes
#   - checks the token has not expired
sub _is_access_token_valid {
  my $self  = shift;
  my $ident = ident $self;

  my $access_token = $access_token_of{$ident};
  if (!$access_token) {
    return 0;
  }

  if (!$self->get_access_token_expires()) {
    my $url =
      OAUTH2_TOKEN_INFO_URL . "?access_token=" . uri_escape($access_token);
    my $res = $self->get___user_agent()->request(GET $url);
    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());



( run in 0.834 second using v1.01-cache-2.11-cpan-39bf76dae61 )