File Coverage

blib/lib/Dancer2/Plugin/Auth/OAuth/Provider.pm
Criterion Covered Total %
statement 101 104 97.1
branch 18 22 81.8
condition 15 27 55.5
subroutine 22 23 95.6
pod 0 8 0.0
total 156 184 84.7


line stmt bran cond sub pod time code
1              
2             use strict;
3 1     1   403 use warnings;
  1         2  
  1         25  
4 1     1   4  
  1         2  
  1         20  
5             use DateTime;
6 1     1   753 use Digest::MD5 qw(md5_hex);
  1         426483  
  1         42  
7 1     1   10 use HTTP::Request::Common;
  1         2  
  1         57  
8 1     1   8 use JSON::MaybeXS;
  1         3  
  1         58  
9 1     1   5 use LWP::UserAgent;
  1         2  
  1         49  
10 1     1   8 use Net::OAuth;
  1         2  
  1         27  
11 1     1   449 use Scalar::Util qw( blessed );
  1         552  
  1         30  
12 1     1   6 use URI::Query;
  1         3  
  1         56  
13 1     1   1253 use Hash::Merge;
  1         1894  
  1         53  
14 1     1   398  
  1         3731  
  1         1135  
15             my ($class, $settings) = @_;
16             my $self = bless {
17 12     12 0 195955 settings => $settings,
18 12         37 }, $class;
19              
20             my $merge = Hash::Merge->new('LEFT_PRECEDENT');
21             my $config = $merge->merge($self->{settings}{providers}{$self->_provider}||{}, $self->config);
22 12         62  
23 12   100     837 $self->{settings}{providers}{$self->_provider} = $config;
24              
25 12         817 my $protocol_version = $self->provider_settings->{version} || 2;
26             $self->{protocol_version} = $protocol_version;
27 12   100     58  
28 12         25 $self->{ua} ||= LWP::UserAgent->new();
29             $self->{ua}->env_proxy; # c'mon make this default behaviour already!
30 12   33     79  
31 12         2377 return $self;
32             }
33 12         5918  
34             # Provider:: module should override this if needed/wanted
35             my $self = shift;
36              
37             return 1;
38 0     0 0 0 }
39              
40 0         0 return (split '::', blessed($_[0]))[-1];
41             }
42              
43             my ($self, $obj) = @_;
44 105     105   793  
45             while( my ($k, $v) = each %{$obj} ) {
46             $obj->{$k} = $self->_stringify_json_booleans( $v )
47             if( ref($v) && ref($v) eq 'HASH' );
48 7     7   655 $obj->{$k} = "$v"
49             if( blessed( $v ) );
50 7         10 }
  75         171  
