File Coverage

blib/lib/WWW/OAuth.pm
Criterion Covered Total %
statement 83 91 91.2
branch 19 36 52.7
condition 3 9 33.3
subroutine 16 18 88.8
pod 2 2 100.0
total 123 156 78.8


line stmt bran cond sub pod time code
1             package WWW::OAuth;
2              
3 1     1   103710 use strict;
  1         8  
  1         28  
4 1     1   5 use warnings;
  1         2  
  1         96  
5              
6             my %default_signer = (
7             'PLAINTEXT' => \&_signer_plaintext,
8             'HMAC-SHA1' => \&_signer_hmac_sha1,
9             );
10              
11             use Class::Tiny::Chained qw(client_id client_secret token token_secret), {
12             signature_method => 'HMAC-SHA1',
13 1         126 signer => sub { $default_signer{$_[0]->signature_method} },
14 1     1   499 };
  1         2511  
  1         14  
15              
16 1     1   970 use Carp 'croak';
  1         2  
  1         66  
17 1     1   8 use Digest::SHA 'hmac_sha1_base64', 'sha1_hex';
  1         2  
  1         63  
18 1     1   7 use List::Util 'all', 'pairs', 'pairgrep';
  1         2  
  1         122  
19 1     1   8 use Scalar::Util 'blessed';
  1         1  
  1         50  
20 1     1   7 use URI;
  1         2  
  1         23  
21 1     1   5 use URI::Escape 'uri_escape_utf8';
  1         2  
  1         47  
22 1     1   468 use WWW::OAuth::Util 'oauth_request';
  1         2  
  1         1007  
