File: oauth.t

package info (click to toggle)
libwww-oauth-perl 1.003-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 228 kB
  • sloc: perl: 480; makefile: 2
file content (145 lines) | stat: -rw-r--r-- 8,391 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
use strict;
use warnings;
use Test::More;
use Data::Dumper 'Dumper';
use Digest::SHA 'hmac_sha1_base64';
use JSON::PP 'decode_json';
use URI;
use URI::Escape 'uri_escape_utf8', 'uri_unescape';
use WWW::OAuth;
use WWW::OAuth::Util 'form_urldecode', 'form_urlencode', 'oauth_request';

my $api_key = $ENV{TWITTER_API_KEY};
my $api_secret = $ENV{TWITTER_API_SECRET};
my $token = $ENV{TWITTER_ACCESS_TOKEN};
my $token_secret = $ENV{TWITTER_ACCESS_SECRET};

my $oauth_base_url = 'https://api.twitter.com/oauth/';
my $api_base_url = 'https://api.twitter.com/1.1/';

my $test_online;
if ($ENV{AUTHOR_TESTING} and defined $api_key and defined $api_secret and defined $token and defined $token_secret) {
	note 'Running online test for Twitter OAuth 1.0';
	$test_online = 1;
	require HTTP::Tiny;
	HTTP::Tiny->VERSION('0.014');
} else {
	note 'Running offline test for Twitter OAuth 1.0; set AUTHOR_TESTING and TWITTER_API_KEY/TWITTER_API_SECRET/TWITTER_ACCESS_TOKEN/TWITTER_ACCESS_SECRET for online test';
	$api_key = 'foo';
	$api_secret = 'bar';
	$token = 'baz';
	$token_secret = 'ban';
}

# OAuth token request
my $oauth_request_url = $oauth_base_url . 'request_token';
my $oauth_request = _request(POST => $oauth_request_url);

my $auth = WWW::OAuth->new(client_id => $api_key, client_secret => $api_secret);
my $auth_header = $auth->authorization_header($oauth_request, { oauth_callback => 'oob' });
like $auth_header, qr/^OAuth oauth_/, 'Formed Authorization header';
$oauth_request->header(Authorization => $auth_header);
is $auth_header, $oauth_request->header('Authorization'), 'Authorization header has been set';

my $oauth_params = _parse_oauth_header($auth_header);
is $oauth_params->{oauth_consumer_key}, $api_key, 'oauth_consumer_key is set to API key';
ok defined($oauth_params->{oauth_nonce}), 'oauth_nonce is set';
is $oauth_params->{oauth_signature_method}, 'HMAC-SHA1', 'oauth_signature_method is set to HMAC-SHA1';
ok defined($oauth_params->{oauth_timestamp}), 'oauth_timestamp is set';
is $oauth_params->{oauth_version}, '1.0', 'oauth_version is set to 1.0';
ok defined($oauth_params->{oauth_signature}), 'oauth_signature is set';
is $oauth_params->{oauth_callback}, 'oob', 'oauth_callback is set to "oob"';
ok !defined($oauth_params->{oauth_token}), 'oauth_token is not set';

my $test_signature = _test_signature('POST', $oauth_request_url, $oauth_params, $api_secret);
is $test_signature, $oauth_params->{oauth_signature}, 'signature formed correctly';

my $response;
if ($test_online) {
	my $res = $oauth_request->request_with(HTTP::Tiny->new);
	ok $res->{success}, 'OAuth request successful' or diag Dumper $res;
	$response = $res->{content};
} else {
	$response = q{oauth_token=aaaaaaaaaaaaaaaaaaaaaaaaaaa&oauth_token_secret=bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb&oauth_callback_confirmed=true};
}

my %response_params = @{form_urldecode($response)};
is $response_params{oauth_callback_confirmed}, 'true', 'OAuth callback was confirmed';
ok defined(my $request_token = $response_params{oauth_token}), 'got request token';
ok defined(my $request_secret = $response_params{oauth_token_secret}), 'got request secret';

# Verify credentials request
my $verify_url = $api_base_url . 'account/verify_credentials.json';
my $verify_request = _request(GET => $verify_url);

$auth->token($token);
$auth->token_secret($token_secret);
$auth->authenticate($verify_request, { realm => 'foo' });
$auth_header = $verify_request->header('Authorization');
ok defined $auth_header, 'Authorization header has been set';

$oauth_params = _parse_oauth_header($auth_header);
is $oauth_params->{oauth_consumer_key}, $api_key, 'oauth_consumer_key is set to API key';
ok defined($oauth_params->{oauth_nonce}), 'oauth_nonce is set';
is $oauth_params->{oauth_signature_method}, 'HMAC-SHA1', 'oauth_signature_method is set to HMAC-SHA1';
ok defined($oauth_params->{oauth_timestamp}), 'oauth_timestamp is set';
is $oauth_params->{oauth_version}, '1.0', 'oauth_version is set to 1.0';
ok defined($oauth_params->{oauth_signature}), 'oauth_signature is set';
is $oauth_params->{oauth_token}, $token, 'oauth_token is set to API access token';
is $oauth_params->{realm}, 'foo', 'realm is set';

