OIDC-Client

 view release on metacpan or  search on metacpan

lib/OIDC/Client.pm  view on Meta::CPAN

                                         build_api_useragent_from_token_value);
use OIDC::Client::Utils qw(reach_data);

our $VERSION = '1.06'; # VERSION: generated by Dist::Zilla::Plugin::OurPkgVersion

=encoding utf8

=head1 NAME

OIDC::Client - OpenID Connect Client

=head1 SYNOPSIS

  my $client = OIDC::Client->new(
    provider          => 'my_provider',
    id                => 'my_client_id',
    secret            => 'my_client_secret',
    provider_metadata => \%provider_metadata,
    log               => $app->log,
  );

  # or...

  my $client = OIDC::Client->new(
    config => $config_provider,
    log    => $app->log,
  );

  my $authorize_url  = $client->auth_url();
  my $token_response = $client->get_token(code => $code);
  my $claims         = $client->verify_jwt_token(token => $token);
  my $claims         = $client->introspect_token(token => $token);
  my $userinfo       = $client->get_userinfo(access_token => $token);
  my $token_response = $client->exchange_token(token => $token, audience => $audience);
  my $ua             = $client->build_api_useragent();
  my $logout_url     = $client->logout_url();

=head1 DESCRIPTION

Client module for OpenID Connect and OAuth 2.0 protocols.

Use this module directly from a batch or a simple script. For use from within
an application, you should instead use one of these framework plugins, which
all use this distribution :

=over 2

=item * L<Mojolicious::Plugin::OIDC>

=item * L<Catalyst::Plugin::OIDC>

=item * L<Dancer2::Plugin::OIDC>

=back

=cut

enum 'StoreMode'             => [qw/session stash cache/];
enum 'ResponseMode'          => [qw/query form_post/];
enum 'GrantType'             => [qw/authorization_code client_credentials password refresh_token/];
enum 'ClientAuthMethod'      => [qw/client_secret_basic client_secret_post client_secret_jwt private_key_jwt none/];
enum 'TokenValidationMethod' => [qw/jwt introspection/];

with 'OIDC::Client::Role::LoggerWrapper';
with 'OIDC::Client::Role::AttributesManager';
with 'OIDC::Client::Role::ConfigurationChecker';
with 'OIDC::Client::Role::ClaimsValidator';
with 'OIDC::Client::Role::ClientAuthenticationHelper';

=head1 METHODS

=head2 BUILD

Called after the object is created. Makes some basic checks and forces
the retrieval of provider metadata and kid keys.

=cut

sub BUILD {
  my $self = shift;

  $self->_check_configuration();
  $self->_check_audiences_configuration();
  $self->_check_cache_configuration();

  $self->provider;
  $self->id;

  $self->provider_metadata;
  $self->kid_keys if $self->provider_metadata->{jwks_url};
}


=head2 auth_url( %args )

  my $authorize_url = $client->auth_url(%args);

Returns a scalar or a L<Mojo::URL> object containing the initial authorization URL.
This is the URL to use to initiate an authorization code flow.

The optional parameters are:

=over 2

=item response_mode

Defines how tokens are sent by the provider.

Can take one of these values:

=over 2

=item query

Tokens are sent in query parameters.

=item form_post

Tokens are sent in a POST form.

=back

lib/OIDC/Client.pm  view on Meta::CPAN

  if (my $extra_params = $params{extra_params} || $self->authorize_endpoint_extra_params) {
    foreach my $param_name (keys %$extra_params) {
      $args{$param_name} = $extra_params->{$param_name};
    }
  }

  my $auth_url = Mojo::URL->new($authorize_url);
  $auth_url->query(%args);

  return $params{want_mojo_url} ? $auth_url : $auth_url->to_string;
}


