package CatalystX::OAuth2;
use Moose::Role;
# ABSTRACT: OAuth2 services for Catalyst
requires '_build_query_parameters';
# spec isn't clear re missing endpoint uris, being strict for now
has redirect_uri => ( is => 'ro', required => 1 );
has store => (
is => 'rw',
does => 'CatalystX::OAuth2::Store',
init_arg => undef,
predicate => 'has_store'
);
has query_parameters => ( is => 'rw', init_arg => undef, lazy_build => 1 );
sub _params {qw(response_type redirect_uri scope state client_id)}
sub BUILD {
my ( $self, $args ) = @_;
delete @{$args}{ $self->_params() };
if ( my @extra = keys %$args ) {
$self->query_parameters(
{ error => 'invalid_request',
error_description => 'unrecognized parameters: '
. join( ', ', @extra )
}
);
}
}
1;
__END__
=pod
=head1 NAME
CatalystX::OAuth2 - OAuth2 services for Catalyst
=head1 VERSION
version 0.001002
=head1 SYNOPSIS
package AuthServer::Controller::OAuth2::Provider;
use Moose;
BEGIN { extends 'Catalyst::Controller::ActionRole' }
with 'CatalystX::OAuth2::Controller::Role::Provider';
__PACKAGE__->config(
store => {
class => 'DBIC',
client_model => 'DB::Client'
}
);
sub request : Chained('/') Args(0) Does('OAuth2::RequestAuth') {}
sub grant : Chained('/') Args(0) Does('OAuth2::GrantAuth') {
my ( $self, $c ) = @_;
my $oauth2 = $c->req->oauth2;
$c->user_exists and $oauth2->user_is_valid(1)
or $c->detach('/passthrulogin');
}
sub token : Chained('/') Args(0) Does('OAuth2::AuthToken::ViaAuthGrant') {}
sub refresh : Chained('/') Args(0) Does('OAuth2::AuthToken::ViaRefreshToken') {}
1;
=head1 DESCRIPTION
This module implements the authorization grant subset of the L<oauth 2 ietf
spec draft|http://tools.ietf.org/html/draft-ietf-oauth-v2-23>. Action roles
containing an implementation of each required endpoint in the specification
are provided and should be applied to a L<Catalyst::Controller::ActionRole>.
The authorization grant flow is defined by the specification as follows:
+--------+ +---------------+
| |--(A)------- Authorization Grant --------->| |
| | | |
| |<-(B)----------- Access Token -------------| |
| | & Refresh Token | |
| | | |
| | +----------+ | |
| |--(C)---- Access Token ---->| | | |
| | | | | |
| |<-(D)- Protected Resource --| Resource | | Authorization |
| Client | | Server | | Server |
| |--(E)---- Access Token ---->| | | |
| | | | | |
| |<-(F)- Invalid Token Error -| | | |
| | +----------+ | |
| | | |
| |--(G)----------- Refresh Token ----------->| |
| | | |
| |<-(H)----------- Access Token -------------| |
+--------+ & Optional Refresh Token +---------------+
The action roles should be applied to actions in a single controller, and no
more than one action of each role type should be present.
Here is an overview of what roles are involved in each of those phases:
=over
=item A - L<Catalyst::ActionRole::OAuth2::RequestAuth>
Required
This is the action where the authentication grant flow begins, it validades
and sanitizes the request parameters and generates an authorization code which
is used for issuing a valid request to the GrantAuth action via a redirect.
The authorization code is only generated if all parameters are well-formed and
valid, this ensures that requests to the GrantAuth action can trust the
request parameters if a valid authorization code is presented.
=item B - L<Catalyst::ActionRole::OAuth2::GrantAuth>
Required
This action checks the request parameters for a valid authorization code,
which should have been generated by a previous request to a RequestAuth
action. This action should be customized to somehow confirm with the end-user
if he wishes to effectively grant the authorization to the requesting
client/app. The user-agent is redirected automatically to the correct endpoint
if the authorization is granted.
=item C and D - L<Catalyst::ActionRole::OAuth2::AuthToken::ViaAuthGrant>
Required
This action exchanges a valid authorization grant code and responds with an
authorization token.
=item G and H - L<Catalyst::ActionRole::OAuth2::AuthToken::ViaRefreshToken>
Optional
This action exchanges a valid refresh token for a new access token and refresh
token.
=back
=head1 CONFIGURATION
=head2 store
Takes a hashref containing two keys:
=over
=item class
The store type to use, so far, only DBIC support is provided
=item client_model
The entity representing the client in your schema
=back
=head1 SPONSORSHIP
This module exists due to the wonderful people at Suretec Systems
Ltd. <http://www.suretecsystems.com/> who sponsored it's development for its
VoIP division called SureVoIP <http://www.surevoip.co.uk/>
=head1 AUTHOR
Eden Cardim <edencardim@gmail.com>
=head1 COPYRIGHT AND LICENSE
This software is copyright (c) 2012 by Suretec Systems Ltd.
This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.
=cut