$test_signature = _test_signature('GET', $verify_url, $oauth_params, $api_secret, $token_secret);
is $test_signature, $oauth_params->{oauth_signature}, 'signature formed correctly';

if ($test_online) {
	my $res = $verify_request->request_with(HTTP::Tiny->new);
	ok $res->{success}, 'OAuth request successful' or diag Dumper $res;
	$response = $res->{content};
} else {
	$response = <<'JSON_RESPONSE';
{"id":36885345,"id_str":"36885345","name":"Grinnz","screen_name":"TheGrinnz","location":"CT","description":"nerrrrrd","url":"http:\/\/t.co\/IomLjiiycH","entities":{"url":{"urls":[{"url":"http:\/\/t.co\/IomLjiiycH","expanded_url":"http:\/\/grinnz.net","display_url":"grinnz.net","indices":[0,22]}]},"description":{"urls":[]}},"protected":false,"followers_count":73,"friends_count":74,"listed_count":3,"created_at":"Fri May 01 04:45:52 +0000 2009","favourites_count":0,"utc_offset":-18000,"time_zone":"Quito","geo_enabled":true,"verified":false,"statuses_count":365,"lang":"en","status":{"created_at":"Thu Aug 14 03:05:35 +0000 2014","id":499753673501990912,"id_str":"499753673501990912","text":"@GermanFatass vpssd down, at least one irc server still up","source":"\u003ca href=\"http:\/\/twitter.com\" rel=\"nofollow\"\u003eTwitter Web Client\u003c\/a\u003e","truncated":false,"in_reply_to_status_id":499752682178224128,"in_reply_to_status_id_str":"499752682178224128","in_reply_to_user_id":66307969,"in_reply_to_user_id_str":"66307969","in_reply_to_screen_name":"GermanFatass","geo":null,"coordinates":null,"place":null,"contributors":null,"retweet_count":0,"favorite_count":0,"entities":{"hashtags":[],"symbols":[],"user_mentions":[{"screen_name":"GermanFatass","name":"John ","id":66307969,"id_str":"66307969","indices":[0,13]}],"urls":[]},"favorited":false,"retweeted":false,"lang":"en"},"contributors_enabled":false,"is_translator":false,"is_translation_enabled":false,"profile_background_color":"C6E2EE","profile_background_image_url":"http:\/\/abs.twimg.com\/images\/themes\/theme2\/bg.gif","profile_background_image_url_https":"https:\/\/abs.twimg.com\/images\/themes\/theme2\/bg.gif","profile_background_tile":false,"profile_image_url":"http:\/\/pbs.twimg.com\/profile_images\/221712898\/tux_redhat80_normal.png","profile_image_url_https":"https:\/\/pbs.twimg.com\/profile_images\/221712898\/tux_redhat80_normal.png","profile_link_color":"1F98C7","profile_sidebar_border_color":"C6E2EE","profile_sidebar_fill_color":"DAECF4","profile_text_color":"663B12","profile_use_background_image":true,"has_extended_profile":false,"default_profile":false,"default_profile_image":false,"following":false,"follow_request_sent":false,"notifications":false}
JSON_RESPONSE
}

my $response_data = decode_json $response;
ok defined($response_data->{id_str}), 'Twitter ID returned in response';

sub _request {
	my ($method, $url, $params) = @_;
	my %req = (method => $method, url => $url);
	if (defined $params) {
		if ($method eq 'GET' or $method eq 'HEAD') {
			my $uri = URI->new($url);
			$uri->query_form($params);
			$req{url} = $uri->as_string;
		} else {
			$req{content} = form_urlencode($params);
			$req{headers}{'content-type'} = 'application/x-www-form-urlencoded';
		}
	}
	return oauth_request(Basic => \%req);
}

sub _parse_oauth_header {
	my $auth_header = shift;
	return {} unless defined $auth_header;
	my %oauth_params;
	while ($auth_header =~ m/(\w+)="(.+?)"/g) {
		$oauth_params{$1} = uri_unescape $2;
	}
	return \%oauth_params;
}

sub _test_signature {
	my ($method, $request_url, $oauth_params, $client_secret, $token_secret) = @_;
	my $params_str = join '&', map { $_ . '=' . uri_escape_utf8($oauth_params->{$_}) } grep { defined $oauth_params->{$_} }
		qw(oauth_callback oauth_consumer_key oauth_nonce oauth_signature_method oauth_timestamp oauth_token oauth_version);
	my $base_str = uc($method) . '&' . uri_escape_utf8($request_url) . '&' . uri_escape_utf8($params_str);
	my $signing_key = uri_escape_utf8($client_secret) . '&';
	$signing_key .= uri_escape_utf8($token_secret) if defined $token_secret;
	my $test_signature = hmac_sha1_base64($base_str, $signing_key);
	$test_signature .= '='x(4 - length($test_signature) % 4) if length($test_signature) % 4;
	return $test_signature;
}

done_testing;