Mojo-JWT-Google

 view release on metacpan or  search on metacpan

lib/Mojo/JWT/Google.pm  view on Meta::CPAN


has client_email => undef;
has expires_in   => 3600;
has issue_at     => undef;
has scopes       => sub { [] };
has target       => q(https://www.googleapis.com/oauth2/v4/token);
has user_as      => undef;
has audience     => undef;

sub new {
  my ($class, %options) = @_;
  my $self = $class->SUPER::new(%options);
  return $self if not defined $self->{from_json};

  my $result = $self->from_json($self->{from_json});

  return $self;
}

sub claims {
  my ($self, $value) = @_;
  if (defined $value) {
    $self->{claims} = $value;
    return $self;
  }
  my $claims = $self->_construct_claims;
  unless (exists $claims->{exp}) {
    $claims->{exp} = $self->now + $self->expires_in ;
  }
  return $claims;
}

sub _construct_claims {
  my $self = shift;
  my $result = {};
  $result->{iss}   = $self->client_email;
  $result->{aud}   = $self->target;
  $result->{sub}   = $self->user_as if defined $self->user_as;
  my @scopes = @{ $self->scopes };

  croak "Can't use both scopes and audience in the same token" if @scopes && $self->audience;
  $result->{scope} = join ' ', @scopes if @scopes;
  $result->{target_audience} = $self->audience if defined $self->audience;

  if ( not defined $self->issue_at ) {
    $self->set_iat(1);
  }
  else {
    $self->set_iat(0);
    $result->{iat} = $self->issue_at;
    $result->{exp} = $self->issue_at + $self->expires_in;
  }
  return $result;
}

sub from_json {
  my ($self, $value) = @_;
  croak 'You did not pass a filename to from_json' if not defined $value;
  croak 'Cannot find file passed to from_json' if not -f $value;
  my $json = decode_json( path($value)->slurp );
  croak 'private key was not found in file passed to from_json' unless $json->{private_key};
  croak 'from_json only works with service accounts' if $json->{type} ne 'service_account';
  $self->algorithm('RS256');
  $self->secret($json->{private_key});
  $self->client_email($json->{client_email});
  return 1
}

sub as_form_data {
  my ($self) = @_;
  return {
    grant_type => 'urn:ietf:params:oauth:grant-type:jwt-bearer',
    assertion => $self->encode
  }
}

1;


=head1 NAME

Mojo::JWT::Google - Service Account tokens

=head1 VERSION

version 0.15

=head1 SYNOPSIS

  my $gjwt = Mojo::JWT::Google->new(secret => 's3cr3t',
                                    scopes => [ '/my/scope/a', '/my/scope/b' ],
                                    client_email => 'riche@cpan.org')->encode;

  # authenticating for apis as a service account
  my $gjwt = Mojo::JWT::Google->new(
     from_json => '/my/secret/project-b98ale897.json',
     scopes    => 'https://www.googleapis.com/auth/gmail.send',
     user_as   => 'some-email@your-org.com'); # if you have domain-wide delegation
  my $ua = Mojo::UserAgent->new;
  my $tx = $ua->post('https://www.googleapis.com/oauth2/v4/token', form => $gjwt->as_form_data);
  $tx->res->json('/access_token') # will contain your access token 
  
  # authenticating to use the Identity Aware Proxy
  my $gjwt = Mojo::JWT::Google->new(
     from_json => '/my/secret/project-b98ale897.json',
     audience  => 'the-client-id-from-your-IAP');
  my $ua = Mojo::UserAgent->new;
  my $tx = $ua->post('https://www.googleapis.com/oauth2/v4/token', form => $gjwt->as_form_data);
  $tx->res->json('/id_token') # will contain your id token 

=head1 DESCRIPTION

Like L<Mojo::JWT>, you can instantiate this class by using the same syntax,
except that this class constructs the claims for you.

 my $jwt = Mojo::JWT::Google->new(secret => 's3cr3t')->encode;

And add any attribute defined in this class.  The JWT is fairly useless unless
you define your scopes.

 my $gjwt = Mojo::JWT::Google->new(secret => 's3cr3t',
                                   scopes => [ '/my/scope/a', '/my/scope/b' ],
                                   client_email => 'riche@cpan.org')->encode;



( run in 0.589 second using v1.01-cache-2.11-cpan-d8267643d1d )