File Coverage

lib/Google/RestApi/Auth/OAuth2Client.pm
Criterion Covered Total %
statement 27 74 36.4
branch 0 14 0.0
condition 1 2 50.0
subroutine 7 14 50.0
pod 1 7 14.2
total 36 111 32.4


line stmt bran cond sub pod time code
1              
2             our $VERSION = '1.0.2';
3              
4             use Google::RestApi::Setup;
5 1     1   624  
  1         2  
  1         12  
6             # this was taken from Net::Google::DataAPI::Auth::OAuth2 and had a moose-ectomy. this will
7             # get rid of warnings about switching to Moo instead of Moose::Any.
8             #
9             # NOTE NOTE NOTE: to generate a config file and token file for use by this module, see:
10             # bin/google_restapi_oauth_token_creator in this package.
11              
12             use Net::OAuth2::Client ();
13 1     1   19667 use Net::OAuth2::Profile::WebServer ();
  1         68386  
  1         24  
14 1     1   6 use Storable qw( retrieve );
  1         3  
  1         18  
15 1     1   5 use URI ();
  1         3  
  1         46  
16 1     1   5  
  1         4  
  1         15  
17             use parent 'Google::RestApi::Auth';
18 1     1   5  
  1         2  
  1         5  
19             my $class = shift;
20              
21 141     141 1 412 my %p = @_;
22             # order is important, resolve the overall config file first.
23 141         833 resolve_config_file_path(\%p, 'config_file');
24             resolve_config_file_path(\%p, 'token_file');
25 141         1050  
26 141         497 my $self = merge_config_file(%p);
27             state $check = compile_named(
28 140         794 config_dir => ReadableDir, { optional => 1 },
29 140         345 config_file => ReadableFile, { optional => 1 },
30             token_file => ReadableFile, { optional => 1 },
31             client_id => Str,
32             client_secret => Str,
33             scope => ArrayRef[Str], { optional => 1 },
34             state => Str, { default => '' },
35             redirect_uri => Str, { default => 'urn:ietf:wg:oauth:2.0:oob' },
36             site => Str, { default => 'https://accounts.google.com' },
37             authorize_path => Str, { default => '/o/oauth2/auth' },
38             access_token_path => Str, { default => '/o/oauth2/token' },
39             userinfo_url => Str, { default => 'https://www.googleapis.com/oauth2/v1/userinfo' },
40             );
41             $self = $check->(%$self);
42              
43 140         4182 $self->{scope} ||= [ # when added to default above, check silently fails to compile.
44             'https://www.googleapis.com/auth/userinfo.profile',
45             'https://www.googleapis.com/auth/userinfo.email',
46 140   50     13487 ];
47              
48             return bless $self, $class;
49             }
50 140         796  
51             my $self = shift;
52             return $self->{headers} if $self->{headers};
53              
54 0     0     $self->access_token(
55 0 0         refresh_token => retrieve($self->{token_file})->{refresh_token},
56             auto_refresh => 1,
57             );
58             $self->refresh_token();
59 0           my $access_token = $self->access_token()->access_token();
60             INFO("Successfully attained access token");
61 0            
62 0           $self->{headers} = [ Authorization => "Bearer $access_token" ];
63 0            
64             return $self->{headers};
65 0           }
66              
67 0           my $self = shift;
68             my $server = $self->oauth2_webserver();
69             return $server->authorize(
70             scope => join(' ', @{ $self->{scope} }), @_
71 0     0 0   );
72 0           }
73              
74 0           my $self = shift;
  0            
