File Coverage

blib/lib/OAuth/Cmdline.pm
Criterion Covered Total %
statement 33 123 26.8
branch 0 28 0.0
condition 0 3 0.0
subroutine 11 26 42.3
pod 3 15 20.0
total 47 195 24.1


line stmt bran cond sub pod time code
1             ###########################################
2             package OAuth::Cmdline;
3             ###########################################
4 1     1   4 use strict;
  1         1  
  1         21  
5 1     1   3 use warnings;
  1         1  
  1         16  
6 1     1   404 use URI;
  1         3440  
  1         22  
7 1     1   348 use YAML qw( DumpFile LoadFile );
  1         4480  
  1         45  
8 1     1   417 use HTTP::Request::Common;
  1         11983  
  1         50  
9 1     1   5 use URI;
  1         1  
  1         14  
10 1     1   540 use LWP::UserAgent;
  1         14234  
  1         32  
11 1     1   681 use Log::Log4perl qw(:easy);
  1         32591  
  1         4  
12 1     1   365 use JSON qw( from_json );
  1         1  
  1         6  
13 1     1   118 use MIME::Base64;
  1         2  
  1         46  
14 1     1   492 use Moo;
  1         8993  
  1         4  
15              
16             our $VERSION = "0.05";
17              
18             has client_id => ( is => "rw" );
19             has client_secret => ( is => "rw" );
20             has local_uri => (
21             is => "rw",
22             default => "http://localhost:8082",
23             );
24             has homedir => (
25             is => "ro",
26             default => glob '~',
27             );
28             has login_uri => ( is => "rw" );
29             has site => ( is => "rw" );
30             has scope => ( is => "rw" );
31             has token_uri => ( is => "rw" );
32             has redir_uri => ( is => "rw" );
33             has access_type => ( is => "rw" );
34             has raise_error => ( is => "rw" );
35              
36             ###########################################
37             sub redirect_uri {
38             ###########################################
39 0     0 0   my( $self ) = @_;
40              
41 0           return $self->local_uri . "/callback";
42             }
43              
44             ###########################################
45             sub cache_file_path {
46             ###########################################
47 0     0 0   my( $self ) = @_;
48              
49             # creds saved ~/.[site].yml
50 0           return $self->homedir . "/." .
51             $self->site . ".yml";
52             }
53              
54             ###########################################
55             sub full_login_uri {
56             ###########################################
57 0     0 0   my( $self ) = @_;
58              
59 0           my $full_login_uri = URI->new( $self->login_uri );
60              
61 0 0         $full_login_uri->query_form (
    0          
62             client_id => $self->client_id(),
63             response_type => "code",
64             (defined $self->redirect_uri() ?
65             ( redirect_uri => $self->redirect_uri() ) :
66             ()
67             ),
68             scope => $self->scope(),
69             ($self->access_type() ?
70             (access_type => $self->access_type()) : ()),
71             );
72              
73 0           DEBUG "full login uri: $full_login_uri";
74 0           return $full_login_uri;
75             }
76              
77             ###########################################
78             sub access_token {
79             ###########################################
80 0     0 0   my( $self ) = @_;
81              
82 0 0         if( $self->token_expired() ) {
83 0 0         $self->token_refresh() or LOGDIE "Token refresh failed";
84             }
85              
86 0           my $cache = $self->cache_read();
87 0           return $cache->{ access_token };
88             }
89              
90             ###########################################
91             sub authorization_headers {
92             ###########################################
93 0     0 1   my( $self ) = @_;
94              
95             return (
96 0           'Authorization' =>
97             'Bearer ' . $self->access_token
98             );
99             }
100              
101             ###########################################
102             sub token_refresh_authorization_header {
103             ###########################################
104 0     0 0   my( $self ) = @_;
105              
106 0           return ();
107             }
108              
109             ###########################################
110             sub token_refresh {
111             ###########################################
112 0     0 0   my( $self ) = @_;
113              
114 0           DEBUG "Refreshing access token";
115              
116 0           my $cache = $self->cache_read();
117              
118 0           $self->token_uri( $cache->{ token_uri } );
119              
120             my $req = &HTTP::Request::Common::POST(
121             $self->token_uri,
122             {
123             refresh_token => $cache->{ refresh_token },
124             client_id => $cache->{ client_id },
125             client_secret => $cache->{ client_secret },
126 0           grant_type => 'refresh_token',
127             },
128             $self->token_refresh_authorization_header(),
129             );
130              
131 0           my $ua = LWP::UserAgent->new();
132 0           my $resp = $ua->request($req);
133              
134 0 0         if( $resp->is_success() ) {
135 0           my $data =
136             from_json( $resp->content() );
137              
138 0           DEBUG "Token refreshed, will expire in $data->{ expires_in } seconds";
139              
140 0           $cache->{ access_token } = $data->{ access_token };
141 0           $cache->{ expires } = $data->{ expires_in } + time();
142              
143 0           $self->cache_write( $cache );
144 0           return 1;
145             }
146              
147 0           ERROR "Token refresh failed: ", $resp->status_line();
148 0           return undef;
149             }
150              
151             ###########################################
152             sub token_expired {
153             ###########################################
154 0     0 1   my( $self ) = @_;
155              
156 0           my $cache = $self->cache_read();
157              
158 0           my $time_remaining = $cache->{ expires } - time();
159              
160 0 0         if( $time_remaining < 300 ) {
161 0 0         if( $time_remaining < 0 ) {
162 0           DEBUG "Token expired ", -$time_remaining, " seconds ago";
163             } else {
164 0           DEBUG "Token will expire in $time_remaining seconds";
165             }
166              
167 0           DEBUG "Token needs to be refreshed.";
168 0           return 1;
169             }
170              
171 0           return 0;
172             }
173              
174             ###########################################
175             sub token_expire {
176             ###########################################
177 0     0 1   my( $self ) = @_;
178              
179 0           my $cache = $self->cache_read();
180              
181 0           $cache->{ expires } = time() - 1;
182 0           $self->cache_write( $cache );
183             }
184              
185             ###########################################
186             sub cache_read {
187             ###########################################
188 0     0 0   my( $self ) = @_;
189              
190 0 0         if( ! -f $self->cache_file_path ) {
191 0           LOGDIE "Cache file ", $self->cache_file_path, " not found. ",
192             "See GETTING STARTED in the docs for how to get started.";
193             }
194              
195 0           return LoadFile $self->cache_file_path;
196             }
197              
198             ###########################################
199             sub cache_write {
200             ###########################################
201 0     0 0   my( $self, $cache ) = @_;
202              
203 0           my $old_umask = umask 0177;
204              
205 0           DumpFile $self->cache_file_path, $cache;
206              
207 0           umask $old_umask;
208 0           return 1;
209             }
210              
211             ###########################################
212             sub tokens_get {
213             ###########################################
214 0     0 0   my( $self, $code ) = @_;
215              
216 0           my $req = &HTTP::Request::Common::POST(
217             $self->token_uri,
218             [
219             code => $code,
220             client_id => $self->client_id,
221             client_secret => $self->client_secret,
222             redirect_uri => $self->redirect_uri,
223             grant_type => 'authorization_code',
224             ]
225             );
226              
227 0           my $ua = LWP::UserAgent->new();
228 0           my $resp = $ua->request($req);
229              
230 0 0         if( $resp->is_success() ) {
231 0           my $json = $resp->content();
232 0           DEBUG "Received: [$json]",
233             my $data = from_json( $json );
234              
235             return ( $data->{ access_token },
236             $data->{ refresh_token },
237 0           $data->{ expires_in } );
238             }
239              
240 0           LOGDIE $resp->status_line();
241 0           return undef;
242             }
243              
244             ###########################################
245             sub tokens_collect {
246             ###########################################
247 0     0 0   my( $self, $code ) = @_;
248              
249 0           my( $access_token, $refresh_token,
250             $expires_in ) = $self->tokens_get( $code );
251              
252 0           my $cache = {
253             access_token => $access_token,
254             refresh_token => $refresh_token,
255             client_id => $self->client_id,
256             client_secret => $self->client_secret,
257             expires => time() + $expires_in,
258             token_uri => $self->token_uri,
259             };
260              
261 0           $self->cache_write( $cache );
262             }
263              
264             ###########################################
265             sub http_get {
266             ###########################################
267 0     0 0   my( $self, $url, $query ) = @_;
268              
269 0           my $ua = LWP::UserAgent->new();
270              
271 0           my $uri = URI->new( $url );
272 0 0         $uri->query_form( @$query ) if defined $query;
273              
274 0           my $resp = $ua->get( $uri,
275             $self->authorization_headers, @$query );
276              
277 0 0         if( $resp->is_error ) {
278 0 0         if( $self->raise_error ) {
279 0           die $resp->message;
280             }
281 0           return undef;
282             }
283              
284 0           return $resp->decoded_content;
285             }
286              
287             ###########################################
288             sub client_init_conf_check {
289             ###########################################
290 0     0 0   my( $self, $url ) = @_;
291              
292 0           my $conf = { };
293 0 0         if( -f $self->cache_file_path ) {
294 0           $conf = $self->cache_read();
295             }
296              
297 0 0 0       if( !exists $conf->{ client_id } or
298             !exists $conf->{ client_secret } ) {
299 0           die "You need to register your application on " .
300             "$url and add the client_id and " .
301             "client_secret entries to " . $self->cache_file_path . "\n";
302             }
303            
304 0           $self->client_id( $conf->{ client_id } );
305 0           $self->client_secret( $conf->{ client_secret } );
306              
307 0           return 1;
308             }
309              
310             1;
311              
312             __END__