=head2 get_token( %args )

  my $token_response = $client->get_token(
    code         => $code,
    redirect_uri => q{http://yourapp/oidc/callback},
  );

Fetch token(s) from an OAuth2/OIDC provider and returns an
L<OIDC::Client::TokenResponse> object.

This method doesn't perform any verification on the ID token.
Call the L</"verify_jwt_token( %args )"> method to do so.

The optional parameters are:

=over 2

=item grant_type

Specifies how the client wants to interact with the identity provider.
Accepted here : C<authorization_code>, C<client_credentials>, C<password>
or C<refresh_token>.
Can also be specified in the C<token_endpoint_grant_type> configuration entry.
Default to C<authorization_code>.

=item auth_method

Specifies how the client authenticates with the identity provider.

Supported client authentication methods:

=over 2

=item *

client_secret_basic (default)

=item *

client_secret_post

=item *

client_secret_jwt

=item *

private_key_jwt

=item *

none

=back

Can also be specified in the C<token_endpoint_auth_method> configuration entry
or the global C<client_auth_method> configuration entry.
Default to C<client_secret_basic>.

=item code

Authorization-code that is issued beforehand by the identity provider.
Used only for the C<authorization_code> grant-type.

=item redirect_uri

Redirection URI to which the response will be sent.
Can also be specified in the C<signin_redirect_uri> configuration entry.
Used only for the C<authorization_code> grant-type.

=item username / password

User credentials for authorization
Can also be specified in the C<username> and C<password> configuration entries.
Used only the for C<password> grant-type.

=item audience

Specifies the Relaying Party for which the token is intended.
Can also be specified in the C<audience> configuration entry.
Not used for the C<refresh_token> grant-type.

=item scope

Specifies the desired scope of the requested token.
Must be a string with space separators.
Can also be specified in the C<scope> configuration entry.
Not used for the C<authorization_code> nor the C<refresh_token> grant-type.

=item refresh_token

Token that can be used to renew the associated access token before it expires.
Used only for the C<refresh_token> grant-type.

=item refresh_scope

Specifies the desired scope of the requested renewed token.
Must be a string with space separators.
Used only for the C<refresh_token> grant-type.

=back

=cut

sub get_token {
  my $self = shift;
  my (%params) = validated_hash(
    \@_,

lib/OIDC/Client.pm  view on Meta::CPAN


=cut

sub verify_token {
  my ($self, %params) = @_;
  warnings::warnif('deprecated',
                   'OIDC::Client::verify_token() is deprecated in favor of OIDC::Client::verify_jwt_token()');
  return $self->verify_jwt_token(%params);
}


=head2 introspect_token( %args )

  my $claims = $client->introspect_token(
    token           => $token,
    token_type_hint => 'access_token',
  );

Allows a Resource Server to validate a token and obtain its metadata by calling the provider's
introspection endpoint. Typically used when the access token is opaque (not a JWT).

Throws an L<OIDC::Client::Error::Provider> exception if an error is returned by the provider
or an L<OIDC::Client::Error::TokenValidation> exception if a validation error occurs.
Otherwise, returns the claims.

The parameters are:

=over 2

=item token

The token to validate.
Required.

=item token_type_hint

Hint about the type of the token submitted for introspection.

=item auth_method

Specifies how the client authenticates with the identity provider.

Supported client authentication methods:

=over 2

=item *

client_secret_basic (default)

=item *

client_secret_post

=item *

client_secret_jwt

=item *

private_key_jwt

=item *

none

=back

Can also be specified in the C<introspection_endpoint_auth_method> configuration entry
or the global C<client_auth_method> configuration entry.
Default to C<client_secret_basic>.

=item expected_audience

If the C<aud> claim is present in the provider response of the introspection endpoint,
its value must match the expected audience, otherwise an exception is thrown.
Default to the C<audience> configuration entry or the client id.

=back

=cut

sub introspect_token {
  my $self = shift;
  my (%params) = validated_hash(
    \@_,
    token             => { isa => 'Str', optional => 0 },
    token_type_hint   => { isa => enum([qw/access_token refresh_token/]), optional => 1 },
    auth_method       => { isa => 'ClientAuthMethod', optional => 1 },
    expected_audience => { isa => 'Str', optional => 1 },
  );

  my $introspection_url = $self->provider_metadata->{introspection_url}
    or croak("OIDC: introspection_url not found in provider metadata");

  my $auth_method = $params{auth_method} || $self->introspection_endpoint_auth_method;
  my ($headers, $form) = $self->_build_client_auth_arguments($auth_method, $introspection_url);

  $form->{token} = $params{token};

  if (my $token_type_hint = $params{token_type_hint}) {
    $form->{token_type_hint} = $token_type_hint;
  }

  $self->log_msg(debug => 'OIDC: calling provider to introspect token');
  my $res = $self->user_agent->post($introspection_url, $headers, form => $form)->result;

  my $claims = $self->response_parser->parse($res);

  $claims->{active}
    or OIDC::Client::Error::TokenValidation->throw("OIDC: inactive token");

  if (exists $claims->{iss}) {
    $self->_validate_issuer($claims->{iss});
  }

  if (exists $claims->{aud}) {
    $self->_validate_audience($claims->{aud}, $params{expected_audience});
  }

  return $claims;

lib/OIDC/Client.pm  view on Meta::CPAN


  my $audience_infos = first { $_->{audience} eq $audience  } values %$audience_alias
    or return;

  return $audience_infos->{scope};
}


=head2 exchange_token( %args )

  my $exchanged_token_response = $client->exchange_token(
    token    => $token,
    audience => $audience,
  );

Exchanges an access token, obtained through OIDC authentication, for another access
token that is accepted by a different OIDC application.

Returns a L<OIDC::Client::TokenResponse> object.

The parameters are:

=over 2

=item token

Content of the valid access token obtained through OIDC authentication.

=item audience

Audience of the target application.

=item scope

Specifies the desired scope of the requested token.
Must be a string with space separators.
Optional.

=item auth_method

Specifies how the client authenticates with the identity provider.

Supported client authentication methods:

=over 2

=item *

client_secret_basic (default)

=item *

client_secret_post

=item *

client_secret_jwt

=item *

private_key_jwt

=item *

none

=back

Can also be specified in the C<token_endpoint_auth_method> configuration entry
or the global C<client_auth_method> configuration entry.
Default to C<client_secret_basic>.

=back

=cut

sub exchange_token {
  my $self = shift;
  my (%params) = validated_hash(
    \@_,
    token       => { isa => 'Str', optional => 0 },
    audience    => { isa => 'Str', optional => 0 },
    scope       => { isa => 'Str', optional => 1 },
    auth_method => { isa => 'ClientAuthMethod', optional => 1 },
  );

  my $token_url = $self->provider_metadata->{token_url}
    or croak("OIDC: token url not found in provider metadata");

  my $auth_method = $params{auth_method} || $self->token_endpoint_auth_method;
  my ($headers, $form) = $self->_build_client_auth_arguments($auth_method, $token_url);

  $form->{audience}           = $params{audience};
  $form->{grant_type}         = 'urn:ietf:params:oauth:grant-type:token-exchange';
  $form->{subject_token}      = $params{token};
  $form->{subject_token_type} = 'urn:ietf:params:oauth:token-type:access_token';

  if (my $scope = ($params{scope} || $self->get_scope_for_audience($params{audience}))) {
    $form->{scope} = $scope;
  }

  $self->log_msg(debug => 'OIDC: calling provider to exchange token');

  my $res = $self->user_agent->post($token_url, $headers, form => $form)->result;

  return $self->token_response_parser->parse($res);
}


=head2 build_api_useragent( %args )

  my $ua = $client->build_api_useragent();

Invokes the L</"get_token( %args )"> method and builds a web client (L<Mojo::UserAgent>
object) that will have the given access token in the authorization header for each request.

This method can be useful if the client is configured for a password grant
or a client credentials grant and you simply want to build a web client to call
an API protected by OAuth2.

=cut



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