File Coverage

blib/lib/OAuth/Lite2/Client/UsernameAndPassword.pm
Criterion Covered Total %
statement 40 42 95.2
branch n/a
condition n/a
subroutine 14 14 100.0
pod n/a
total 54 56 96.4


line stmt bran cond sub pod time code
1             package OAuth::Lite2::Client::UsernameAndPassword;
2 1     1   1445 use strict;
  1         2  
  1         26  
3 1     1   4 use warnings;
  1         1  
  1         20  
4 1     1   5 use base 'Class::ErrorHandler';
  1         1  
  1         56  
5 1     1   5 use bytes ();
  1         2  
  1         14  
6              
7 1     1   87 use Carp ();
  1         2  
  1         16  
8 1     1   4 use Try::Tiny qw/try catch/;
  1         2  
  1         38  
9 1     1   5 use LWP::UserAgent;
  1         1  
  1         23  
10 1     1   4 use MIME::Base64 qw(encode_base64);
  1         2  
  1         28  
11 1     1   4 use HTTP::Request;
  1         7  
  1         19  
12 1     1   4 use HTTP::Headers;
  1         1  
  1         20  
13 1     1   3 use Params::Validate qw(HASHREF);
  1         2  
  1         39  
14 1     1   4 use OAuth::Lite2;
  1         1  
  1         19  
15 1     1   5 use OAuth::Lite2::Util qw(build_content);
  1         1  
  1         49  
16 1     1   35 use OAuth::Lite2::Client::TokenResponseParser;
  0            
  0            