51 68 100 100     118  
52             return $obj;
53 68 100       163 }
54              
55             my $self = shift;
56              
57 7         15 return (
58             consumer_key => $self->provider_settings->{tokens}{consumer_key},
59             consumer_secret => $self->provider_settings->{tokens}{consumer_secret},
60             signature_method => $self->provider_settings->{signature_method} || 'HMAC-SHA1',
61 3     3   10965 timestamp => DateTime->now->epoch,
62             nonce => md5_hex(time),
63             );
64             }
65              
66 3   50     8 my $self = shift;
67              
68             # construct the callback url
69             return sprintf "%s%s/%s/callback",
70             $self->settings->{base},
71             $self->settings->{prefix},
72             lc($self->_provider)
73 12     12   67 ;
74             }
75              
76              
77             return $_[0]->{ua};
78             }
79 12         21  
80             return $_[0]->{protocol_version};
81             }
82              
83             return $_[0]->{settings};
84             }
85 3     3 0 14  
86             my $self = shift;
87             return $self->{settings}{providers}{$self->_provider};
88             }
89 13     13 0 39  
90             my ( $self, $base ) = @_;
91              
92             $self->settings->{base} ||= $base;
93 36     36 0 89  
94             if( $self->protocol_version < 2 ) {
95             # oAuth 1.0 / 1.0a
96             $Net::OAuth::PROTOCOL_VERSION = $self->protocol_version;
97 63     63 0 878 my $request = Net::OAuth->request("request token")->new(
98 63         128 $self->_default_args_v1,
99             request_method => 'POST',
100             request_url => $self->provider_settings->{urls}{request_token_url},
101             callback => $self->_callback_url,
102 6     6 0 1821 );
103             $request->sign;
104 6   66     23  
105             my $res = $self->ua->request(POST $request->to_url);
106 6 100       42 if ($res->is_success) {
107             my $response = Net::OAuth->response('request token')->from_post_body($res->content);
108 1         3 my $uri = URI->new( $self->provider_settings->{urls}{authorize_url} );
109             $uri->query_form( oauth_callback => $self->_callback_url, oauth_token => $response->token );
110              
111             return $uri->as_string;
112             } else {
113 1         8 return $self->settings->{error_url} || '/';
114             }
115 1         1138 } else {
116             # oAuth 2 and up
117 1         3743 my $uri = URI->new( $self->provider_settings->{urls}{authorize_url} );
118 1 50       1361 my %query = (
119 1         11 client_id => $self->provider_settings->{tokens}{client_id},
120 1         2668 redirect_uri => $self->_callback_url,
121 1         62 %{ $self->provider_settings->{query_params}{authorize} || {} },
122             );
123 1         130 $uri->query_form( %query );
124             return $uri->as_string;
125 0   0     0 }
126             }
127              
128             my ($self, $request, $session) = @_;
129 5         13  
130             # this code may be called before authentication_url()
131             # (multiple processes), so we must make sure the base
132             # setting isn't undef
133 5 100       292 $self->settings->{base} ||= $request->uri_base;
  5         11  
134              
135 5         23 my $provider = lc $self->_provider;
136 5         635 my $session_data = $session->read('oauth') || {};
137              
138             if( $self->protocol_version < 2 ) {
139             return $self->settings->{error_url} || '/' unless( defined($request->param('oauth_token')) );
140             my $at_request = Net::OAuth->request( 'access token' )->new(
141 6     6 0 10152 $self->_default_args_v1,
142             token => $request->param('oauth_token'),
143             token_secret => '',
144             verifier => $request->param('oauth_verifier'),
145              
146 6   33     16 request_url => $self->provider_settings->{urls}{access_token_url},
147             request_method => 'POST'
148 6         12 );
149 6   50     16 $at_request->sign;
150              
151 6 100       151 my $ua_response = $self->ua->request(
152 1 50 0     5 POST $at_request->to_url, [
153             'oauth_verifier', $request->param('oauth_verifier')
154             ]
155             );
156              
157             if( $ua_response->is_success ) {
158             my $response = Net::OAuth->response( 'access token' )->from_post_body( $ua_response->content );
159             $session_data->{$provider} = {
160 1         17 access_token => $response->token,
161             access_token_secret => $response->token_secret,
162 1         811 extra => $response->extra_params,
163             };
164 1         1112 }
165             } else {
166             my $uri = URI->new( $self->provider_settings->{urls}{access_token_url} );
167             my %args = (
168             client_id => $self->provider_settings->{tokens}{client_id},
169             client_secret => $self->provider_settings->{tokens}{client_secret},
170 1 50       1498 code => $request->param('code'),
171 1         15 grant_type => 'authorization_code',
172 1         1261 redirect_uri => $self->_callback_url,
173             );
174             my $response = $self->{ua}->request( POST $uri->as_string, \%args );
175              
176             if( $response->is_success ) {
177             my $content_type = $response->header('Content-Type');
178             my $params = {};
179 5         11 if( $content_type =~ m/json/ || $content_type =~ m/javascript/ ) {
180             $params = decode_json( $response->content );
181             } else {
182             $params = URI::Query->new( $response->content )->hash;
183 5         297 }
184              
185             for my $key (qw/access_token email user_id expires expires_in id_token token_type id issued_at scope instance_url refresh_token signature x_mailru_vid error/) {
186             $session_data->{$provider}{$key} = $params->{$key}
187 5         16 if $params->{$key};
188             }
189 5 50       3887 }
190 5         42 }
191 5         177 $session->write('oauth', $session_data);
192 5 100 66     30  
193 2         5 # fetch user info or whatever we want to do at this point
194             $self->post_process( $session );
195 3         8 }
196              
197             1;