--- /dev/null
+package Catalyst::Authentication::Credential::OAuth;
+use strict;
+use warnings;
+
+use Moose;
+
+has _config => ( is => 'rw' );
+has realm => ( is => 'ro' );
+has debug => ( is => 'rw' );
+has defaults => ( is => 'rw' );
+has provider => ( is => 'rw' );
+
+our $VERSION = "0.01";
+
+use Net::OAuth;
+#$Net::OAuth::PROTOCOL_VERSION = Net::OAuth::PROTOCOL_VERSION_1_0A;
+use HTTP::Request::Common;
+use LWP::UserAgent;
+use String::Random qw/ random_string /;
+
+use Catalyst::Exception ();
+
+sub new {
+ my ($class, $config, $c, $realm) = @_;
+
+ my $self = { _config => {
+ %{ $config },
+ %{ $realm->{config} }
+ } };
+
+ bless $self, $class;
+
+ $self->debug( $self->_config->{debug} );
+
+ $self->defaults( {
+ request_method => 'GET',
+ signature_method => 'HMAC-SHA1',
+ nonce => random_string( 'ccccccccccccccccccc' ),
+ } );
+
+ return $self;
+}
+
+
+sub authenticate {
+ my ($self, $c, $realm, $auth_info) = @_;
+
+ Catalyst::Exception->throw( "Provider is not defined." )
+ unless defined $self->_config->{ $auth_info->{oauth_provider} };
+
+ $self->provider( $self->_config->{ $auth_info->{oauth_provider} } );
+
+ $self->defaults( {
+ %{ $self->defaults },
+ timestamp => time,
+ consumer_key => $self->provider->{key},
+ consumer_secret => $self->provider->{secret},
+ callback => $c->uri_for( $c->action )->as_string,
+ } );
+
+ $c->log_debug( "authenticate() called from " . $c->request->uri ) if $self->debug;
+
+ my $ua = LWP::UserAgent->new;
+
+ if( $c->req->params->{oauth_token} ) {
+
+ my $response = Net::OAuth->response( 'user auth' )->from_hash( $c->req->params );
+
+ Catalyst::Exception->throw( "access_token_endpoint not defined" )
+ unless $self->provider->{access_token_endpoint};
+
+ my $request = Net::OAuth->request( 'access token' )->new(
+ %{ $self->defaults },
+ token => $response->token,
+ token_secret => '',
+ request_url => $self->provider->{access_token_endpoint},
+ );
+
+ $request->sign;
+
+ my $ua_response = $ua->request( GET $request->to_url );
+
+ Catalyst::Exception->throw( $ua_response->status_line.' '.$ua_response->content )
+ unless $ua_response->is_success;
+
+ $response = Net::OAuth->response( 'access token' )->from_post_body( $ua_response->content );
+
+ my $user = +{
+ token => $response->token,
+ token_secret => $response->token_secret,
+ extra_params => $response->extra_params
+ };
+
+ my $user_obj = $realm->find_user( $user, $c );
+
+ return $user_obj if ref $user_obj;
+
+ $c->log->debug( 'Verified OAuth identity failed' ) if $self->debug;
+
+ return;
+ }
+ else {
+
+ Catalyst::Exception->throw( "request_token_endpoint not defined" )
+ unless $self->provider->{request_token_endpoint};
+
+ my $request = Net::OAuth->request( 'request token' )->new(
+ %{ $self->defaults },
+ request_url => $self->provider->{request_token_endpoint}
+ );
+
+ $request->sign;
+
+ my $ua_response = $ua->request( GET $request->to_url );
+
+ Catalyst::Exception->throw( $ua_response->status_line.' '.$ua_response->content )
+ unless $ua_response->is_success;
+
+ my $response = Net::OAuth->response( 'request token' )->from_post_body( $ua_response->content );
+
+ Catalyst::Exception->throw( "user_auth_endpoint not defined" )
+ unless $self->provider->{user_auth_endpoint};
+
+ $request = Net::OAuth->request( 'user auth' )->new(
+ %{ $self->defaults },
+ token => $response->token,
+ );
+
+ $c->res->redirect( $request->to_url( $self->provider->{user_auth_endpoint} ) );
+ }
+
+}
+
+
+
+1;
+
+
+__END__
+
+=head1 NAME
+
+Catalyst::Authentication::Credential::OAuth - OAuth credential for Catalyst::Plugin::Authentication framework.
+
+=head1 VERSION
+
+0.01
+
+=head1 SYNOPSIS
+
+In MyApp.pm
+
+ use Catalyst qw/
+ Authentication
+ Session
+ Session::Store::FastMmap
+ Session::State::Cookie
+ /;
+
+
+In myapp.conf
+
+ <Plugin::Authentication>
+ default_realm oauth
+ <realms>
+ <oauth>
+ <credential>
+ class OAuth
+ </credential>
+ <example_provider>
+ key my_app_key
+ secret my_app_secret
+ request_token_endpoint http://example.com/oauth/request_token
+ access_token_endpoint http://example.com/oauth/access_token
+ user_auth_endpoint http://example.com/oauth/authorize
+ </example_provider>
+ </oauth>
+ </realms>
+</Plugin::Authentication>
+
+
+In controller code,
+
+ sub oauth : Local {
+ my ($self, $c) = @_;
+
+ if( $c->authenticate( { oauth_provider => 'example_provider' } ) ) {
+ #do something with $c->user
+ }
+ }
+
+
+
+=head1 USER METHODS
+
+=over 4
+
+=item $c->user->token
+
+=item $c->user->token_secret
+
+=item $c->user->extra_params - whatever other parameters the provider sends back
+
+=back
+
+=head1 AUTHOR
+
+Cosmin Budrica E<lt>cosmin@sinapticode.comE<gt>
+
+Bogdan Lucaciu E<lt>bogdan@sinapticode.comE<gt>
+
+=head1 COPYRIGHT
+
+Copyright (c) 2009 Sinapticode. All rights reserved
+
+This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
+
+=cut