23              
24             our $VERSION = '1.000';
25              
26             sub authenticate {
27 1     1 1 118 my $self = shift;
28 1 50       8 my @req_args = ref $_[0] ? shift() : (shift, shift);
29 1         4 my $req = oauth_request(@req_args);
30            
31 1         18 my $auth_header = $self->authorization_header($req, @_);
32            
33 1         5 $req->header(Authorization => $auth_header);
34 1         3 return $req;
35             }
36              
37             sub authorization_header {
38 2     2 1 340 my $self = shift;
39 2 50       11 my @req_args = ref $_[0] ? shift() : (shift, shift);
40 2         8 my $req = oauth_request(@req_args);
41 2         30 my $extra_params = shift;
42            
43 2         49 my ($client_id, $client_secret, $token, $token_secret, $signature_method, $signer) =
44             ($self->client_id, $self->client_secret, $self->token, $self->token_secret, $self->signature_method, $self->signer);
45            
46 2 50 33     137 croak 'Client ID and secret are required to generate authorization header'
47             unless defined $client_id and defined $client_secret;
48            
49 2 50       10 croak "Signer is required for signature method $signature_method" unless defined $signer;
50            
51 2 50 33     10 if ($signature_method eq 'RSA-SHA1' and blessed $signer) {
52 0         0 my $signer_obj = $signer;
53 0 0       0 croak 'Signer for RSA-SHA1 must have "sign" method' unless $signer_obj->can('sign');
54 0     0   0 $signer = sub { $signer_obj->sign($_[0]) };
  0         0  
55             }
56 2 50 33     19 croak "Signer for $signature_method must be a coderef" unless !blessed $signer and ref $signer eq 'CODE';
57            
58 2         13 my %oauth_params = (
59             oauth_consumer_key => $client_id,
60             oauth_nonce => _nonce(),
61             oauth_signature_method => $signature_method,
62             oauth_timestamp => time,
63             oauth_version => '1.0',
64             );
65 2 100       9 $oauth_params{oauth_token} = $token if defined $token;
66            
67             # Extra parameters passed to authenticate()
68 2 50       8 if (defined $extra_params) {
69 2 50       11 croak 'OAuth parameters must be specified as a hashref' unless ref $extra_params eq 'HASH';
70             croak 'OAuth parameters other than "realm" must all begin with "oauth_"'
71 2 100   2   21 unless all { $_ eq 'realm' or m/^oauth_/ } keys %$extra_params;
  2 50       16  
72 2         18 %oauth_params = (%oauth_params, %$extra_params);
73             }
74            
75             # This parameter is not allowed when creating the signature
76 2         6 delete $oauth_params{oauth_signature};
77            
78             # Don't bother to generate signature base string for PLAINTEXT method
79 2 50       14 my $base_str = $signature_method eq 'PLAINTEXT' ? '' : _signature_base_string($req, \%oauth_params);
80 2         223 $oauth_params{oauth_signature} = $signer->($base_str, $client_secret, $token_secret);
81            
82 2         14 my $auth_str = join ', ', map { $_ . '="' . uri_escape_utf8($oauth_params{$_}) . '"' } sort keys %oauth_params;
  15         252  
83 2         46 return "OAuth $auth_str";
84             }
85              
86 2     2   117 sub _nonce { sha1_hex join '$', \my $dummy, time, $$, rand }
87              
88             sub _signer_plaintext {
89 0     0   0 my ($base_str, $client_secret, $token_secret) = @_;
90 0 0       0 $token_secret = '' unless defined $token_secret;
91 0         0 return uri_escape_utf8($client_secret) . '&' . uri_escape_utf8($token_secret);
92             }
93              
94             sub _signer_hmac_sha1 {
95 2     2   7 my ($base_str, $client_secret, $token_secret) = @_;
96 2 100       8 $token_secret = '' unless defined $token_secret;
97 2         5 my $signing_key = uri_escape_utf8($client_secret) . '&' . uri_escape_utf8($token_secret);
98 2         79 my $digest = hmac_sha1_base64($base_str, $signing_key);
99 2 50       32 $digest .= '='x(4 - length($digest) % 4) if length($digest) % 4; # Digest::SHA does not pad Base64 digests
100 2         8 return $digest;
101             }
102              
103             sub _signature_base_string {
104 2     2   6 my ($req, $oauth_params) = @_;
105            
106 2         5 my @all_params = @{$req->query_pairs};
  2         9  
107 2         9487 push @all_params, map { ($_ => $oauth_params->{$_}) } grep { $_ ne 'realm' } keys %$oauth_params;
  12         37  
  13         26  
108 2 50       13 push @all_params, @{$req->body_pairs} if $req->content_is_form;
  0         0  
109 2         5 my @pairs = pairs map { uri_escape_utf8 $_ } @all_params;
  24         373  
110 2 50       68 @pairs = sort { ($a->[0] cmp $b->[0]) or ($a->[1] cmp $b->[1]) } @pairs;
  18         52  
111 2         5 my $params_str = join '&', map { $_->[0] . '=' . $_->[1] } @pairs;
  12         34  
112            
113 2         48 my $base_url = URI->new($req->url);
114 2         161 $base_url->query(undef);
115 2         46 $base_url->fragment(undef);
116 2         65 return uc($req->method) . '&' . uri_escape_utf8($base_url) . '&' . uri_escape_utf8($params_str);
117             }
118              
119             1;
120              
121             =head1 NAME
122              
123             WWW::OAuth - Portable OAuth 1.0 authentication
124              
125             =head1 SYNOPSIS
126              
127             use WWW::OAuth;
128            
129             my $oauth = WWW::OAuth->new(
130             client_id => $client_id,
131             client_secret => $client_secret,
132             token => $token,
133             token_secret => $token_secret,
134             );
135            
136             # Just retrieve authorization header
137             my $auth_header = $oauth->authorization_header($http_request, { oauth_callback => $url });
138             $http_request->header(Authorization => $auth_header);
139            
140             # HTTP::Tiny
141             use HTTP::Tiny;
142             my $res = $oauth->authenticate(Basic => { method => 'GET', url => $url })
143             ->request_with(HTTP::Tiny->new);
144            
145             # HTTP::Request
146             use HTTP::Request::Common;
147             use LWP::UserAgent;
148             my $res = $oauth->authenticate(GET $url)->request_with(LWP::UserAgent->new);
149            
150             # Mojo::Message::Request
151             use Mojo::UserAgent;
152             my $tx = $ua->build_tx(get => $url);
153             $tx = $oauth->authenticate($tx->req)->request_with(Mojo::UserAgent->new);
154            
155             =head1 DESCRIPTION
156              
157             L implements OAuth 1.0 request authentication according to
158             L (sometimes referred to as OAuth
159             1.0A). It does not implement the user agent requests needed for the complete
160             OAuth 1.0 authorization flow; it only prepares and signs requests, leaving the
161             rest up to your application. It can authenticate requests for
162             L, L, L, and can be extended to
163             operate on other types of requests.
164              
165             Some user agents can be configured to automatically authenticate each request
166             with a L object.
167              
168             # LWP::UserAgent
169             my $ua = LWP::UserAgent->new;
170             $ua->add_handler(request_prepare => sub { $oauth->authenticate($_[0]) });
171            
172             # Mojo::UserAgent
173             my $ua = Mojo::UserAgent->new;
174             $ua->on(start => sub { $oauth->authenticate($_[1]->req) });
175              
176             =head1 RETRIEVING ACCESS TOKENS
177              
178             The process of retrieving access tokens and token secrets for authorization on
179             behalf of a user may differ among various APIs, but it follows this general
180             format (error checking is left as an exercise to the reader):
181              
182             use WWW::OAuth;
183             use WWW::OAuth::Util 'form_urldecode';
184             use HTTP::Tiny;
185             my $ua = HTTP::Tiny->new;
186             my $oauth = WWW::OAuth->new(
187             client_id => $client_id,
188             client_secret => $client_secret,
189             );
190            
191             # Request token request
192             my $res = $oauth->authenticate({ method => 'POST', url => $request_token_url },
193             { oauth_callback => $callback_url })->request_with($ua);
194             my %res_data = @{form_urldecode $res->{content}};
195             my ($request_token, $request_secret) = @res_data{'oauth_token','oauth_token_secret'};
196            
197             Now, the returned request token must be used to construct a URL for the user to
198             go to and authorize your application. The exact method differs by API. The user
199             will usually be redirected to the C<$callback_url> passed earlier after
200             authorizing, with a verifier token that can be used to retrieve the access
201             token and secret.
202            
203             # Access token request
204             $oauth->token($request_token);
205             $oauth->token_secret($request_secret);
206             my $res = $oauth->authenticate({ method => 'POST', url => $access_token_url },
207             { oauth_verifier => $verifier_token })->request_with($ua);
208             my %res_data = @{form_urldecode $res->{content}};
209             my ($access_token, $access_secret) = @res_data{'oauth_token','oauth_token_secret'};
210            
211             Finally, the access token and secret can now be stored and used to authorize
212             your application on behalf of this user.
213              
214             $oauth->token($access_token);
215             $oauth->token_secret($access_secret);
216              
217             =head1 ATTRIBUTES
218              
219             L implements the following attributes.
220              
221             =head2 client_id
222              
223             my $client_id = $oauth->client_id;
224             $oauth = $oauth->client_id($client_id);
225              
226             Client ID used to identify application (sometimes called an API key or consumer
227             key). Required for all requests.
228              
229             =head2 client_secret
230              
231             my $client_secret = $oauth->client_secret;
232             $oauth = $oauth->client_secret($client_secret);
233              
234             Client secret used to authenticate application (sometimes called an API secret
235             or consumer secret). Required for all requests.
236              
237             =head2 token
238              
239             my $token = $oauth->token;
240             $oauth = $oauth->token($token);
241              
242             Request or access token used to identify resource owner. Leave undefined for
243             temporary credentials requests (request token requests).
244              
245             =head2 token_secret
246              
247             my $token_secret = $oauth->token_secret;
248             $oauth = $oauth->token_secret($token_secret);
249              
250             Request or access token secret used to authenticate on behalf of resource
251             owner. Leave undefined for temporary credentials requests (request token
252             requests).
253              
254             =head2 signature_method
255              
256             my $method = $oauth->signature_method;
257             $oauth = $oauth->signature_method($method);
258              
259             Signature method, can be C, C<HMAC-SHA1>, C<RSA-SHA1>, or a custom </td> </tr> <tr> <td class="h" > <a name="260">260</a> </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td class="s"> signature method. For C<RSA-SHA1> or custom signature methods, a L</"signer"> </td> </tr> <tr> <td class="h" > <a name="261">261</a> </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td class="s"> must be provided. Defaults to C<HMAC-SHA1>. </td> </tr> <tr> <td class="h" > <a name="262">262</a> </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td class="s"> &nbsp; </td> </tr> <tr> <td class="h" > <a name="263">263</a> </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td class="s"> =head2 signer </td> </tr> <tr> <td class="h" > <a name="264">264</a> </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td class="s"> &nbsp; </td> </tr> <tr> <td class="h" > <a name="265">265</a> </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td class="s"> my $signer = $oauth->signer; </td> </tr> <tr> <td class="h" > <a name="266">266</a> </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td class="s"> $oauth = $oauth->signer(sub { </td> </tr> <tr> <td class="h" > <a name="267">267</a> </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td class="s"> my ($base_str, $client_secret, $token_secret) = @_; </td> </tr> <tr> <td class="h" > <a name="268">268</a> </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td class="s"> ... </td> </tr> <tr> <td class="h" > <a name="269">269</a> </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td class="s"> return $signature; </td> </tr> <tr> <td class="h" > <a name="270">270</a> </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td class="s"> }); </td> </tr> <tr> <td class="h" > <a name="271">271</a> </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td class="s"> &nbsp; </td> </tr> <tr> <td class="h" > <a name="272">272</a> </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td class="s"> Coderef which implements the L</"signature_method">. A default signer is </td> </tr> <tr> <td class="h" > <a name="273">273</a> </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td class="s"> provided for signature methods C<PLAINTEXT> and C<HMAC-SHA1>; this attribute is </td> </tr> <tr> <td class="h" > <a name="274">274</a> </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td class="s"> required for other signature methods. For signature method C<RSA-SHA1>, this </td> </tr> <tr> <td class="h" > <a name="275">275</a> </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td class="s"> attribute may also be an object which has a C<sign> method like </td> </tr> <tr> <td class="h" > <a name="276">276</a> </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td class="s"> L<Crypt::OpenSSL::RSA>. </td> </tr> <tr> <td class="h" > <a name="277">277</a> </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td class="s"> &nbsp; </td> </tr> <tr> <td class="h" > <a name="278">278</a> </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td class="s"> The signer is passed the computed signature base string, the client secret, and </td> </tr> <tr> <td class="h" > <a name="279">279</a> </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td class="s"> (if present) the token secret, and must return the signature string. </td> </tr> <tr> <td class="h" > <a name="280">280</a> </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td class="s"> &nbsp; </td> </tr> <tr> <td class="h" > <a name="281">281</a> </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td class="s"> =head1 METHODS </td> </tr> <tr> <td class="h" > <a name="282">282</a> </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td class="s"> &nbsp; </td> </tr> <tr> <td class="h" > <a name="283">283</a> </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td class="s"> L<WWW::OAuth> implements the following methods. </td> </tr> <tr> <td class="h" > <a name="284">284</a> </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td class="s"> &nbsp; </td> </tr> <tr> <td class="h" > <a name="285">285</a> </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td class="s"> =head2 authenticate </td> </tr> <tr> <td class="h" > <a name="286">286</a> </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td class="s"> &nbsp; </td> </tr> <tr> <td class="h" > <a name="287">287</a> </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td class="s"> $container = $oauth->authenticate($container, \%oauth_params); </td> </tr> <tr> <td class="h" > <a name="288">288</a> </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td class="s"> my $container = $oauth->authenticate($http_request, \%oauth_params); </td> </tr> <tr> <td class="h" > <a name="289">289</a> </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td class="s"> my $container = $oauth->authenticate(Basic => { method => 'GET', url => $url }, \%oauth_params); </td> </tr> <tr> <td class="h" > <a name="290">290</a> </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td class="s"> &nbsp; </td> </tr> <tr> <td class="h" > <a name="291">291</a> </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td class="s"> Wraps the HTTP request in a container with L<WWW::OAuth::Util/"oauth_request">, </td> </tr> <tr> <td class="h" > <a name="292">292</a> </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td class="s"> then sets the Authorization header using L</"authorization_header"> to sign the </td> </tr> <tr> <td class="h" > <a name="293">293</a> </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td class="s"> request for OAuth 1.0. An optional hashref of OAuth parameters will be passed </td> </tr> <tr> <td class="h" > <a name="294">294</a> </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td class="s"> through to L</"authorization_header">. Returns the container object. </td> </tr> <tr> <td class="h" > <a name="295">295</a> </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td class="s"> &nbsp; </td> </tr> <tr> <td class="h" > <a name="296">296</a> </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td class="s"> =head2 authorization_header </td> </tr> <tr> <td class="h" > <a name="297">297</a> </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td class="s"> &nbsp; </td> </tr> <tr> <td class="h" > <a name="298">298</a> </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td class="s"> my $auth_header = $oauth->authorization_header($container, \%oauth_params); </td> </tr> <tr> <td class="h" > <a name="299">299</a> </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td class="s"> my $auth_header = $oauth->authorization_header($http_request, \%oauth_params); </td> </tr> <tr> <td class="h" > <a name="300">300</a> </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td class="s"> my $auth_header = $oauth->authorization_header(Basic => { method => 'GET', url => $url }, \%oauth_params); </td> </tr> <tr> <td class="h" > <a name="301">301</a> </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td class="s"> &nbsp; </td> </tr> <tr> <td class="h" > <a name="302">302</a> </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td class="s"> Forms an OAuth 1.0 signed Authorization header for the passed request. As in </td> </tr> <tr> <td class="h" > <a name="303">303</a> </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td class="s"> L</"authenticate">, the request may be specified in any form accepted by </td> </tr> <tr> <td class="h" > <a name="304">304</a> </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td class="s"> L<WWW::OAuth::Util/"oauth_request">. OAuth protocol parameters (starting with </td> </tr> <tr> <td class="h" > <a name="305">305</a> </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td class="s"> C<oauth_> or the special parameter C<realm>) may be optionally specified in a </td> </tr> <tr> <td class="h" > <a name="306">306</a> </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td class="s"> hashref and will override any generated protocol parameters of the same name </td> </tr> <tr> <td class="h" > <a name="307">307</a> </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td class="s"> (they should not be present in the request URL or body parameters). Returns the </td> </tr> <tr> <td class="h" > <a name="308">308</a> </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td class="s"> signed header value. </td> </tr> <tr> <td class="h" > <a name="309">309</a> </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td class="s"> &nbsp; </td> </tr> <tr> <td class="h" > <a name="310">310</a> </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td class="s"> =head1 HTTP REQUEST CONTAINERS </td> </tr> <tr> <td class="h" > <a name="311">311</a> </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td class="s"> &nbsp; </td> </tr> <tr> <td class="h" > <a name="312">312</a> </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td class="s"> Request containers provide a unified interface for L</"authenticate"> to parse </td> </tr> <tr> <td class="h" > <a name="313">313</a> </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td class="s"> and update HTTP requests. They must perform the L<Role::Tiny> role </td> </tr> <tr> <td class="h" > <a name="314">314</a> </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td class="s"> L<WWW::OAuth::Request>. Custom container classes can be instantiated </td> </tr> <tr> <td class="h" > <a name="315">315</a> </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td class="s"> directly or via L<WWW::OAuth::Util/"oauth_request">. </td> </tr> <tr> <td class="h" > <a name="316">316</a> </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td class="s"> &nbsp; </td> </tr> <tr> <td class="h" > <a name="317">317</a> </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td class="s"> =head2 Basic </td> </tr> <tr> <td class="h" > <a name="318">318</a> </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td class="s"> &nbsp; </td> </tr> <tr> <td class="h" > <a name="319">319</a> </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td class="s"> L<WWW::OAuth::Request::Basic> contains the request attributes directly, for </td> </tr> <tr> <td class="h" > <a name="320">320</a> </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td class="s"> user agents such as L<HTTP::Tiny> that do not use request objects. </td> </tr> <tr> <td class="h" > <a name="321">321</a> </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td class="s"> &nbsp; </td> </tr> <tr> <td class="h" > <a name="322">322</a> </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td class="s"> =head2 HTTP_Request </td> </tr> <tr> <td class="h" > <a name="323">323</a> </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td class="s"> &nbsp; </td> </tr> <tr> <td class="h" > <a name="324">324</a> </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td class="s"> L<WWW::OAuth::Request::HTTP_Request> wraps a L<HTTP::Request> object, which </td> </tr> <tr> <td class="h" > <a name="325">325</a> </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td class="s"> is compatible with several user agents including L<LWP::UserAgent>, </td> </tr> <tr> <td class="h" > <a name="326">326</a> </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td class="s"> L<HTTP::Thin>, and L<Net::Async::HTTP>. </td> </tr> <tr> <td class="h" > <a name="327">327</a> </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td class="s"> &nbsp; </td> </tr> <tr> <td class="h" > <a name="328">328</a> </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td class="s"> =head2 Mojo </td> </tr> <tr> <td class="h" > <a name="329">329</a> </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td class="s"> &nbsp; </td> </tr> <tr> <td class="h" > <a name="330">330</a> </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td class="s"> L<WWW::OAuth::Request::Mojo> wraps a L<Mojo::Message::Request> object, </td> </tr> <tr> <td class="h" > <a name="331">331</a> </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td class="s"> which is used by L<Mojo::UserAgent> via L<Mojo::Transaction>. </td> </tr> <tr> <td class="h" > <a name="332">332</a> </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td class="s"> &nbsp; </td> </tr> <tr> <td class="h" > <a name="333">333</a> </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td class="s"> =head1 BUGS </td> </tr> <tr> <td class="h" > <a name="334">334</a> </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td class="s"> &nbsp; </td> </tr> <tr> <td class="h" > <a name="335">335</a> </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td class="s"> Report any issues on the public bugtracker. </td> </tr> <tr> <td class="h" > <a name="336">336</a> </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td class="s"> &nbsp; </td> </tr> <tr> <td class="h" > <a name="337">337</a> </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td class="s"> =head1 AUTHOR </td> </tr> <tr> <td class="h" > <a name="338">338</a> </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td class="s"> &nbsp; </td> </tr> <tr> <td class="h" > <a name="339">339</a> </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td class="s"> Dan Book <dbook@cpan.org> </td> </tr> <tr> <td class="h" > <a name="340">340</a> </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td class="s"> &nbsp; </td> </tr> <tr> <td class="h" > <a name="341">341</a> </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td class="s"> =head1 COPYRIGHT AND LICENSE </td> </tr> <tr> <td class="h" > <a name="342">342</a> </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td class="s"> &nbsp; </td> </tr> <tr> <td class="h" > <a name="343">343</a> </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td class="s"> This software is Copyright (c) 2015 by Dan Book. </td> </tr> <tr> <td class="h" > <a name="344">344</a> </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td class="s"> &nbsp; </td> </tr> <tr> <td class="h" > <a name="345">345</a> </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td class="s"> This is free software, licensed under: </td> </tr> <tr> <td class="h" > <a name="346">346</a> </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td class="s"> &nbsp; </td> </tr> <tr> <td class="h" > <a name="347">347</a> </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td class="s"> The Artistic License 2.0 (GPL Compatible) </td> </tr> <tr> <td class="h" > <a name="348">348</a> </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td class="s"> &nbsp; </td> </tr> <tr> <td class="h" > <a name="349">349</a> </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td class="s"> =head1 SEE ALSO </td> </tr> <tr> <td class="h" > <a name="350">350</a> </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td class="s"> &nbsp; </td> </tr> <tr> <td class="h" > <a name="351">351</a> </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td > &nbsp; </td> <td class="s"> L<Net::OAuth>, L<Mojolicious::Plugin::OAuth2> </td> </tr> </table> </body> </html>