17              
18             =head1 NAME
19              
20             OAuth::Lite2::Client::UsernameAndPassword - OAuth 2.0 Username And Password Profile Client
21              
22             =head1 SYNOPSIS
23              
24             my $client = OAuth::Lite2::Client::WebServer->new(
25             id => q{my_client_id},
26             secret => q{my_client_secret},
27             access_token_uri => q{http://example.org/token},
28             );
29              
30             sub get_access_token {
31             my $your_app = shift;
32              
33             my $access_token = $client->get_access_token(
34             username => $your_app->request->param("username"),
35             password => $your_app->request->param("password"),
36             scope => q{photo},
37             ) or return $your_app->error( $client->errstr );
38              
39             $your_app->store->save( access_token => $access_token->access_token );
40             $your_app->store->save( expires_at => time() + $access_token->expires_in );
41             $your_app->store->save( refresh_token => $access_token->refresh_token );
42             }
43              
44             sub refresh_access_token {
45             my $your_app = shift;
46              
47             my $access_token = $client->refresh_access_token(
48             refresh_token => $refresh_token,
49             ) or return $your_app->error( $client->errstr );
50              
51             $your_app->store->save( access_token => $access_token->access_token );
52             $your_app->store->save( expires_at => time() + $access_token->expires_in );
53             $your_app->store->save( refresh_token => $access_token->refresh_token );
54             }
55              
56             sub access_to_protected_resource {
57             my $your_app = shift;
58              
59             my $access_token = $your_app->store->get("access_token");
60             my $expires_at = $your_app->store->get("expires_at");
61             my $refresh_token = $your_app->store->get("refresh_token");
62              
63             unless ($access_token) {
64             $your_app->show_reauthorize_page();
65             return;
66             }
67              
68             if ($expires_at < time()) {
69             $your_app->refresh_access_token();
70             return;
71             }
72              
73             my $req = HTTP::Request->new( GET => q{http://example.org/photo} );
74             $req->header( Authorization => sprintf(q{OAuth %s}, $access_token) );
75             my $agent = LWP::UserAgent->new;
76             my $res = $agent->request($req);
77             ...
78             }
79              
80              
81             =head1 DESCRIPTION
82              
83             OAuth 2.0 Username And Password Profile Client.
84              
85              
86             =head2 new( %params )
87              
88             =over 4
89              
90             =item id
91              
92             Client ID
93              
94             =item secret
95              
96             Client secret
97              
98             =item access_token_uri
99              
100             token endpoint uri on auth-server.
101              
102             =item refresh_token_uri
103              
104             refresh-token endpoint uri on auth-server.
105             if you omit this, access_token_uri is used instead.
106              
107             =item agent
108              
109             user agent. if you omit this, LWP::UserAgent's object is set by default.
110             You can use your custom agent or preset-agents.
111              
112             See also
113              
114             L
115             L
116             L
117              
118             =back
119              
120             =cut
121              
122             sub new {
123             my $class = shift;
124              
125             my %args = Params::Validate::validate(@_, {
126             id => 1,
127             secret => 1,
128             # format => { optional => 1 },
129             access_token_uri => { optional => 1 },
130             refresh_token_uri => { optional => 1 },
131             agent => { optional => 1 },
132             });
133              
134             my $self = bless {
135             id => undef,
136             secret => undef,
137             access_token_uri => undef,
138             refresh_token_uri => undef,
139             last_request => undef,
140             last_response => undef,
141             %args,
142             }, $class;
143              
144             unless ($self->{agent}) {
145             $self->{agent} = LWP::UserAgent->new;
146             $self->{agent}->agent(
147             join "/", __PACKAGE__, $OAuth::Lite2::VERSION);
148             }
149              
150             # $self->{format} ||= 'json';
151             $self->{response_parser} = OAuth::Lite2::Client::TokenResponseParser->new;
152              
153             return $self;
154             }
155              
156             =head2 get_access_token( %params )
157              
158             =over 4
159              
160             =item username
161              
162             =item password
163              
164             =item scope
165              
166             =back
167              
168             =cut
169              
170             sub get_access_token {
171             my $self = shift;
172              
173             my %args = Params::Validate::validate(@_, {
174             username => 1,
175             password => 1,
176             scope => { optional => 1 },
177             uri => { optional => 1 },
178             use_basic_schema => { optional => 1 },
179             # secret_type => { optional => 1 },
180             # format => { optional => 1 },
181             });
182              
183             unless (exists $args{uri}) {
184             $args{uri} = $self->{access_token_uri}
185             || Carp::croak "uri not found";
186             }
187              
188             # $args{format} ||= $self->{format};
189              
190             my %params = (
191             grant_type => 'password',
192             username => $args{username},
193             password => $args{password},
194             # format => $args{format},
195             );
196              
197             unless ($args{use_basic_schema}){
198             $params{client_id} = $self->{id};
199             $params{client_secret} = $self->{secret};
200             }
201              
202             $params{scope} = $args{scope}
203             if $args{scope};
204              
205             # $params{secret_type} = $args{secret_type}
206             # if $args{secret_type};
207              
208             my $content = build_content(\%params);
209             my $headers = HTTP::Headers->new;
210             $headers->header("Content-Type" => q{application/x-www-form-urlencoded});
211             $headers->header("Content-Length" => bytes::length($content));
212             $headers->authorization_basic($self->{id}, $self->{secret})
213             if($args{use_basic_schema});
214             my $req = HTTP::Request->new( POST => $args{uri}, $headers, $content );
215              
216             my $res = $self->{agent}->request($req);
217             $self->{last_request} = $req;
218             $self->{last_response} = $res;
219              
220             my ($token, $errmsg);
221             try {
222             $token = $self->{response_parser}->parse($res);
223             } catch {
224             $errmsg = "$_";
225             };
226             return $token || $self->error($errmsg);
227              
228             }
229              
230             =head2 refresh_access_token( %params )
231              
232             =over 4
233              
234             =item refresh_token
235              
236             =back
237              
238             =cut
239              
240             sub refresh_access_token {
241             my $self = shift;
242              
243             my %args = Params::Validate::validate(@_, {
244             refresh_token => 1,
245             uri => { optional => 1 },
246             use_basic_schema => { optional => 1 },
247             # secret_type => { optional => 1 },
248             # format => { optional => 1 },
249             });
250              
251             unless (exists $args{uri}) {
252             $args{uri} = $self->{access_token_uri}
253             || Carp::croak "uri not found";
254             }
255              
256             # $args{format} ||= $self->{format};
257              
258             my %params = (
259             grant_type => 'refresh_token',
260             refresh_token => $args{refresh_token},
261             # format => $args{format},
262             );
263              
264             unless ($args{use_basic_schema}){
265             $params{client_id} = $self->{id};
266             $params{client_secret} = $self->{secret};
267             }
268              
269             # $params{secret_type} = $args{secret_type}
270             # if $args{secret_type};
271              
272             my $content = build_content(\%params);
273             my $headers = HTTP::Headers->new;
274             $headers->header("Content-Type" => q{application/x-www-form-urlencoded});
275             $headers->header("Content-Length" => bytes::length($content));
276             $headers->authorization_basic($self->{id}, $self->{secret})
277             if($args{use_basic_schema});
278             my $req = HTTP::Request->new( POST => $args{uri}, $headers, $content );
279              
280             my $res = $self->{agent}->request($req);
281             $self->{last_request} = $req;
282             $self->{last_response} = $res;
283              
284             my ($token, $errmsg);
285             try {
286             $token = $self->{response_parser}->parse($res);
287             } catch {
288             $errmsg = "$_";
289             };
290             return $token || $self->error($errmsg);
291             }
292              
293             =head2 last_request
294              
295             Returns a HTTP::Request object that is used
296             when you obtain or refresh access token last time internally.
297              
298             =head2 last_request
299              
300             Returns a HTTP::Response object that is used
301             when you obtain or refresh access token last time internally.
302              
303             =cut
304              
305             sub last_request { $_[0]->{last_request} }
306             sub last_response { $_[0]->{last_response} }
307              
308             =head1 AUTHOR
309              
310             Lyo Kato, Elyo.kato@gmail.comE
311              
312             =head1 COPYRIGHT AND LICENSE
313              
314             Copyright (C) 2010 by Lyo Kato
315              
316             This library is free software; you can redistribute it and/or modify
317             it under the same terms as Perl itself, either Perl version 5.8.8 or,
318             at your option, any later version of Perl 5 you may have available.
319              
320             =cut
321              
322             1;