75              
76             if (scalar @_ == 1) {
77             state $check = compile(Str);
78             my ($code) = $check->(@_);
79 0     0 0   my $server = $self->oauth2_webserver();
80             $self->{access_token} = $server->get_access_token($code);
81 0 0         DEBUG("Created access token:\n", Dump($self->{access_token}));
    0          
82 0           } elsif (@_) {
83 0           state $check = compile_named(
84 0           refresh_token => Str,
85 0           auto_refresh => Bool,
86 0           );
87             my $p = $check->(@_);
88 0           $p->{profile} = $self->oauth2_webserver();
89             # DEBUG("Building access token from:\n", Dump($p)); # shows secret in the logs.
90             $self->{access_token} = Net::OAuth2::AccessToken->new(%$p);
91             }
92 0            
93 0           return $self->{access_token};
94             }
95 0            
96             my ($self, $refresh_token) = @_;
97             DEBUG("About to refresh token");
98 0           my $server = $self->oauth2_webserver();
99             $server->update_access_token($self->access_token());
100             return $self->access_token()->refresh();
101             }
102 0     0 0    
103 0           my $self = shift;
104 0           if (!$self->{oauth2_client}) {
105 0           DEBUG("Creating OAuth2 client");
106 0           $self->{oauth2_client} = Net::OAuth2::Client->new(
107             $self->{client_id},
108             $self->{client_secret},
109             site => $self->{site},
110 0     0 0   authorize_path => $self->{authorize_path},
111 0 0         access_token_path => $self->{access_token_path},
112 0           refresh_token_path => $self->{access_token_path},
113             );
114             }
115             return $self->{oauth2_client};
116             }
117              
118             my $self = shift;
119             if (!$self->{oauth2_webserver}) {
120 0           DEBUG("Creating OAuth2 web server");
121             my $client = $self->oauth2_client();
122 0           $self->{oauth2_webserver} = $client->web_server(
123             redirect_uri => $self->{redirect_uri},
124             state => $self->{state},
125             );
126 0     0 0   }
127 0 0         return $self->{oauth2_webserver};
128 0           }
129 0            
130             # not currently used
131             my $self = shift;
132             my $token = $self->access_token();
133 0           my $url = URI->new($self->{userinfo_url});
134             my $res = $token->get($url);
135 0           $res->is_success or LOGDIE 'userinfo request failed: ' . $res->as_string;
136             my %res_params = $self->oauth2_webserver()->params_from_response($res)
137             or LOGDIE 'params_from_response for userinfo response failed';
138             return \%res_params;
139             }
140 0     0 0    
141 0           1;
142 0            
143 0            
144 0 0         =head1 NAME
145 0 0          
146             Google::RestApi::Auth::OAuth2Client - OAuth2 support for Google Rest APIs
147 0            
148             =head1 SYNOPSIS
149              
150             use Google::RestApi::Auth::OAuth2Client;
151              
152             my $oauth2 = Google::RestApi::Auth::OAuth2Client->new(
153             client_id => 'xxxxxxxxxxxxxxxxxxxxxx.apps.googleusercontent.com',
154             client_secret => 'mys3cr33333333333333t',
155             scope => ['http://spreadsheets.google.com/feeds/'],
156              
157             # with web apps, redirect_uri is needed:
158             # redirect_uri => 'http://your_app.sample.com/callback',
159             );
160             my $url = $oauth2->authorize_url();
161              
162             # you can add optional parameters:
163             my $url = $oauth2->authorize_url(
164             access_type => 'offline',
165             approval_prompt => 'force',
166             );
167              
168             # generate an access token from the code returned from Google:
169             my $token = $oauth2->access_token($code);
170            
171             =head1 DESCRIPTION
172              
173             Google::RestApi::Auth::OAuth2Client interacts with google OAuth 2.0 service
174             and creates the 'Authorization' header for use in Furl or LWP::UserAgent.
175              
176             To generate a config file and token file for use by this moudle, see:
177             bin/google_restapi_oauth_token_creator in this pacakage.
178              
179             This was copied from Net::Google::DataAPI::Auth::OAuth2 and modified
180             to fit this framework. The other framework was dated and produced
181             constant warnings to upgrade from Moose to Moo. I removed Moose since I
182             didn't use Moose anywhere else in this framework.
183              
184             =head1 ATTRIBUTES
185              
186             =head2 sub new
187              
188             =over 2
189              
190             config_file: Optional YAML configuration file that can specify any
191             or all of the following args:
192             client_id: The OAuth2 client id supplied by Google.
193             client_secret: The OAuth2 client secret supplied by Google.
194             token_file: The file path to the previously saved token (see OAUTH2
195             SETUP below). If a config_file is passed, the dirname of the config
196             file is tried to resolve the token_file (same directory) if the
197             directory portion is omitted.
198              
199             You can specify any of the arguments in the optional YAML config file.
200             Any passed in arguments will override what is in the config file.
201              
202             =item * client_id
203              
204             client id. You can get it at L<https://code.google.com/apis/console#access>.
205              
206             =item * client_secret
207              
208             The client secret paired with the client id.
209              
210             =item * scope
211              
212             URL identifying the service(s) to be accessed. You can see the list
213             of the urls to use at: L<http://code.google.com/intl/en-US/apis/gdata/faq.html#AuthScopes>
214              
215             =item * redirect_url
216              
217             OAuth2 redirect url. 'urn:ietf:wg:oauth:2.0:oob' will be used if you don't specify it.
218              
219             =back
220              
221             See L<https://developers.google.com/accounts/docs/OAuth2> for details.
222              
223             =head1 OAUTH2 SETUP
224              
225             This class depends on first creating an OAuth2 token session file
226             that you point to via the 'token_file' config param passed via 'new'.
227             See bin/google_restapi_oauth_token_creator and follow the instructions to
228             save your token file.
229              
230             =head1 AUTHOR
231              
232             Robin Murray E<lt>mvsjes@cpan.ork<gt>, copied and modifed from Net::Google::DataAPI::Auth::OAuth2.
233              
234             =head1 SEE ALSO
235              
236             L<OAuth2>
237              
238             L<Google::DataAPI::Auth::OAuth2>
239              
240             L<https://developers.google.com/accounts/docs/OAuth2>
241              
242             =head1 LICENSE
243              
244             This library is free software; you can redistribute it and/or modify
245             it under the same terms as Perl itself.