File Coverage

blib/lib/OAuth/Lite2/Signer.pm
Criterion Covered Total %
statement 53 53 100.0
branch 3 6 50.0
condition 9 17 52.9
subroutine 13 13 100.0
pod 3 3 100.0
total 81 92 88.0


line stmt bran cond sub pod time code
1             package OAuth::Lite2::Signer;
2              
3 2     2   907 use strict;
  2         4  
  2         61  
4 2     2   9 use warnings;
  2         2  
  2         70  
5              
6 2     2   1079 use MIME::Base64 qw(encode_base64);
  2         1562  
  2         172  
7 2     2   1279 use String::Random;
  2         9654  
  2         148  
8 2     2   699 use URI;
  2         9099  
  2         74  
9 2     2   16 use Carp ();
  2         4  
  2         48  
10 2     2   697 use Params::Validate;
  2         11348  
  2         145  
11              
12 2     2   1340 use OAuth::Lite2::Signer::Algorithms;
  2         5  
  2         930  
13              
14             =head1 NAME
15              
16             OAuth::Lite2::Signer - OAuth 2.0 signature (DEPRECATED)
17              
18             =head1 SYNOPSIS
19              
20             my $signed_params = OAuth::Lite2::Signer->sign(
21             secret => q{my_token_secret},
22             algorithm => q{hmac-sha256},
23             method => q{GET},
24             url => q{http://example.org/protected/resource},
25             );
26              
27             =head1 DESCRIPTION
28              
29             DEPRECATED. This is for old version of OAuth 2.0 draft specification.
30              
31             This is for client to generate signed request,
32             or for server to verify received request.
33              
34             =head1 METHODS
35              
36             =head2 sign( %params )
37              
38             Returns the hash reference that includes parameters for OAuth 2.0 signed request.
39              
40             my $signed_params = OAuth::Lite2::Signer->sign(
41             secret => q{my_token_secret},
42             algorithm => q{hmac-sha256},
43             method => q{GET},
44             url => q{http://example.org/protected/resource},
45             );
46              
47             =over 4
48              
49             =item secret
50              
51             Access token secret.
52              
53             =item algorithm
54              
55             The algorithm what you make signature with.
56              
57             =item method
58              
59             HTTP method of the request.
60              
61             =item url
62              
63             URL of the request.
64              
65             =item debug_nonce
66              
67             Optional. If you omit this, nonce string is automatically generate random string.
68              
69             =item debug_timestamp
70              
71             Optional. If you omit this, current timestamp is set.
72              
73             =back
74              
75             =cut
76              
77             sub sign {
78 2     2 1 26 my $class = shift;
79              
80 2         87 my %args = Params::Validate::validate(@_, {
81             secret => 1,
82             algorithm => 1,
83             method => 1,
84             url => 1,
85             debug_nonce => { optional => 1 },
86             debug_timestamp => { optional => 1 },
87             });
88              
89 2         27 my $uri = URI->new($args{url});
90             Carp::croak "invalid uri scheme: " . $args{url}
91 2 50 33     8491 unless ($uri->scheme eq 'http' || $uri->scheme eq 'https');
92              
93             my $params = {
94             nonce => $args{debug_nonce} || $class->_gen_nonce(),
95             timestamp => $args{debug_timestamp} || $class->_gen_timestamp(),
96             algorithm => $args{algorithm},
97 2   66     154 };
      66        
98              
99             my $string = $class->normalize_string(%$params,
100             method => $args{method},
101             host => $uri->host,
102             port => $uri->port || 80,
103             url => $args{url},
104 2   50     17 );
105              
106             my $algorithm =
107             OAuth::Lite2::Signer::Algorithms->get_algorithm(lc $args{algorithm})
108 2 50       17 or Carp::croak "Unsupported algorithm: " . $args{algorithm};
109              
110 2         11 my $signature = encode_base64($algorithm->hash($args{secret}, $string));
111 2         5 chomp $signature;
112 2         5 $params->{signature} = $signature;
113 2         18 return $params;
114             }
115              
116             =head2 normalize_string( %params )
117              
118             Returns normalized string according to the specification.
119              
120             =over 4
121              
122             =item host
123              
124             host part of the url.
125              
126             =item port
127              
128             If you omit this, 80 is set by default.
129              
130             =item nonce
131              
132             Random string.
133              
134             =item timestamp
135              
136             unix timestamp.
137              
138             =item algorithm
139              
140             name of hmac hash algorithm.
141              
142             =item method
143              
144             HTTP method of the request.
145              
146             =item url
147              
148             URL of the request.
149              
150             =back
151              
152             =cut
153              
154             sub normalize_string {
155 4     4 1 233 my ($class, %args) = @_;
156 4   50     10 $args{port} ||= 80;
157             return join(",",
158             $args{timestamp},
159             $args{nonce},
160             $args{algorithm},
161             uc($args{method}),
162             sprintf(q{%s:%d}, $args{host}, $args{port}),
163             $args{url},
164 4         32 );
165             }
166              
167             sub _gen_nonce {
168 1     1   3 my ($class, $digit) = @_;
169 1   50     6 $digit ||= 10;
170 1         16 my $random = String::Random->new;
171 1         35 return $random->randregex( sprintf '[a-zA-Z0-9]{%d}', $digit );
172             }
173              
174             sub _gen_timestamp {
175 1     1   315 my $class = shift;
176 1         9 return time();
177             }
178              
179             =head2 verify( %params )
180              
181             Verify a signed request.
182              
183             unless ( OAuth::Lite2::Signer->verify( %params ) ) {
184             $app->error("Invalid request");
185             }
186              
187             =over 4
188              
189             =item signature
190              
191             'signature' parameter of the received request.
192              
193             =item secret
194              
195             The access token secret.
196              
197             =item algorithm
198              
199             'algorithm' parameter of the received request.
200              
201             =item method
202              
203             HTTP method of the received request.
204              
205             =item url
206              
207             URL of the received request.
208              
209             =item nonce
210              
211             'nonce' parameter of the received request.
212              
213             =item timestamp
214              
215             'timestamp' parameter of the received request.
216              
217             =back
218              
219             =cut
220              
221             sub verify {
222 2     2 1 439 my $class = shift;
223              
224 2         62 my %args = Params::Validate::validate(@_, {
225             secret => 1,
226             algorithm => 1,
227             method => 1,
228             url => 1,
229             nonce => 1,
230             timestamp => 1,
231             signature => 1,
232             });
233              
234 2         19 my $uri = URI->new($args{url});
235              
236             my $params = {
237             nonce => $args{nonce},
238             timestamp => $args{timestamp},
239             algorithm => $args{algorithm},
240 2         136 };
241              
242             my $string = $class->normalize_string(%$params,
243             method => $args{method},
244             host => $uri->host,
245             port => $uri->port || 80,
246             url => $args{url},
247 2   50     11 );
248              
249             my $algorithm =
250             OAuth::Lite2::Signer::Algorithms->get_algorithm($args{algorithm})
251 2 50       11 or return 0;
252              
253 2         6 my $signature = encode_base64($algorithm->hash($args{secret}, $string));
254 2         6 chomp $signature;
255              
256 2         18 return ($args{signature} eq $signature);
257             }
258              
259              
260             =head1 AUTHOR
261              
262             Lyo Kato, Elyo.kato@gmail.comE
263              
264             =head1 COPYRIGHT AND LICENSE
265              
266             Copyright (C) 2010 by Lyo Kato
267              
268             This library is free software; you can redistribute it and/or modify
269             it under the same terms as Perl itself, either Perl version 5.8.8 or,
270             at your option, any later version of Perl 5 you may have available.
271              
272             =cut
273              
274             1;