| Net-Twitter documentation | Contained in the Net-Twitter distribution. |
Net::Twitter::Role::OAuth - Net::Twitter role that provides OAuth instead of Basic Authentication
use Net::Twitter;
my $nt = Net::Twitter->new(
traits => ['API::REST', 'OAuth'],
consumer_key => "YOUR-CONSUMER-KEY",
consumer_secret => "YOUR-CONSUMER-SECRET",
);
# Do some Authentication work. See EXAMPLES
my $tweets = $nt->friends_timeline;
my $res = $nt->update({ status => "I CAN HAZ OAUTH!" });
Net::Twitter::Role::OAuth is a Net::Twitter role that provides OAuth authentication instead of the default Basic Authentication.
Note that this client only works with APIs that are compatible to OAuth authentication.
Beginning with version 3.02, it is necessary for web applications to pass the
callback parameter to get_authorization_url. In the absence of a
callback parameter, when the user authorizes the application a PIN number is
displayed rather than redirecting the user back to your site.
See the examples directory in this distribution for working examples of both
desktop and web applications.
Here's how to authorize users as a desktop app mode:
use Net::Twitter;
my $nt = Net::Twitter->new(
traits => ['API::REST', 'OAuth'],
consumer_key => "YOUR-CONSUMER-KEY",
consumer_secret => "YOUR-CONSUMER-SECRET",
);
# You'll save the token and secret in cookie, config file or session database
my($access_token, $access_token_secret) = restore_tokens();
if ($access_token && $access_token_secret) {
$nt->access_token($access_token);
$nt->access_token_secret($access_token_secret);
}
unless ( $nt->authorized ) {
# The client is not yet authorized: Do it now
print "Authorize this app at ", $nt->get_authorization_url, " and enter the PIN#\n";
my $pin = <STDIN>; # wait for input
chomp $pin;
my($access_token, $access_token_secret, $user_id, $screen_name) = $nt->request_access_token(verifier => $pin);
save_tokens($access_token, $access_token_secret); # if necessary
}
# Everything's ready
In a web application mode, you need to save the oauth_token and oauth_token_secret somewhere when you redirect the user to the OAuth authorization URL.
sub twitter_authorize : Local {
my($self, $c) = @_;
my $nt = Net::Twitter->new(traits => [qw/API::REST OAuth/], %param);
my $url = $nt->get_authorization_url(callback => $callbackurl);
$c->response->cookies->{oauth} = {
value => {
token => $nt->request_token,
token_secret => $nt->request_token_secret,
},
};
$c->response->redirect($url);
}
And when the user returns back, you'll reset those request token and secret to upgrade the request token to access token.
sub twitter_auth_callback : Local {
my($self, $c) = @_;
my %cookie = $c->request->cookies->{oauth}->value;
my $verifier = $c->req->params->{oauth_verifier};
my $nt = Net::Twitter->new(traits => [qw/API::REST OAuth/], %param);
$nt->request_token($cookie{token});
$nt->request_token_secret($cookie{token_secret});
my($access_token, $access_token_secret, $user_id, $screen_name)
= $nt->request_access_token(verifier => $verifier);
# Save $access_token and $access_token_secret in the database associated with $c->user
}
Later on, you can retrieve and reset those access token and secret before calling any Twitter API methods.
sub make_tweet : Local {
my($self, $c) = @_;
my($access_token, $access_token_secret) = ...;
my $nt = Net::Twitter->new(traits => [qw/API::REST OAuth/], %param);
$nt->access_token($access_token);
$nt->access_token_secret($access_token_secret);
# Now you can call any Net::Twitter API methods on $nt
my $status = $c->req->param('status');
my $res = $nt->update({ status => $status });
}
Whether the client has the necessary credentials to be authorized.
Note that the credentials may be wrong and so the request may fail.
Request the access token, access token secret, user id and screen name for
this user. You must pass the PIN# (for desktop applications) or the
oauth_verifier value, provided as a parameter to the oauth callback
(for web applications) as $verifier.
The user must have authorized this app at the url given by get_authorization_url first.
Returns the access_token, access_token_secret, user_id, and screen_name in a list. Also sets them internally so that after calling this method, you can immediately call API methods requiring authentication.
Exchanges the $username and $password for access tokens. This method has
the same return value as request_access_token: access_token, access_token_secret,
user_id, and screen_name in a list. Also, like request_access_token, it sets
the access_token and access_secret, internally, so you can immediately call API
methods requiring authentication.
Get the URL used to authorize the user. Returns a URI object. For web
applications, pass your applications callback URL as the callback parameter.
No arguments are required for desktop applications (callback defaults to
oob, out-of-band).
Get the URL used to authenticate the user with "Sign in with Twitter"
authentication flow. Returns a URI object. For web applications, pass your
applications callback URL as the callback parameter. No arguments are
required for desktop applications (callback defaults to oob, out-of-band).
Get or set the access token.
Get or set the access token secret.
Get or set the request token.
Get or set the request token secret.
Prior versions used Net::OAuth::Simple. This method provided access to the
contained Net::OAuth::Simple object. Beginning with Net::Twitter 3.00, the
OAuth methods were delegated to Net::OAuth::Simple. They have since made first
class methods. Net::Simple::OAuth is no longer used. A warning will be
displayed when accessing OAuth methods via the <oauth> method. The oauth
method will be removed in a future release.
Use authorized instead.
Use get_authorization_url instead.
$nt->oauth_token($access_token, $access_token_secret);
Use access_token and access_token_seccret instead:
$nt->access_token($access_token); $nt->access_token_secret($access_token_secret);
This module was originally authored by Tatsuhiko Miyagawa as
Net::Twitter::OAuth, a subclass of the Net::Twitter 2.x. It was
refactored into a Moose Role for use in Net::Twitter 3.0 and above by Marc
Mims. Many thanks to Tatsuhiko for the original work on both code and
documentation.
Marc Mims <marc@questright.com>
Tatsuhiko Miyagawa <miyagawa@bulknews.net>
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
Net::Twitter, Net::Twitter::OAuth::Simple, Net::OAuth::Simple
| Net-Twitter documentation | Contained in the Net-Twitter distribution. |
package Net::Twitter::Role::OAuth; use Moose::Role; use HTTP::Request::Common; use Carp; use URI; use Digest::SHA; use List::Util qw/first/; requires qw/_add_authorization_header ua/; use namespace::autoclean; use Net::OAuth; $Net::OAuth::PROTOCOL_VERSION = Net::OAuth::PROTOCOL_VERSION_1_0A; # flatten oauth_urls with defaults around BUILDARGS => sub { my $orig = shift; my $class = shift; my $args = $class->$orig(@_); my $oauth_urls = delete $args->{oauth_urls} || { request_token_url => "https://api.twitter.com/oauth/request_token", authentication_url => "https://api.twitter.com/oauth/authenticate", authorization_url => "https://api.twitter.com/oauth/authorize", access_token_url => "https://api.twitter.com/oauth/access_token", xauth_url => "https://api.twitter.com/oauth/access_token", }; return { %$oauth_urls, %$args }; }; has consumer_key => ( isa => 'Str', is => 'ro', required => 1 ); has consumer_secret => ( isa => 'Str', is => 'ro', required => 1 ); # url attributes for my $attribute ( qw/authentication_url authorization_url request_token_url access_token_url xauth_url/ ) { has $attribute => ( isa => 'Str', is => 'rw', required => 1, # inflate urls to URI objects when read reader => { $attribute => sub { URI->new(shift->{$attribute}) } }, ); } # token attributes for my $attribute ( qw/access_token access_token_secret request_token request_token_secret/ ) { has $attribute => ( isa => 'Str', is => 'rw', clearer => "clear_$attribute", predicate => "has_$attribute", ); } # simple check to see if we have access tokens; does not check to see if they are valid sub authorized { my $self = shift; return defined $self->has_access_token && $self->has_access_token_secret; } # get the athorization or authentication url sub _get_auth_url { my ($self, $which_url, %params ) = @_; $self->_request_request_token(%params); my $uri = $self->$which_url; $uri->query_form(oauth_token => $self->request_token); return $uri; } # get the authentication URL from Twitter sub get_authentication_url { return shift->_get_auth_url(authentication_url => @_) } # get the authorization URL from Twitter sub get_authorization_url { return shift->_get_auth_url(authorization_url => @_) } # common portion of all oauth requests sub _make_oauth_request { my ($self, $type, %params) = @_; my $class = $type =~ s/^\+// ? $type : Net::OAuth->request($type); my $request = $class->new( version => '1.0', consumer_key => $self->{consumer_key}, consumer_secret => $self->{consumer_secret}, request_method => 'GET', signature_method => 'HMAC-SHA1', timestamp => time, nonce => Digest::SHA::sha1_base64(time . $$ . rand), %params, ); $request->sign; return $request; } # called by get_authorization_url to obtain request tokens sub _request_request_token { my ($self, %params) = @_; my $uri = $self->request_token_url; $params{callback} ||= 'oob'; my $request = $self->_make_oauth_request( 'request token', request_url => $uri, %params, ); my $msg = HTTP::Request->new(GET => $uri); $msg->header(authorization => $request->to_authorization_header); my $res = $self->_send_request($msg); croak "GET $uri failed: ".$res->status_line unless $res->is_success; # reuse $uri to extract parameters from the response content $uri->query($res->content); my %res_param = $uri->query_form; $self->request_token($res_param{oauth_token}); $self->request_token_secret($res_param{oauth_token_secret}); } # exchange request tokens for access tokens; call with (verifier => $verifier) sub request_access_token { my ($self, %params ) = @_; my $uri = $self->access_token_url; my $request = $self->_make_oauth_request( 'access token', request_url => $uri, token => $self->request_token, token_secret => $self->request_token_secret, %params, # verifier => $verifier ); my $msg = HTTP::Request->new(GET => $uri); $msg->header(authorization => $request->to_authorization_header); my $res = $self->_send_request($msg); croak "GET $uri failed: ".$res->status_line unless $res->is_success; # discard request tokens, they're no longer valid $self->clear_request_token; $self->clear_request_token_secret; # reuse $uri to extract parameters from content $uri->query($res->content); my %res_param = $uri->query_form; return ( $self->access_token($res_param{oauth_token}), $self->access_token_secret($res_param{oauth_token_secret}), $res_param{user_id}, $res_param{screen_name}, ); } around _prepare_request => sub { my $orig = shift; my ($self, $http_method, $uri, $args, $authenticate) = @_; delete $args->{source}; $orig->(@_); }; override _add_authorization_header => sub { my ( $self, $msg, $args ) = @_; return unless $self->authorized; my $is_multipart = grep { ref } %$args; local $Net::OAuth::SKIP_UTF8_DOUBLE_ENCODE_CHECK = 1; my $request = $self->_make_oauth_request( 'protected resource', request_url => $msg->uri, request_method => $msg->method, token => $self->access_token, token_secret => $self->access_token_secret, extra_params => $is_multipart ? {} : $args, ); $msg->header(authorization => $request->to_authorization_header); }; sub xauth { my ( $self, $username, $password ) = @_; my @args = ( x_auth_username => $username, x_auth_password => $password, x_auth_mode => 'client_auth', ); my $uri = $self->xauth_url; my $request = $self->_make_oauth_request( 'XauthAccessToken', request_url => $uri, request_method => 'POST', @args, ); my $res = $self->ua->request( POST $uri, \@args, Authorization => $request->to_authorization_header); die "POST $uri failed: ".$res->status_line unless $res->is_success; # reuse $uri to extract parameters from content $uri->query($res->content); my %res_param = $uri->query_form; return ( $self->access_token($res_param{oauth_token}), $self->access_token_secret($res_param{oauth_token_secret}), $res_param{user_id}, $res_param{screen_name}, ); } # shortcuts defined in early releases # DEPRECATED sub oauth_token { my($self, @tokens) = @_; carp "DEPRECATED: use access_token and access_token_secret instead"; $self->access_token($tokens[0]); $self->access_token_secret($tokens[1]); return @tokens; } sub is_authorized { carp "DEPRECATED: use authorized instead"; shift->authorized(@_) } sub oauth_authorization_url { carp "DEPRECATED: use get_authorization_url instead"; shift->get_authorization_url(@_) } sub oauth { carp "DEPRECATED: call this method on Net::Twitter itself, rather than through the oauth accessor"; shift } 1; __END__