use strict;
use utf8;
use Mouse;
use JSON;
use Amon2::Auth::Util qw(parse_content);
our $VERSION = '0.07';
sub moniker { 'github' }
has client_id => (
is => 'ro',
isa => 'Str',
required => 1,
);
has client_secret => (
is => 'ro',
isa => 'Str',
required => 1,
);
has scope => (
is => 'ro',
isa => 'Str',
);
has user_info => (
is => 'rw',
isa => 'Bool',
default => 1,
);
has ua => (
is => 'ro',
isa => 'LWP::UserAgent',
lazy => 1,
default => sub {
my $ua = LWP::UserAgent->new(agent => "Amon2::Auth/$Amon2::Auth::VERSION");
},
);
has authorize_url => (
is => 'ro',
isa => 'Str',
);
has access_token_url => (
is => 'ro',
isa => 'Str',
);
has redirect_url => (
is => 'ro',
isa => 'Str',
);
sub auth_uri {
my ($self, $c, $callback_uri) = @_;
my $redirect_uri = URI->new($self->authorize_url);
my %params;
if (defined $callback_uri) {
$params{redirect_uri} = $callback_uri;
} elsif (defined $self->redirect_url) {
$params{redirect_uri} = $self->redirect_url;
}
for (qw(client_id scope)) {
next unless defined $self->$_;
$params{$_} = $self->$_;
}
$redirect_uri->query_form(%params);
return $redirect_uri->as_string;
}
sub callback {
my ($self, $c, $callback) = @_;
my $code = $c->req->param('code') or die "Cannot get a 'code' parameter";
my %params = (code => $code);
$params{client_id} = $self->client_id;
$params{client_secret} = $self->client_secret;
$params{redirect_url} = $self->redirect_url if defined $self->redirect_url;
my $res = $self->ua->post($self->access_token_url, \%params);
$res->is_success or die "Cannot authenticate";
my $dat = parse_content($res->decoded_content);
if (my $err = $dat->{error}) {
return $callback->{on_error}->($err);
}
my $access_token = $dat->{access_token} or die "Cannot get a access_token";
my @args = ($access_token);
if ($self->user_info) {
my $res = $self->ua->get("https://api.github.com/user?oauth_token=${access_token}");
$res->is_success or return $callback->{on_error}->($res->status_line);
my $dat = decode_json($res->decoded_content);
push @args, $dat;
}
return $callback->{on_finished}->( @args );
}
1;
__END__
=head1 NAME
Amon2::Auth::Site::Github - Github integration for Amon2
=head1 SYNOPSIS
__PACKAGE__->load_plugin('Web::Auth', {
module => 'Github',
on_finished => sub {
my ($c, $token, $user) = @_;
my $name = $user->{name} || die;
$c->session->set('name' => $name);
$c->session->set('site' => 'github');
return $c->redirect('/');
}
});
=head1 DESCRIPTION
This is a github authentication module for Amon2. You can call a github APIs with this module.
=head1 ATTRIBUTES
=over 4
=item client_id
=item client_secret
=item scope
API scope in string.
=item user_info(Default: true)
Fetch user information after authenticate?
=item ua(instance of LWP::UserAgent)
You can replace instance of L<LWP::UserAgent>.
=back
=head1 METHODS
=over 4
=item C<< $auth->auth_uri($c:Amon2::Web, $callback_uri : Str) :Str >>
Get a authenticate URI.
=item C<< $auth->callback($c:Amon2::Web, $callback:HashRef) : Plack::Response >>
Process the authentication callback dispatching.
C<< $callback >> MUST have two keys.
=over 4
=item on_error
on_error callback function is called if an error was occurred.
The arguments are following:
sub {
my ($c, $error_message) = @_;
...
}
=item on_finished
on_finished callback function is called if an authentication was finished.
The arguments are following:
sub {
my ($c, $access_token, $user) = @_;
...
}
C<< $user >> contains user information. This code contains a information like L<https://api.github.com/users/dankogai>.
If you set C<< $auth->user_info >> as false value, authentication engine does not pass C<< $user >>.
=back
=back