Net-Linkedin-OAuth2/lib/Net/Linkedin/OAuth2.pm
package Net::Linkedin::OAuth2;
use strict;
use warnings;
use JSON::Any;
use LWP::UserAgent;
use Carp 'confess';
use XML::Hash;
use Digest::MD5 'md5_hex';
require Exporter;
our @ISA = qw(Exporter);
our %EXPORT_TAGS = ( 'all' => [ qw( ) ] );
our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
our @EXPORT = qw(
);
our $VERSION = '0.32';
=head1 NAME
Net::Linkedin::OAuth2 - An easy way to authenticate users via LinkedIn.
=head1 VERSION
version 0.32
=head1 SYNOPSIS
my $linkedin = Net::Linkedin::OAuth2->new( key => 'your-app-key', secret => 'your-app-secret');
=head2 get authorization url({ redirect_uri => 'http://localhost:3000/user/linkedin', scope => ['r_basicprofile','rw_groups','r_emailaddress']})
# scope is an array of permissions that your app requires, see http://developer.linkedin.com/documents/authentication#granting for more details, this field is optional
my $authorization_code_url = $linkedin->authorization_code_url(
redirect_uri => 'url_of_your_app_to_intercept_success',
scope => ['r_basicprofile','rw_groups','r_emailaddress']
);
# convert code response to an access token
# redirect_uri is the url where you will check for the parameter code.
# param('code') is the parameter 'code' that you will get after the user authorizes your app and gets redirected to the redirect_uri (callback) page.
my $token_object = $linkedin->get_access_token(
authorization_code => param('code'),
redirect_uri => 'your-app-redirect-url-or-callback'
);
# use the new token to request user information
my $result = $linkedin->request(
url => 'https://api.linkedin.com/v1/people/~:(id,formatted-name,picture-url,email-address)?format=json',
token => $token_object->{access_token}
);
# we have the email address
if ($result->{emailAddress}) {
# ...
}
# Or here is an entire login logic or recipe:
my $linkedin = Net::Linkedin::OAuth2->new( key => 'your-app-key',
secret => 'your-app-secret');
# catch the code param and try to convert it into an access_token and get the email address
if (param('code')) {
my $token_object = $linkedin->get_access_token(
authorization_code => param('code'),
# has to be the same redirect_uri you specified in the code before
redirect_uri => 'your-app-redirect-uri-or-callback-url'
);
my $result = $linkedin->request(
url => 'https://api.linkedin.com/v1/people/~:(id,formatted-name,picture-url,email-address)?format=json',
token => $token_object->{access_token} );
if ($result->{emailAddress}) {
# we have the email address, authenticate the user and redirect somewhere..
# ....
return;
} else {
# we did not get an email address
# redirect to try again?
return;
}
}
# get the url for permissions
my $authorization_code_url = $linkedin->authorization_code_url(
# this field is required
redirect_uri => 'your-app-redirect',
#array of permissions that your app requires, see http://developer.linkedin.com/documents/authentication#granting for more details, this field is optional
scope => ['r_basicprofile','rw_groups','r_emailaddress']
);
#redirect the user to get their permission
redirect($authorization_code_url);
# and catch an error back from linked in
if (param('error')) {
# handle the error
# if the user denied, redirect to try again...
}
=head1 SEE ALSO
http://developer.linkedin.com/documents
=head1 AUTHOR
Asaf Klibansky
discobeta@gmail.com
=head1 METHODS
=head2 authorization_code_url( { redirect_uri => '...', scope => '...'} )
=over
B<Definition:> This method is used to get the url required to authenticate the
user via LinkedIn OAuth2.
I<It assumes that you have a linkedin api key and secret which you may obtain
here https://www.linkedin.com/secure/developer.> Basically this builds the
url where you should redirect the user to obtain their permission to access
certain information (scope) on linkedin.
B<Accepts:> a hash or hashref of arguments. They must include the
necessary information to build the url.
I<redirect_url> is a url where the user should be redirect to after successfuly
authorizing (or not) and should be a method ready to capture the 'code' or
'error' parameters.'
I<scope> scope is an array of permissions that your app requires,
see http://developer.linkedin.com/documents/authentication#granting for
more details, this field is optional
B<Returns:> This will return a string containing the url where the user should
be redirect to in order to obtain their linkedin permissions.
=back
=cut
sub authorization_code_url {
my ($self, %args) = @_;
foreach(qw( redirect_uri )) {
confess "Required '$_' was not specified" unless $args{$_};
}
return "https://www.linkedin.com/uas/oauth2/authorization?response_type=code&client_id=$self->{key}&scope=".join('+',$self->{scope})."&state=".rand()."&redirect_uri=$args{redirect_uri}";
}
=back
=head2 get_access_token( { authorization_code => '...', redirect_uri => '...'} )
=over
B<Definition:> This method is used to convert the parameter 'code' that we
got from facebook after obtaining the user permissions into an access token
that we can later use to access the LinkedIn API.
B<Accepts:> a hash or hashref of arguments. They must include the
necessary information to convert the code.
I<authorization_code> is the parameter linkedin provided you with after
successfully obtaining a user's permission.
I<redirect_uri> is a url where the user should be redirect to after successfuly
authorizing (or not) and should be a method ready to capture the 'code' or
'error' parameters.'
B<Returns:> This will return a hash containing an access_token and an expires_in keys and values
=back
=cut
sub get_access_token {
my ($self, %args) = @_;
foreach(qw( authorization_code redirect_uri )) {
confess "Required '$_' was not specified" unless $args{$_};
}
my $r = $self->{class}->get("https://api.linkedin.com/uas/oauth2/accessToken?grant_type=authorization_code&code=$args{authorization_code}&redirect_uri=$args{redirect_uri}&client_id=$self->{key}&client_secret=$self->{secret}");
if (!$r->is_success){
my $j = JSON::Any->new;
my $error = $j->jsonToObj($r->content());
}
my $file = $r->content();
my $j = JSON::Any->new;
my $res = $j->jsonToObj($r->content());
return $res;
}
=head2 new( { key => '...', secret => '...', scope => ['...'] } )
=over
B<Definition:> This method is used to convert the parameter 'code' that we
got from facebook after obtaining the user permissions into an access token
that we can later use to access the LinkedIn API.
B<Accepts:> a hash or hashref of arguments. They must include the
necessary information to convert the code.
I<key> is the key linkedin provided you with when you create an app. See
https://www.linkedin.com/secure/developer for more details.
I<secret> is tha app secret that linkedin provided you with when you create
an app.
I<scope> scope is an array of permissions that your app requires,
see http://developer.linkedin.com/documents/authentication#granting for
more details, this field is optional
B<Returns:> This will create an interface to the linked in API
=back
=cut
sub new {
my ($class, $args) = @_;
my $self = bless {}, $class;
$self->{class} = LWP::UserAgent->new(
params => $args,
);
$self->{ params } = $args;
$self->{ key } = $args->{'key'};
$self->{ secret } = $args->{'secret'};
my @e;
for (my $n=0; $n <= 2; $n++) {
push @e, $args->{'scope'}[$n];
}
$self->{ scope } = join('+',@e);
return $self;
}
=head2 request( { url => '...', token => '...' } )
=over
B<Definition:> This method is used to access the linkedin api.
B<Accepts:> a hash or hashref of arguments. They must include the
necessary information to convert the code.
I<url> is the linkedin API url to access. See
https://developer.linkedin.com/docs for more details.
I<token> is a valid token that you retrieved from a successful
linkedin authentication.
B<Returns:> This will return a scalar with the results from a given url
=back
=cut
sub request {
my ($self, %args) = @_;
foreach(qw( url token )) {
confess "Required '$_' was not specified" unless $args{$_};
}
my $url;
if ($args{url} =~ /\?/) {
$url = "$args{url}&oauth2_access_token=$args{token}";
} else {
$url = "$args{url}?oauth2_access_token=$args{token}";
}
my $r = $self->{class}->get($url);
if (!$r->is_success){
my $j = XML::Hash->new();
my $error = $j->fromXMLStringtoHash($r->content());
}
my $j = JSON::Any->new;
return $j->jsonToObj( $r->content() );
}
1;