Net-OAuth-0.32/0000755000175000017500000000000015240175731011037 5ustar rrrrNet-OAuth-0.32/README0000644000175000017500000000357215236366473011740 0ustar rrrrNet-OAuth OAuth 1.0 for Perl, implementing RFC 5849. http://tools.ietf.org/html/rfc5849 INSTALLATION $ cpanm Net::OAuth USAGE Net::OAuth::Client is the high-level API. It is framework-agnostic: supply your own redirect and session handling. use Net::OAuth::Client; my $client = Net::OAuth::Client->new( $consumer_key, $consumer_secret, site => 'https://provider.example/', request_token_path => '/oauth/request_token', authorize_path => '/oauth/authorize', access_token_path => '/oauth/access_token', callback => 'https://you.example/auth/callback', session => \&session, ); # 1. Send the user to the provider to authorize. # (use whatever your framework provides to redirect) $client->authorize_url; # 2. They return to your callback with oauth_token and oauth_verifier. my $access_token = $client->get_access_token($token, $verifier); # 3. Use the access token to fetch a protected resource. my $response = $access_token->get('/profile'); die $response->status_line unless $response->is_success; print $response->decoded_content; The session argument is a coderef used to stash the request token secret between steps 1 and 2; called with a key it reads, with a key and value it writes. Net::OAuth itself is the low-level interface for reading and writing OAuth messages directly. perldoc Net::OAuth perldoc Net::OAuth::Client AUTHOR Originally by Keith Grennan Currently maintained by Robert Rothenberg LICENSE AND COPYRIGHT Copyright 2007-2012, 2024-2025 Keith Grennan This program is free software; you can redistribute it and/or modify it under the terms of either: the GNU General Public License as published by the Free Software Foundation; or the Artistic License. See http://dev.perl.org/licenses/ for more information. Net-OAuth-0.32/CONTRIBUTING.md0000644000175000017500000001606415236366473013311 0ustar rrrr# HOW TO CONTRIBUTE Thank you for considering contributing to Net-OAuth. There are multiple ways that you can help with this project. Any contributions (bug reports, feature requests, security issues, or patches) must cite any tools which generated the reports or code, and any software that the code is based on. Contributions must not include content generated by large language models (LLMs) or other probabilistic tools, including but not limited to Anthropic, Copilot or ChatGPT. This policy covers code, documentation, pull requests, issues, comments, and any other contributions to this project. See [AI Contributions](#ai-contributions) below for more more details. ## Report Bugs and Submit Feature Requests Please report any bugs or feature requests on the bugtracker website [https://github.com/keeth/Net-OAuth/issues](https://github.com/keeth/Net-OAuth/issues). When submitting a bug or request, please include a test-file or a patch to an existing test-file that illustrates the bug or desired feature. Using the bugtracker is preferable to emailing the maintainer, as identified in the AUTHOR section of the POD. But if you are unable to use the bugtracker, then you may email the current maintainer, Robert Rothenberg . ### Reporting Security Vulnerabilities Security issues should not be reported on the bugtracker website. Please see `SECURITY.md` for instructions how to report security vulnerabilities. ## Submitting Patches The source code is available via GitHub at [https://github.com/keeth/Net-OAuth](https://github.com/keeth/Net-OAuth). Patches should be based on a recent fork of the `main` branch. This distribution is managed with [Dist::Zilla](https://dzil.org/). This means that many of the usual files you might expect are not in the repository, but are generated at release time, as is much of the documentation. Some generated files are kept in the repository as a convenience (e.g. `Makefile.PL` or `cpanfile`). Generally, **you do not need Dist::Zilla to contribute patches**. You do need Dist::Zilla to create a tarball. See [Installing and using Dist::Zilla](#installing-and-using-distzilla) below for guidance. ### Getting dependencies If you have [App::cpanminus](https://metacpan.org/pod/App::cpanminus) 1.6 or later installed, you can use `cpanm` to satisfy dependencies like this: $ cpanm --installdeps . Otherwise, look for either a `Makefile.PL` or `cpanfile` file for a list of dependencies to satisfy. ### Running tests You can run tests directly using the `prove` tool: $ prove -l $ prove -lv t/some_test_file.t For most cases, `prove` is entirely sufficient to test any patches you have. ### Code style and tidying Please try to match any existing coding style. If there is a `.perltidyrc` file, please install [Perl::Tidy](https://metacpan.org/pod/Perl::Tidy) and use `perltidy` before submitting patches. If there is a `tidyall.ini` file, you can also install [Code::TidyAll](https://metacpan.org/pod/Code::TidyAll) and run `tidyall` on a file or `tidyall -a` to tidy all files. ### Patching documentation Much of the documentation POD is generated at release time. Some is generated boilerplate; other documentation is built from [Pod::Weaver](https://metacpan.org/pod/Pod::Weaver) pseudo-POD directives in the source like '=attr', '=method' or '=export'. If you would like to submit a documentation edit, please limit yourself to the documentation you see. If you see typos or documentation issues in the generated docs, please email the maintainers or open a bug ticket instead of patching. ### Where to send patches and pull requests If you found this distribution on GitHub, sending a pull-request is the best way to contribute. If a pull-request isn't possible, a bug ticket with a patch file is the next best option. As a last resort, an email to the maintainer is acceptable. ## Installing and using Dist::Zilla Dist::Zilla is not required for contributing, but if you'd like to learn more, this section will get you up to speed. Dist::Zilla is a very powerful authoring tool, optimised for maintaining a large number of distributions with a high degree of automation, but it has a large dependency chain, a bit of a learning curve and requires a number of author-specific plugins. To install it from CPAN, I recommend one of the following approaches for the quickest installation: # using CPAN.pm, but bypassing non-functional pod tests $ cpan TAP::Harness::Restricted $ PERL_MM_USE_DEFAULT=1 HARNESS_CLASS=TAP::Harness::Restricted cpan Dist::Zilla # using cpanm, bypassing *all* tests $ cpanm -n Dist::Zilla In either case, it's probably going to take several minutes. Go for a walk, go get a cup of your favourite beverage, take a bathroom break, or whatever. When you get back, Dist::Zilla should be ready for you. Then you need to install any plugins specific to this distribution: $ cpan `dzil authordeps` $ dzil authordeps | cpanm Once installed, here are some dzil commands you might try: $ dzil build $ dzil test You can learn more about Dist::Zilla at . ## AI Contributions Contributions must not include content generated by large language models (LLMs) or other probabilistic tools, including but not limited to Anthropic, Copilot or ChatGPT. This policy covers code, documentation, pull requests, issues, comments, and any other contributions to this project. This restriction is based on several concerns: ### Maintainer burden These tools make it easy to generate large amounts of plausible-looking bug reports or code that the contributor does not understand and cannot explain. Instead, the burden of understanding is placed on the maintainers. ### Correctness and security These tools generate code based on probabilities of symbols in their models. There is no semantic model about what the code does. There is no guarantee that it is correct, and no indication of what security implications it may have. ### Copyright issues These tools may use models that are trained on copyrighted content, both accidentally and intentionally, and their output often includes that content verbatim, without attribution. Since the legality of this is uncertain, these contributions may violate the licenses of copyrighted works. Using these tools also requires training their models on the source code from this project, and it makes it likely that code from this project will be used in other projects in ways that violate this project's license. ### Ethical issues These tools require an unreasonable amount of energy and water to build and operate, and they are being used to undermine labour and justify layoffs. These are harms that the maintainers of this project do not want to perpetuate, even if only indirectly. # Credits This file was adapted from an initial `CONTRIBUTING.mkdn` file from David Golden under the terms of the Apache 2 license. The text in "AI Contributions" was adapted from the [Contributing to Servo](https://book.servo.org/contributing.html) section of The Servo Book, which is licensed as no rights reserved under [CC0](https://creativecommons.org/public-domain/cc0/). Net-OAuth-0.32/xt/0000755000175000017500000000000015240175731011472 5ustar rrrrNet-OAuth-0.32/xt/author/0000755000175000017500000000000015240175731012774 5ustar rrrrNet-OAuth-0.32/xt/author/manifest.t0000644000175000017500000000131615236366473015002 0ustar rrrr#!perl # Keeps MANIFEST honest in both directions. CONTRIBUTING.md was added to the # repository but never to MANIFEST, so it silently stayed out of the released # tarball; this catches that class of drift. use strict; use warnings; use Test::More; plan skip_all => 'Author test; set AUTHOR_TESTING=1 to run' unless $ENV{AUTHOR_TESTING}; require ExtUtils::Manifest; my @missing = ExtUtils::Manifest::manicheck(); is_deeply( \@missing, [], 'every file in MANIFEST exists on disk' ) or diag "listed but absent: @missing"; my @unlisted = ExtUtils::Manifest::filecheck(); is_deeply( \@unlisted, [], 'every shippable file is listed in MANIFEST' ) or diag "present but unlisted: @unlisted"; done_testing; Net-OAuth-0.32/xt/author/pod.t0000644000175000017500000000040115236366473013750 0ustar rrrr#!perl use strict; use warnings; use Test::More; plan skip_all => 'Author test; set AUTHOR_TESTING=1 to run' unless $ENV{AUTHOR_TESTING}; eval 'use Test::Pod 1.41'; plan skip_all => 'Test::Pod 1.41 required for this test' if $@; all_pod_files_ok(); Net-OAuth-0.32/lib/0000755000175000017500000000000015240175731011605 5ustar rrrrNet-OAuth-0.32/lib/Net/0000755000175000017500000000000015240175731012333 5ustar rrrrNet-OAuth-0.32/lib/Net/OAuth.pm0000644000175000017500000003467215240175617013730 0ustar rrrrpackage Net::OAuth; use warnings; use strict; use Carp; sub PROTOCOL_VERSION_1_0() {1} sub PROTOCOL_VERSION_1_0A() {1.001} sub OAUTH_VERSION() {'1.0'} our $VERSION = '0.32'; our $SKIP_UTF8_DOUBLE_ENCODE_CHECK = 0; our $PROTOCOL_VERSION = PROTOCOL_VERSION_1_0; sub request { my $self = shift; my $what = shift; return $self->message($what . ' Request'); } sub response { my $self = shift; my $what = shift; return $self->message($what . ' Response'); } sub message { my $self = shift; my $base_class = ref $self || $self; my $type = camel(shift); my $class = $base_class . '::' . $type; smart_require($class, 1); return $class; } sub camel { my @words; foreach (@_) { while (/([A-Za-z0-9]+)/g) { (my $word = $1) =~ s/authentication/auth/i; push @words, $word; } } my $name = join('', map("\u$_", @words)); } our %ALREADY_REQUIRED = (); # class_name => rv of ->require sub smart_require { my $required_class = shift; my $croak_on_error = shift || 0; unless (exists $ALREADY_REQUIRED{$required_class}) { my $rv = eval "require $required_class"; my $error = $@; if ($error) { croak $error if $croak_on_error; return 0; } $ALREADY_REQUIRED{$required_class} = $rv; } return $ALREADY_REQUIRED{$required_class}; } =encoding utf8 =head1 NAME Net::OAuth - OAuth 1.0 for Perl =head1 SYNOPSIS use Net::OAuth::Client; # client_id is the Consumer Key, client_secret the Consumer Secret. # Framework-agnostic: supply your own redirect and session handling. my $client = Net::OAuth::Client->new( $client_id, $client_secret, site => 'https://provider.example/', request_token_path => '/oauth/request_token', authorize_path => '/oauth/authorize', access_token_path => '/oauth/access_token', callback => 'https://you.example/auth/callback', session => \&session, ); # 1. Send the user to the provider to authorize. $client->authorize_url; # 2. They return to your callback with oauth_token and oauth_verifier. my $access_token = $client->get_access_token($token, $verifier); # 3. Use the access token to fetch a protected resource. my $response = $access_token->get('/profile'); die $response->status_line unless $response->is_success; print $response->decoded_content; =head1 IMPORTANT Net::OAuth provides a low-level API for reading and writing OAuth messages. You probably should start with L. =head1 ABSTRACT OAuth is "An open protocol to allow secure API authentication in a simple and standard method from desktop and web applications." In practical terms, OAuth is a mechanism for a Consumer to request protected resources from a Service Provider on behalf of a user. Please refer to the OAuth spec: L Net::OAuth provides: =over =item * classes that encapsulate OAuth messages (requests and responses). =item * message signing =item * message serialization and parsing. =item * 2-legged requests (aka. tokenless requests, aka. consumer requests), see L =back Net::OAuth does not provide: =over =item * Consumer or Service Provider encapsulation =item * token/nonce/key storage/management =back =head1 DESCRIPTION =head2 OAUTH MESSAGES An OAuth message is a set of key-value pairs. The following message types are supported: Requests =over =item * Request Token (Net::OAuth::RequestTokenRequest) =item * Access Token (Net::OAuth::AccessTokenRequest) =item * User Authentication (Net::OAuth::UserAuthRequest) =item * Protected Resource (Net::OAuth::ProtectedResourceRequest) =item * Consumer Request (Net::OAuth::ConsumerRequest) (2-legged / token-less request) =back Responses =over =item * Request Token (Net::OAuth::RequestTokenResponse) =item * Access Token (Net::OAuth:AccessTokenResponse) =item * User Authentication (Net::OAuth::UserAuthResponse) =back Each OAuth message type has one or more required parameters, zero or more optional parameters, and most allow arbitrary parameters. All OAuth requests must be signed by the Consumer. Responses from the Service Provider, however, are not signed. To create a message, the easiest way is to use the factory methods (Net::OAuth->request, Net::OAuth->response, Net::OAuth->message). The following method invocations are all equivalent: $request = Net::OAuth->request('user authentication')->new(%params); $request = Net::OAuth->request('user_auth')->new(%params); $request = Net::OAuth->request('UserAuth')->new(%params); $request = Net::OAuth->message('UserAuthRequest')->new(%params); The more verbose way is to use the class directly: use Net::OAuth::UserAuthRequest; $request = Net::OAuth::UserAuthRequest->new(%params); You can also create a message by deserializing it from a Authorization header, URL, query hash, or POST body $request = Net::OAuth->request('protected resource')->from_authorization_header($ENV{HTTP_AUTHORIZATION}, %api_params); $request = Net::OAuth->request('protected resource')->from_url($url, %api_params); $request = Net::OAuth->request('protected resource')->from_hash({$q->Vars}, %api_params); # CGI $request = Net::OAuth->request('protected resource')->from_hash($c->request->params, %api_params); # Catalyst $response = Net::OAuth->response('request token')->from_post_body($response_content, %api_params); Note that the deserialization methods (as opposed to new()) expect OAuth protocol parameters to be prefixed with 'oauth_', as you would expect in a valid OAuth message. Before sending a request, the Consumer must first sign it: $request->sign; When receiving a request, the Service Provider should first verify the signature: die "Signature verification failed" unless $request->verify; When sending a message the last step is to serialize it and send it to wherever it needs to go. The following serialization methods are available: $response->to_post_body # a application/x-www-form-urlencoded POST body $request->to_url # the query string of a URL $request->to_authorization_header # the value of an HTTP Authorization header $request->to_hash # a hash that could be used for some other serialization =head2 API PARAMETERS vs MESSAGE PARAMETERS Net::OAuth defines 'message parameters' as parameters that are part of the transmitted OAuth message. These include any protocol parameter (prefixed with 'oauth_' in the message), and any additional message parameters (the extra_params hash). 'API parameters' are parameters required to build a message object that are not transmitted with the message, e.g. consumer_secret, token_secret, request_url, request_method. There are various methods to inspect a message class to see what parameters are defined: $request->required_message_params; $request->optional_message_params; $request->all_message_params; $request->required_api_params; $request->optional_api_params; $request->all_api_params; $request->all_params; E.g. use Net::OAuth; use Data::Dumper; print Dumper(Net::OAuth->request("protected resource")->required_message_params); $VAR1 = [ 'consumer_key', 'signature_method', 'timestamp', 'nonce', 'token' ]; =head2 ACCESSING PARAMETERS All parameters can be get/set using accessor methods. E.g. my $consumer_key = $request->consumer_key; $request->request_method('POST'); =head2 THE REQUEST_URL PARAMETER Any query parameters in the request_url are removed and added to the extra_params hash when generating the signature. E.g. the following requests are pretty much equivalent: my $request = Net::OAuth->request('Request Token')->new( %params, request_url => 'https://photos.example.net/request_token', extra_params => { foo => 'bar' }, ); my $request = Net::OAuth->request('Request Token')->new( %params, request_url => 'https://photos.example.net/request_token?foo=bar', ); Calling $request->request_url will still return whatever you set it to originally. If you want to get the request_url with the query parameters removed, you can do: my $url = $request->normalized_request_url; =head2 SIGNATURE METHODS The following signature methods are supported: =over =item * PLAINTEXT =item * HMAC-SHA1 =item * HMAC-SHA256 =item * RSA-SHA1 =back The signature method is determined by the value of the signature_method parameter that is passed to the message constructor. If an unknown signature method is specified, the signing/verification will throw an exception. =head3 PLAINTEXT SIGNATURES This method is a trivial signature which adds no security. Not recommended. =head3 HMAC-SHA1 SIGNATURES This method is available if you have Digest::SHA installed. This is by far the most commonly used method. =head3 HMAC-SHA256 SIGNATURES This method is available if you have Digest::SHA installed. =head3 RSA-SHA1 SIGNATURES To use RSA-SHA1 signatures, pass in a Crypt::OpenSSL::RSA object (or any object that can do $o->sign($str) and/or $o->verify($str, $sig)) E.g. Consumer: use Crypt::OpenSSL::RSA; use File::Slurp; $keystring = read_file('private_key.pem'); $private_key = Crypt::OpenSSL::RSA->new_private_key($keystring); $request = Net::OAuth->request('request token')->new(%params); $request->sign($private_key); Service Provider: use Crypt::OpenSSL::RSA; use File::Slurp; $keystring = read_file('public_key.pem'); $public_key = Crypt::OpenSSL::RSA->new_public_key($keystring); $request = Net::OAuth->request('request token')->new(%params); if (!$request->verify($public_key)) { die "Signature verification failed"; } Note that you can pass the key in as a parameter called 'signature_key' to the message constructor, rather than passing it to the sign/verify method, if you like. =head2 CONSUMER REQUESTS To send a request without including a token, use a Consumer Request: my $request = Net::OAuth->request('consumer')->new( consumer_key => 'dpf43f3p2l4k3l03', consumer_secret => 'kd94hf93k423kf44', request_url => 'http://provider.example.net/profile', request_method => 'GET', signature_method => 'HMAC-SHA1', timestamp => '1191242096', nonce => 'kllo9940pd9333jh', ); $request->sign; See L =head2 I18N Per the OAuth spec, when making the signature Net::OAuth first encodes parameters to UTF-8. This means that any parameters you pass to Net::OAuth, if they might be outside of ASCII character set, should be run through Encode::decode() (or an equivalent PerlIO layer) first to decode them to Perl's internal character structure. =head2 OAUTH 1.0A Background: L L Net::OAuth defaults to OAuth 1.0 spec compliance, and supports OAuth 1.0 Rev A with an optional switch: use Net::OAuth $Net::OAuth::PROTOCOL_VERSION = Net::OAuth::PROTOCOL_VERSION_1_0A; It is recommended that any new projects use this switch if possible, and existing projects move to supporting this switch as soon as possible. Probably the easiest way for existing projects to do this is to turn on the switch and run your test suite. The Net::OAuth constructor will throw an exception where the new protocol parameters (callback, callback_confirmed, verifier) are missing. Internally, the Net::OAuth::Message constructor checks $Net::OAuth::PROTOCOL_VERSION and attempts to load the equivalent subclass in the Net::OAuth::V1_0A:: namespace. So if you instantiate a Net::OAuth::RequestTokenRequest object, you will end up with a Net::OAuth::V1_0A::RequestTokenRequest (a subclass of Net::OAuth::RequestTokenRequest) if the protocol version is set to PROTOCOL_VERSION_1_0A. You can also select a 1.0a subclass on a per-message basis by passing protocol_version => Net::OAuth::PROTOCOL_VERSION_1_0A in the API parameters hash. If you are not sure whether the entity you are communicating with is 1.0A compliant, you can try instantiating a 1.0A message first and then fall back to 1.0 if that fails: use Net::OAuth $Net::OAuth::PROTOCOL_VERSION = Net::OAuth::PROTOCOL_VERSION_1_0A; my $is_oauth_1_0 = 0; my $response = eval{Net::OAuth->response('request token')->from_post_body($res->content)}; if ($@) { if ($@ =~ /Missing required parameter 'callback_confirmed'/) { # fall back to OAuth 1.0 $response = Net::OAuth->response('request token')->from_post_body( $res->content, protocol_version => Net::OAuth::PROTOCOL_VERSION_1_0 ); $is_oauth_1_0 = 1; # from now on treat the server as OAuth 1.0 compliant } else { die $@; } } At some point in the future, Net::OAuth will default to Net::OAuth::PROTOCOL_VERSION_1_0A. =head1 SEE ALSO L Check out L - it has a simpler API that may be more to your liking Check out L for a Twitter-specific OAuth API Check out L for a Netflix-specific OAuth API =head1 TODO =over =item * Support for repeating/multivalued parameters =item * Add convenience methods for SPs Something like: # direct from CGI.pm object $request = Net::OAuth->request('Request Token')->from_cgi_query($cgi, %api_params); # direct from Catalyst::Request object $request = Net::OAuth->request('Request Token')->from_catalyst_request($c->req, %api_params); # from Auth header and GET and POST params in one local $/; my $post_body = ; $request = Net::OAuth->request('Request Token')->from_auth_get_and_post( $ENV{HTTP_AUTHORIZATION}, $ENV{QUERY_STRING}, $post_body, %api_params ); =back =head1 AUTHOR Originally by Keith Grennan Currently maintained by Robert Rothenberg =head1 CONTRIBUTORS Adam Taylor Brad Whitaker Cosimo Streppone Daisuke Maki Gregor Herrmann James Raspass Jeff Dairiki Jens Rehsack Katou Akira Masayoshi Sekimura Marc Mims Mike Schleif Nobuo Danjou Pattawan Gerlings-Kaewduangdee (oiami) Sergey Romanov Shawn Moore Simon Wistow Tomaž Šolc =head1 COPYRIGHT & LICENSE Copyright 2007-2012, 2024-2025 Keith Grennan This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut 1; Net-OAuth-0.32/lib/Net/OAuth/0000755000175000017500000000000015240175731013353 5ustar rrrrNet-OAuth-0.32/lib/Net/OAuth/Request.pm0000644000175000017500000000435215240167432015344 0ustar rrrrpackage Net::OAuth::Request; use warnings; use strict; use base qw/Net::OAuth::Message/; use URI; use URI::QueryParam; use Net::OAuth; our $VERSION = '0.32'; __PACKAGE__->mk_classdata(required_message_params => [qw/ consumer_key signature_method timestamp nonce /]); __PACKAGE__->mk_classdata(optional_message_params => [qw/ version signature /]); __PACKAGE__->mk_classdata(required_api_params => [qw/ request_method request_url consumer_secret /]); __PACKAGE__->mk_classdata(optional_api_params => [qw/ signature_key token_secret extra_params protocol_version /]); __PACKAGE__->mk_classdata(signature_elements => [qw/ request_method normalized_request_url normalized_message_parameters /]); __PACKAGE__->mk_classdata(all_message_params => [ @{__PACKAGE__->required_message_params}, @{__PACKAGE__->optional_message_params}, ]); __PACKAGE__->mk_classdata(all_api_params => [ @{__PACKAGE__->required_api_params}, @{__PACKAGE__->optional_api_params}, ]); __PACKAGE__->mk_classdata(all_params => [ @{__PACKAGE__->all_api_params}, @{__PACKAGE__->all_message_params}, ]); __PACKAGE__->mk_accessors( @{__PACKAGE__->all_params}, ); sub signature_key { my $self = shift; # For some sig methods (I.e. RSA), users will pass in their own key my $key = $self->get('signature_key'); unless (defined $key) { $key = Net::OAuth::Message::encode($self->consumer_secret) . '&'; $key .= Net::OAuth::Message::encode($self->token_secret) if $self->can('token_secret'); } return $key; } sub normalized_request_url { my $self = shift; my $url = $self->request_url; Net::OAuth::Message::_ensure_uri_object($url); $url = $url->clone; $url->query(undef); return $url; } =head1 NAME Net::OAuth::Request - base class for OAuth requests =head1 SEE ALSO L, L =head1 AUTHOR Originally by Keith Grennan Currently maintained by Robert Rothenberg =head1 COPYRIGHT & LICENSE Copyright 2007-2012, 2024-2025 Keith Grennan This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut 1; Net-OAuth-0.32/lib/Net/OAuth/AccessToken.pm0000644000175000017500000000327415236366473016133 0ustar rrrrpackage Net::OAuth::AccessToken; use warnings; use strict; use base qw(Class::Accessor::Fast); __PACKAGE__->mk_accessors(qw/client token token_secret session_handle expires_in authorization_expires_in/); sub new { my $class = shift; my %opts = @_; my $self = bless \%opts, $class; return $self; } sub request { my $self = shift; my ($method, $uri, $header, $content, %params) = @_; my $oauth_req = $self->client->_make_request( 'protected resource', request_method => $method, request_url => $self->client->site_url($uri), token => $self->token, token_secret => $self->token_secret, %params, ); $oauth_req->sign; return $self->client->request(HTTP::Request->new( $method => $oauth_req->to_url, $header, $content )); } sub get { return shift->request('GET', @_); } sub post { return shift->request('POST', @_); } sub delete { return shift->request('DELETE', @_); } sub put { return shift->request('PUT', @_); } =head1 NAME Net::OAuth::AccessToken - OAuth Access Token =head1 DESCRIPTION WARNING: Net::OAuth::AccessToken is alpha code. The rest of Net::OAuth is quite stable but this particular module is new, and is under-documented and under-tested. =head1 SEE ALSO L =head1 AUTHOR Originally by Keith Grennan Currently maintained by Robert Rothenberg =head1 LICENSE AND COPYRIGHT Copyright 2007-2012, 2024-2025 Keith Grennan This program is free software; you can redistribute it and/or modify it under the terms of either: the GNU General Public License as published by the Free Software Foundation; or the Artistic License. See http://dev.perl.org/licenses/ for more information. =cut 1; Net-OAuth-0.32/lib/Net/OAuth/RequestTokenResponse.pm0000644000175000017500000000122715236366473020075 0ustar rrrrpackage Net::OAuth::RequestTokenResponse; use warnings; use strict; use base 'Net::OAuth::Response'; __PACKAGE__->add_required_message_params(qw/token_secret/); sub allow_extra_params {1} =head1 NAME Net::OAuth::RequestTokenResponse - An OAuth protocol response for an Request Token =head1 SEE ALSO L, L =head1 AUTHOR Originally by Keith Grennan Currently maintained by Robert Rothenberg =head1 COPYRIGHT & LICENSE Copyright 2007-2012, 2024-2025 Keith Grennan This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut 1; Net-OAuth-0.32/lib/Net/OAuth/AccessTokenResponse.pm0000644000175000017500000000122615236366473017645 0ustar rrrrpackage Net::OAuth::AccessTokenResponse; use warnings; use strict; use base 'Net::OAuth::Response'; __PACKAGE__->add_required_message_params(qw/token_secret/); sub allow_extra_params {1} =head1 NAME Net::OAuth::AccessTokenResponse - An OAuth protocol response for an Access Token =head1 SEE ALSO L, L =head1 AUTHOR Originally by Keith Grennan Currently maintained by Robert Rothenberg =head1 LICENSE AND COPYRIGHT Copyright 2007-2012, 2024-2025 Keith Grennan This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut 1; Net-OAuth-0.32/lib/Net/OAuth/Client.pm0000644000175000017500000002410615240175617015135 0ustar rrrrpackage Net::OAuth::Client; use warnings; use strict; use base qw(Class::Accessor::Fast); __PACKAGE__->mk_accessors(qw/id secret callback is_v1a user_agent site debug session allow_v1a_downgrade/); use LWP::UserAgent; use URI; use Net::OAuth; use Net::OAuth::Message; use Net::OAuth::AccessToken; use Carp; use Crypt::SysRandom qw( random_bytes ); our $VERSION = '0.32'; =head1 NAME Net::OAuth::Client - OAuth 1.0A Client =head1 SYNOPSIS use Net::OAuth::Client; # client_id is the Consumer Key, client_secret the Consumer Secret. # Framework-agnostic: supply your own redirect and session handling. my $client = Net::OAuth::Client->new( $client_id, $client_secret, site => 'https://provider.example/', request_token_path => '/oauth/request_token', authorize_path => '/oauth/authorize', access_token_path => '/oauth/access_token', callback => 'https://you.example/auth/callback', session => \&session, ); # 1. Send the user to the provider to authorize. $client->authorize_url; # 2. They return to your callback with oauth_token and oauth_verifier. my $access_token = $client->get_access_token($token, $verifier); # 3. Use the access token to fetch a protected resource. my $response = $access_token->get('/profile'); die $response->status_line unless $response->is_success; print $response->decoded_content; =head1 DESCRIPTION Net::OAuth::Client represents an OAuth client or consumer. WARNING: Net::OAuth::Client is alpha code. The rest of Net::OAuth is quite stable but this particular module is new, and is under-documented and under-tested. =head1 METHODS =over =item new($client_id, $client_secret, %params) Create a new Client =over =item * $client_id AKA Consumer Key - you get this from the service provider when you register your application. =item * $client_secret AKA Consumer Secret - you get this from the service provider when you register your application. =item * $params{site} =item * $params{request_token_path} =item * $params{authorize_path} =item * $params{access_token_path} =item * $params{callback} =item * $params{session} =item * $params{allow_v1a_downgrade} Permit the fallback to OAuth 1.0 described in L. Off by default. =back =back =head2 OAUTH 1.0A AND THE CALLBACK CONFIRMATION Passing a C to C selects OAuth 1.0a. In 1.0a the service provider echoes C in its request token response, and later hands the user back with an C that the client must present when it exchanges the request token for an access token. If the provider's request token response does not contain C, this client cannot use 1.0a. It used to drop back to plain OAuth 1.0 by itself, and that fallback was invisible: the access token request is then built from the 1.0 message class, which has no C parameter, so C is quietly left off the wire even when the caller passed one to L. The verifier is exactly what 1.0a added to stop an attacker starting a flow, getting a victim to authorize the attacker's request token, and then completing the exchange - so an application that asked for 1.0a and silently got 1.0 is open to that, with nothing to tell it so. C now croaks in that situation instead. An application that has to talk to a provider which is not 1.0a can opt in with allow_v1a_downgrade => 1 which restores the fallback and warns rather than dying. =cut sub new { my $class = shift; my $client_id = shift; my $client_secret = shift; my %opts = @_; $opts{user_agent} ||= LWP::UserAgent->new; $opts{id} = $client_id; $opts{secret} = $client_secret; $opts{is_v1a} = defined $opts{callback}; my $self = bless \%opts, $class; return $self; } sub request { my $self = shift; my $response = $self->user_agent->request(@_); } sub _parse_oauth_response { my $self = shift; my $do_what = shift; my $http_res = shift; my $msg = "Unable to $do_what: Request for " . $http_res->request->uri . " failed"; unless ($http_res->is_success) { if ($self->debug) { $msg .= "," . $http_res->as_string . " "; } elsif ( $http_res->content_type eq 'application/x-www-form-urlencoded' and $http_res->decoded_content =~ /\boauth_problem=(\w+)/ ) { $msg .= ", reason: " . $1; } else { $msg .= ": " . $http_res->status_line . " (pass debug=>1 to Net::OAuth::Client->new to dump the entire response)"; } croak $msg; } my $oauth_res = _parse_url_encoding($http_res->decoded_content); foreach my $k (qw/token token_secret/) { croak "Unable to $do_what: server response is missing '$k'" unless defined $oauth_res->{$k}; } return $oauth_res; } sub _parse_url_encoding { my $str = shift; my @pairs = split '&', $str; my %params; foreach my $pair (@pairs) { my ($k,$v) = split /=/, $pair; if (defined $k and defined $v) { $v =~ s/(^"|"$)//g; ($k,$v) = map Net::OAuth::Message::decode($_), $k, $v; $k =~ s/^oauth_//; $params{$k} = $v; } } return \%params; } sub get_request_token { my $self = shift; my %params = @_; my $oauth_req = $self->_make_request( "request token", request_method => $self->request_token_method, request_url => $self->_make_url("request_token"), %params ); $oauth_req->sign; my $http_res = $self->request(HTTP::Request->new( $self->request_token_method => $oauth_req->to_url )); my $oauth_res = $self->_parse_oauth_response('get a request token', $http_res); if ($self->is_v1a and !defined $oauth_res->{callback_confirmed}) { # The application asked for OAuth 1.0a by configuring a callback and the # provider did not confirm it. Dropping to 1.0 here also drops # oauth_verifier from the access token request further down, which is # the parameter 1.0a added to prevent session fixation, so this is not a # decision to take on the application's behalf without telling it. croak "Unable to get a request token: the service provider did not " . "confirm the OAuth 1.0a callback (no oauth_callback_confirmed in " . "its response). Pass allow_v1a_downgrade => 1 to " . "Net::OAuth::Client->new to fall back to OAuth 1.0 instead" unless $self->allow_v1a_downgrade; carp "Net::OAuth::Client warning: service provider did not confirm the " . "OAuth 1.0a callback; falling back to OAuth 1.0, so oauth_verifier " . "will not be sent"; $self->is_v1a(0); } return $oauth_res; } sub authorize_url { my $self = shift; my %params = @_; # allow user to get request token their own way unless (defined $params{token} and defined $params{token_secret}) { my $request_token = $self->get_request_token; $params{token} = $request_token->{token}; $params{token_secret} = $request_token->{token_secret}; } if (defined $self->session) { $self->session->($params{token} => $params{token_secret}); } my $oauth_req = $self->_make_request( 'user auth', %params ); return $oauth_req->to_url($self->_make_url('authorize')); } sub get_access_token { my $self = shift; my $token = shift; my $verifier = shift; my %params = @_; if (defined $self->session) { $params{token_secret} = $self->session->($token); } # In OAuth 1.0 mode the access token request class has no verifier message # parameter, so gather_message_parameters() would drop this on the floor # without a word. Say so rather than sending a request that is missing # the credential the caller believed it was presenting. if (defined $verifier and !$self->is_v1a) { carp "Net::OAuth::Client warning: an oauth_verifier was supplied but " . "this client is in OAuth 1.0 mode, so it will not be sent"; } my $oauth_req = $self->_make_request( 'access token', request_method => $self->access_token_method, request_url => $self->_make_url('access_token'), token => $token, verifier => $verifier, %params ); $oauth_req->sign; my $http_res = $self->request(HTTP::Request->new( $self->access_token_method => $oauth_req->to_url )); my $oauth_res = $self->_parse_oauth_response('get an access token', $http_res); return Net::OAuth::AccessToken->new(%$oauth_res, client => $self); } sub access_token_url { return shift->_make_url('access_token', @_); } sub request_token_url { return shift->_make_url('request_token', @_); } sub access_token_method { return shift->{access_token_method} || 'GET'; } sub request_token_method { return shift->{request_token_method} || 'GET'; } sub _make_request { my $self = shift; my $type = shift; my %params = @_; my %defaults = ( timestamp => time, consumer_key => $self->id, consumer_secret => $self->secret, callback => $self->callback, signature_method => 'HMAC-SHA1', request_method => 'GET', ); $defaults{nonce} = unpack("H*", random_bytes(16)) unless exists $params{nonce}; $defaults{protocol_version} = Net::OAuth::PROTOCOL_VERSION_1_0A if $self->is_v1a; my $req = Net::OAuth->request($type)->new( %defaults, %params ); return $req; } sub _make_url { my $self = shift; my $thing = shift; my $path = $self->{"${thing}_url"} || $self->{"${thing}_path"} || "/oauth/${thing}"; return $self->site_url($path, @_); } sub site_url { my $self = shift; my $path = shift; my %params = @_; my $url; if (defined $self->{site}) { $url = URI->new_abs($path, $self->{site}); } else { $url = URI->new($path); } if (@_) { $url->query_form($url->query_form , %params); } return $url; } =head1 AUTHOR Originally by Keith Grennan Currently maintained by Robert Rothenberg =head1 LICENSE AND COPYRIGHT Copyright 2007-2012, 2024-2025 Keith Grennan This program is free software; you can redistribute it and/or modify it under the terms of either: the GNU General Public License as published by the Free Software Foundation; or the Artistic License. See http://dev.perl.org/licenses/ for more information. =cut 1; Net-OAuth-0.32/lib/Net/OAuth/ConsumerRequest.pm0000644000175000017500000000150715236366473017072 0ustar rrrrpackage Net::OAuth::ConsumerRequest; use warnings; use strict; use base 'Net::OAuth::Request'; sub allow_extra_params {1} sub sign_message {1} =head1 NAME Net::OAuth::ConsumerRequest - An OAuth Consumer Request =head1 NOTE Consumer Requests are a proposed extension to OAuth, so other OAuth implementations may or may not support them. =head1 SEE ALSO Consumer Request Extension Draft: L L, L =head1 AUTHOR Originally by Keith Grennan Currently maintained by Robert Rothenberg =head1 COPYRIGHT & LICENSE Copyright 2007-2012, 2024-2025 Keith Grennan This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut 1; Net-OAuth-0.32/lib/Net/OAuth/Message.pm0000644000175000017500000002276215240167432015305 0ustar rrrrpackage Net::OAuth::Message; use warnings; use strict; use base qw/Class::Data::Inheritable Class::Accessor/; use URI::Escape; use Net::OAuth; use URI; use URI::QueryParam; use Carp; use constant OAUTH_PREFIX => 'oauth_'; our $OAUTH_PREFIX_RE = do {my $p = OAUTH_PREFIX; qr/^$p/}; __PACKAGE__->mk_classdata(extension_param_patterns => []); sub add_required_message_params { my $class = shift; $class->required_message_params([@{$class->required_message_params}, @_]); $class->all_message_params([@{$class->all_message_params}, @_]); $class->all_params([@{$class->all_params}, @_]); $class->mk_accessors(@_); } sub add_optional_message_params { my $class = shift; $class->optional_message_params([@{$class->optional_message_params}, @_]); $class->all_message_params([@{$class->all_message_params}, @_]); $class->all_params([@{$class->all_params}, @_]); $class->mk_accessors(@_); } sub add_required_api_params { my $class = shift; $class->required_api_params([@{$class->required_api_params}, @_]); $class->all_api_params([@{$class->all_api_params}, @_]); $class->all_params([@{$class->all_params}, @_]); $class->mk_accessors(@_); } sub add_extension_param_pattern { my $class = shift; $class->extension_param_patterns([@{$class->extension_param_patterns}, @_]); } sub add_to_signature { my $class = shift; $class->signature_elements([@{$class->signature_elements}, @_]); } sub new { my $proto = shift; my $class = ref $proto || $proto; my %params = @_; $class = get_versioned_class($class, \%params); my $self = bless \%params, $class; $self->set_defaults; $self->check; return $self; } sub get_versioned_class { my $class = shift; my $params = shift; my $protocol_version = $params->{protocol_version} || $Net::OAuth::PROTOCOL_VERSION; if (defined $protocol_version and $protocol_version == Net::OAuth::PROTOCOL_VERSION_1_0A and $class !~ /\::V1_0A\::/) { (my $versioned_class = $class) =~ s/::(\w+)$/::V1_0A::$1/; return $versioned_class if Net::OAuth::smart_require($versioned_class); } return $class; } sub set_defaults { my $self = shift; $self->{extra_params} ||= {}; $self->{version} ||= Net::OAuth::OAUTH_VERSION unless $self->{from_hash}; } sub is_extension_param { my $self = shift; my $param = shift; return grep ($param =~ $_, @{$self->extension_param_patterns}); } sub check { my $self = shift; foreach my $k (@{$self->required_message_params}, @{$self->required_api_params}) { if (not defined $self->{$k}) { croak "Missing required parameter '$k'"; } } if ($self->{extra_params} and $self->allow_extra_params) { foreach my $k (keys %{$self->{extra_params}}) { if ($k =~ $OAUTH_PREFIX_RE) { croak "Parameter '$k' not allowed in arbitrary params" } } } } sub encode { my $str = shift; $str = "" unless defined $str; unless($Net::OAuth::SKIP_UTF8_DOUBLE_ENCODE_CHECK) { if ($str =~ /[\x80-\xFF]/ and !utf8::is_utf8($str)) { warn "Net::OAuth warning: your OAuth message appears to contain some multi-byte characters that need to be decoded via Encode.pm or a PerlIO layer first. This may result in an incorrect signature."; } } return URI::Escape::uri_escape_utf8($str); } sub decode { my $str = shift; return uri_unescape($str); } sub allow_extra_params {1} sub sign_message {0} sub gather_message_parameters { my $self = shift; my %opts = @_; $opts{quote} = "" unless defined $opts{quote}; $opts{params} ||= []; my %params; foreach my $k (@{$self->required_message_params}, @{$self->optional_message_params}, @{$opts{add}}) { next if $k eq 'signature' and (!$self->sign_message or !grep ($_ eq 'signature', @{$opts{add}})); my $message_key = $self->is_extension_param($k) ? $k : OAUTH_PREFIX . $k; my $v = $self->$k; $params{$message_key} = $v if defined $v; } if ($self->{extra_params} and !$opts{no_extra} and $self->allow_extra_params) { foreach my $k (keys %{$self->{extra_params}}) { $params{$k} = $self->{extra_params}{$k}; } if ($self->can('request_url')) { my $url = $self->request_url; _ensure_uri_object($url); foreach my $k ($url->query_param) { $params{$k} = $url->query_param($k); } } } if ($opts{hash}) { return \%params; } my @pairs; while (my ($k,$v) = each %params) { push @pairs, join('=', encode($k), $opts{quote} . encode($v) . $opts{quote}); } return sort(@pairs); } sub normalized_message_parameters { my $self = shift; return join('&', $self->gather_message_parameters); } sub signature_base_string { my $self = shift; return join('&', map(encode($self->$_), @{$self->signature_elements})); } sub sign { my $self = shift; my $class = $self->_signature_method_class; $self->signature($class->sign($self, @_)); } sub verify { my $self = shift; my $class = $self->_signature_method_class; return $class->verify($self, @_); } sub _signature_method_class { my $self = shift; (my $signature_method = $self->signature_method) =~ s/\W+/_/g; my $sm_class = 'Net::OAuth::SignatureMethod::' . $signature_method; croak "Unable to load $signature_method plugin" unless Net::OAuth::smart_require($sm_class); return $sm_class; } sub to_authorization_header { my $self = shift; my $realm = shift; my $sep = shift || ","; if (defined $realm) { $realm = "realm=\"$realm\"$sep"; } else { $realm = ""; } return "OAuth $realm" . join($sep, $self->gather_message_parameters(quote => '"', add => [qw/signature/], no_extra => 1)); } sub from_authorization_header { my $proto = shift; my $header = shift; my $class = ref $proto || $proto; croak "Header must start with \"OAuth \"" unless $header =~ s/OAuth //; my @header = split /[\s]*,[\s]*/, $header; shift @header if $header[0] =~ /^realm=/i; return $class->_from_pairs(\@header, @_) } sub _from_pairs() { my $class = shift; my $pairs = shift; if (ref $pairs ne 'ARRAY') { croak 'Expected an array!'; } my %params; foreach my $pair (@$pairs) { my ($k,$v) = split /=/, $pair; if (defined $k and defined $v) { $v =~ s/(^"|"$)//g; ($k,$v) = map decode($_), $k, $v; $params{$k} = $v; } } return $class->from_hash(\%params, @_); } sub from_hash { my $proto = shift; my $class = ref $proto || $proto; my $hash = shift; if (ref $hash ne 'HASH') { croak 'Expected a hash!'; } my %api_params = @_; # need to do this earlier than Message->new because # the below validation step needs the correct class. # https://rt.cpan.org/Public/Bug/Display.html?id=47293 $class = get_versioned_class($class, \%api_params); my %msg_params; foreach my $k (keys %$hash) { if ($k =~ s/$OAUTH_PREFIX_RE//) { if (!grep ($_ eq $k, @{$class->all_message_params})) { croak "Parameter ". OAUTH_PREFIX ."$k not valid for a message of type $class"; } else { $msg_params{$k} = $hash->{OAUTH_PREFIX . $k}; } } elsif ($class->is_extension_param($k)) { if (!grep ($_ eq $k, @{$class->all_message_params})) { croak "Parameter $k not valid for a message of type $class"; } else { $msg_params{$k} = $hash->{$k}; } } else { $msg_params{extra_params}->{$k} = $hash->{$k}; } } $api_params{from_hash} = 1; return $class->new(%msg_params, %api_params); } sub _ensure_uri_object { $_[0] = UNIVERSAL::isa($_[0], 'URI') ? $_[0] : URI->new($_[0]); } sub from_url { my $proto = shift; my $class = ref $proto || $proto; my $url = shift; _ensure_uri_object($url); return $class->from_hash($url->query_form_hash, @_); } sub to_post_body { my $self = shift; return join('&', $self->gather_message_parameters(add => [qw/signature/])); } sub from_post_body { my $proto = shift; my $class = ref $proto || $proto; my @pairs = split '&', shift; return $class->_from_pairs(\@pairs, @_); } sub to_hash { my $self = shift; return $self->gather_message_parameters(hash => 1, add => [qw/signature/]); } sub to_url { my $self = shift; my $url = shift; if (!defined $url and $self->can('request_url') and defined $self->request_url) { $url = $self->request_url; } if (defined $url) { _ensure_uri_object($url); $url = $url->clone; # don't modify the URL that was passed in $url->query(undef); # remove any existing query params, as these may cause the signature to break my $params = $self->to_hash; my $sep = '?'; foreach my $k (sort keys %$params) { $url .= $sep . encode($k) . '=' . encode( $params->{$k} ); $sep = '&' if $sep eq '?'; } return $url; } else { return $self->to_post_body; } } =head1 NAME Net::OAuth::Message - base class for OAuth messages =head1 SEE ALSO L, L =head1 AUTHOR Originally by Keith Grennan Currently maintained by Robert Rothenberg =head1 COPYRIGHT & LICENSE Copyright 2007-2012, 2024-2025 Keith Grennan This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut 1; Net-OAuth-0.32/lib/Net/OAuth/V1_0A/0000755000175000017500000000000015240175731014161 5ustar rrrrNet-OAuth-0.32/lib/Net/OAuth/V1_0A/RequestTokenResponse.pm0000644000175000017500000000123415236366473020701 0ustar rrrrpackage Net::OAuth::V1_0A::RequestTokenResponse; use warnings; use strict; use base 'Net::OAuth::RequestTokenResponse'; __PACKAGE__->add_required_message_params(qw/callback_confirmed/); =head1 NAME Net::OAuth::V1_0A::RequestTokenResponse - An OAuth protocol response for an Request Token =head1 SEE ALSO L, L =head1 AUTHOR Originally by Keith Grennan Currently maintained by Robert Rothenberg =head1 COPYRIGHT & LICENSE Copyright 2007-2012, 2024-2025 Keith Grennan This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut 1; Net-OAuth-0.32/lib/Net/OAuth/V1_0A/AccessTokenRequest.pm0000644000175000017500000000121215236366473020300 0ustar rrrrpackage Net::OAuth::V1_0A::AccessTokenRequest; use warnings; use strict; use base 'Net::OAuth::AccessTokenRequest'; __PACKAGE__->add_required_message_params(qw/verifier/); =head1 NAME Net::OAuth::V1_0A::AccessTokenRequest - An OAuth protocol request for an Access Token =head1 SEE ALSO L, L =head1 AUTHOR Originally by Keith Grennan Currently maintained by Robert Rothenberg =head1 COPYRIGHT & LICENSE Copyright 2007-2012, 2024-2025 Keith Grennan This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut 1; Net-OAuth-0.32/lib/Net/OAuth/V1_0A/UserAuthResponse.pm0000644000175000017500000000110514733627432020001 0ustar rrrrpackage Net::OAuth::V1_0A::UserAuthResponse; use warnings; use strict; use base 'Net::OAuth::UserAuthResponse'; __PACKAGE__->add_required_message_params(qw/verifier/); =head1 NAME Net::OAuth::V1_0A::UserAuthResponse - An OAuth protocol response for an Access Token =head1 SEE ALSO L, L =head1 AUTHOR Keith Grennan, C<< >> =head1 COPYRIGHT & LICENSE Copyright 2007 Keith Grennan, all rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut 1;Net-OAuth-0.32/lib/Net/OAuth/V1_0A/RequestTokenRequest.pm0000644000175000017500000000121515236366473020532 0ustar rrrrpackage Net::OAuth::V1_0A::RequestTokenRequest; use warnings; use strict; use base 'Net::OAuth::RequestTokenRequest'; __PACKAGE__->add_required_message_params(qw/callback/); =head1 NAME Net::OAuth::V1_0A::RequestTokenRequest - An OAuth protocol request for a Request Token =head1 SEE ALSO L, L =head1 AUTHOR Originally by Keith Grennan Currently maintained by Robert Rothenberg =head1 COPYRIGHT & LICENSE Copyright 2007-2012, 2024-2025 Keith Grennan This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut 1; Net-OAuth-0.32/lib/Net/OAuth/YahooAccessTokenRefreshRequest.pm0000644000175000017500000000135615236366473022022 0ustar rrrrpackage Net::OAuth::YahooAccessTokenRefreshRequest; use warnings; use strict; use base 'Net::OAuth::AccessTokenRequest'; __PACKAGE__->add_required_message_params(qw/session_handle/); sub allow_extra_params {0} sub sign_message {1} =head1 NAME Net::OAuth::YahooAccessTokenRefreshRequest - Yahoo OAuth Extension =head1 SEE ALSO L =head1 AUTHOR Originally by Keith Grennan Currently maintained by Robert Rothenberg =head1 CONTRIBUTORS Marc Mims =head1 COPYRIGHT & LICENSE Copyright 2007-2012, 2024-2025 Keith Grennan This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut 1; Net-OAuth-0.32/lib/Net/OAuth/UserAuthRequest.pm0000644000175000017500000000256215236366473017041 0ustar rrrrpackage Net::OAuth::UserAuthRequest; use warnings; use strict; use base qw/Net::OAuth::Message/; __PACKAGE__->mk_classdata(required_message_params => [qw/ /]); __PACKAGE__->mk_classdata(optional_message_params => [qw/ token callback /]); __PACKAGE__->mk_classdata(required_api_params => [qw/ /]); __PACKAGE__->mk_classdata(optional_api_params => [qw/ extra_params /]); __PACKAGE__->mk_classdata(signature_elements => [qw/ /]); __PACKAGE__->mk_classdata(all_message_params => [ @{__PACKAGE__->required_message_params}, @{__PACKAGE__->optional_message_params}, ]); __PACKAGE__->mk_classdata(all_api_params => [ @{__PACKAGE__->required_api_params}, @{__PACKAGE__->optional_api_params}, ]); __PACKAGE__->mk_classdata(all_params => [ @{__PACKAGE__->all_api_params}, @{__PACKAGE__->all_message_params}, ]); __PACKAGE__->mk_accessors( @{__PACKAGE__->all_params}, ); =head1 NAME Net::OAuth::UserAuthRequest - request for OAuth User Authentication =head1 SEE ALSO L, L =head1 AUTHOR Originally by Keith Grennan Currently maintained by Robert Rothenberg =head1 COPYRIGHT & LICENSE Copyright 2007-2012, 2024-2025 Keith Grennan This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut 1; Net-OAuth-0.32/lib/Net/OAuth/AccessTokenRequest.pm0000644000175000017500000000132615236366473017500 0ustar rrrrpackage Net::OAuth::AccessTokenRequest; use warnings; use strict; use base 'Net::OAuth::Request'; __PACKAGE__->add_required_message_params(qw/token/); __PACKAGE__->add_required_api_params(qw/token_secret/); sub allow_extra_params {0} sub sign_message {1} =head1 NAME Net::OAuth::AccessTokenRequest - An OAuth protocol request for an Access Token =head1 SEE ALSO L, L =head1 AUTHOR Originally by Keith Grennan Currently maintained by Robert Rothenberg =head1 COPYRIGHT & LICENSE Copyright 2007-2012, 2024-2025 Keith Grennan This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut 1; Net-OAuth-0.32/lib/Net/OAuth/Response.pm0000644000175000017500000000253115240167432015507 0ustar rrrrpackage Net::OAuth::Response; use warnings; use strict; use base qw/Net::OAuth::Message/; __PACKAGE__->mk_classdata(required_message_params => [qw/ token /]); __PACKAGE__->mk_classdata(optional_message_params => [qw/ /]); __PACKAGE__->mk_classdata(required_api_params => [qw/ /]); __PACKAGE__->mk_classdata(optional_api_params => [qw/ extra_params protocol_version /]); __PACKAGE__->mk_classdata(signature_elements => [qw/ /]); __PACKAGE__->mk_classdata(all_message_params => [ @{__PACKAGE__->required_message_params}, @{__PACKAGE__->optional_message_params}, ]); __PACKAGE__->mk_classdata(all_api_params => [ @{__PACKAGE__->required_api_params}, @{__PACKAGE__->optional_api_params}, ]); __PACKAGE__->mk_classdata(all_params => [ @{__PACKAGE__->all_api_params}, @{__PACKAGE__->all_message_params}, ]); __PACKAGE__->mk_accessors( @{__PACKAGE__->all_params}, ); =head1 NAME Net::OAuth::Response - base class for OAuth responses =head1 SEE ALSO L, L =head1 AUTHOR Originally by Keith Grennan Currently maintained by Robert Rothenberg =head1 COPYRIGHT & LICENSE Copyright 2007-2012, 2024-2025 Keith Grennan This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut 1; Net-OAuth-0.32/lib/Net/OAuth/ProtectedResourceRequest.pm0000644000175000017500000000135115236366473020735 0ustar rrrrpackage Net::OAuth::ProtectedResourceRequest; use warnings; use strict; use base 'Net::OAuth::Request'; __PACKAGE__->add_required_message_params(qw/token/); __PACKAGE__->add_required_api_params(qw/token_secret/); sub allow_extra_params {1} sub sign_message {1} =head1 NAME Net::OAuth::ProtectedResourceRequest - An OAuth protocol request for a Protected Resource =head1 SEE ALSO L, L =head1 AUTHOR Originally by Keith Grennan Currently maintained by Robert Rothenberg =head1 COPYRIGHT & LICENSE Copyright 2007-2012, 2024-2025 Keith Grennan This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut 1; Net-OAuth-0.32/lib/Net/OAuth/SignatureMethod/0000755000175000017500000000000015240175731016455 5ustar rrrrNet-OAuth-0.32/lib/Net/OAuth/SignatureMethod/HMAC_SHA256.pm0000644000175000017500000000167715236366473020500 0ustar rrrrpackage Net::OAuth::SignatureMethod::HMAC_SHA256; use warnings; use strict; use Digest::SHA (); use MIME::Base64 (); sub sign { my $self = shift; my $request = shift; my $hmac_digest = Digest::SHA::hmac_sha256( $request->signature_base_string, $request->signature_key ); return MIME::Base64::encode_base64($hmac_digest, ''); } sub verify { my $self = shift; my $request = shift; return $request->signature eq $self->sign($request); } =head1 NAME Net::OAuth::SignatureMethod::HMAC_SHA256 - HMAC_SHA256 Signature Method for OAuth protocol =head1 SEE ALSO L, L =head1 AUTHOR Originally by Keith Grennan Currently maintained by Robert Rothenberg =head1 COPYRIGHT & LICENSE Copyright 2007-2012, 2024-2025 Keith Grennan This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut 1; Net-OAuth-0.32/lib/Net/OAuth/SignatureMethod/HMAC_SHA1.pm0000644000175000017500000000164515236366473020317 0ustar rrrrpackage Net::OAuth::SignatureMethod::HMAC_SHA1; use warnings; use strict; use Digest::SHA (); use MIME::Base64; sub sign { my $self = shift; my $request = shift; my $hmac_digest = Digest::SHA::hmac_sha1( $request->signature_base_string, $request->signature_key ); return encode_base64($hmac_digest, ''); } sub verify { my $self = shift; my $request = shift; return $request->signature eq $self->sign($request); } =head1 NAME Net::OAuth::SignatureMethod::HMAC_SHA1 - HMAC_SHA1 Signature Method for OAuth protocol =head1 SEE ALSO L, L =head1 AUTHOR Originally by Keith Grennan Currently maintained by Robert Rothenberg =head1 COPYRIGHT & LICENSE Copyright 2007-2012, 2024-2025 Keith Grennan This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut 1; Net-OAuth-0.32/lib/Net/OAuth/SignatureMethod/RSA_SHA1.pm0000644000175000017500000000356215236366473020234 0ustar rrrrpackage Net::OAuth::SignatureMethod::RSA_SHA1; use warnings; use strict; use MIME::Base64; # RFC 5849 3.4.3 mandates RSASSA-PKCS1-v1_5 with SHA-1. Crypt::OpenSSL::RSA # defaults have drifted (SHA-256 since 0.29_01, PSS padding since 0.35), so # pin both rather than inheriting whatever the installed version prefers. sub _apply_rfc5849_defaults { my $key = shift; for my $method (qw(use_sha1_hash use_pkcs1_padding)) { next unless UNIVERSAL::can($key, $method); eval { $key->$method; 1 } or die "Your Crypt::OpenSSL::RSA cannot do $method, which OAuth " . "RSA-SHA1 requires (RFC 5849 3.4.3): $@"; } return $key; } sub sign { my $self = shift; my $request = shift; my $key = shift || $request->signature_key; die '$request->signature_key must be an RSA key object (e.g. Crypt::OpenSSL::RSA) that can sign($text)' unless UNIVERSAL::can($key, 'sign'); _apply_rfc5849_defaults($key); return encode_base64($key->sign($request->signature_base_string), ""); } sub verify { my $self = shift; my $request = shift; my $key = shift || $request->signature_key; die 'You must pass an RSA key object (e.g. Crypt::OpenSSL::RSA) that can verify($text,$sig)' unless UNIVERSAL::can($key, 'verify'); _apply_rfc5849_defaults($key); return $key->verify($request->signature_base_string, decode_base64($request->signature)); } =head1 NAME Net::OAuth::SignatureMethod::RSA_SHA1 - RSA_SHA1 Signature Method for OAuth protocol =head1 SEE ALSO L, L =head1 AUTHOR Originally by Keith Grennan Currently maintained by Robert Rothenberg =head1 COPYRIGHT & LICENSE Copyright 2007-2012, 2024-2025 Keith Grennan This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut 1; Net-OAuth-0.32/lib/Net/OAuth/SignatureMethod/PLAINTEXT.pm0000644000175000017500000000140115236366473020371 0ustar rrrrpackage Net::OAuth::SignatureMethod::PLAINTEXT; use warnings; use strict; sub sign { my $self = shift; my $request = shift; return $request->signature_key; } sub verify { my $self = shift; my $request = shift; return $request->signature eq $self->sign($request); } =head1 NAME Net::OAuth::SignatureMethod::PLAINTEXT - PLAINTEXT Signature Method for OAuth protocol =head1 SEE ALSO L, L =head1 AUTHOR Originally by Keith Grennan Currently maintained by Robert Rothenberg =head1 COPYRIGHT & LICENSE Copyright 2007-2012, 2024-2025 Keith Grennan This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut 1; Net-OAuth-0.32/lib/Net/OAuth/UserAuthResponse.pm0000644000175000017500000000114215236366473017200 0ustar rrrrpackage Net::OAuth::UserAuthResponse; use warnings; use strict; use base 'Net::OAuth::Response'; use Net::OAuth; sub allow_extra_params {1} =head1 NAME Net::OAuth::UserAuthResponse - An OAuth protocol response for an Access Token =head1 SEE ALSO L, L =head1 AUTHOR Originally by Keith Grennan Currently maintained by Robert Rothenberg =head1 COPYRIGHT & LICENSE Copyright 2007-2012, 2024-2025 Keith Grennan This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut 1; Net-OAuth-0.32/lib/Net/OAuth/RequestTokenRequest.pm0000644000175000017500000000112015236366473017717 0ustar rrrrpackage Net::OAuth::RequestTokenRequest; use warnings; use strict; use base 'Net::OAuth::Request'; sub sign_message {1} =head1 NAME Net::OAuth::RequestTokenRequest - An OAuth protocol request for a Request Token =head1 SEE ALSO L, L =head1 AUTHOR Originally by Keith Grennan Currently maintained by Robert Rothenberg =head1 COPYRIGHT & LICENSE Copyright 2007-2012, 2024-2025 Keith Grennan This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut 1; Net-OAuth-0.32/lib/Net/OAuth/XauthAccessTokenRequest.pm0000644000175000017500000000151715236366473020514 0ustar rrrrpackage Net::OAuth::XauthAccessTokenRequest; use warnings; use strict; use base 'Net::OAuth::Request'; __PACKAGE__->add_extension_param_pattern(qr/x_auth_/); __PACKAGE__->add_required_message_params(qw/x_auth_username x_auth_password x_auth_mode/); sub allow_extra_params {0} sub sign_message {1} =head1 NAME Net::OAuth::xAuthAccessTokenRequest - xAuth extension =head1 SEE ALSO L =head1 AUTHOR Originally by Keith Grennan Currently maintained by Robert Rothenberg =head1 CONTRIBUTORS Masayoshi Sekimura Simon Wistow =head1 COPYRIGHT & LICENSE Copyright 2007-2012, 2024-2025 Keith Grennan This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut 1; Net-OAuth-0.32/META.yml0000664000175000017500000000203415240175731012311 0ustar rrrr--- abstract: 'OAuth 1.0 for Perl' author: - 'Keith Grennan ' - 'Robert Rothenberg ' build_requires: ExtUtils::MakeMaker: '0' Test::More: '0.66' Test::Warn: '0.21' configure_requires: ExtUtils::MakeMaker: '0' dynamic_config: 1 generated_by: 'ExtUtils::MakeMaker version 7.78, CPAN::Meta::Converter version 2.150010' license: perl meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html version: '1.4' name: Net-OAuth no_index: directory: - t - inc recommends: Crypt::OpenSSL::RSA: '0.38' Crypt::SysRandom::XS: '0.010' requires: Class::Accessor: '0.31' Class::Data::Inheritable: '0.06' Crypt::SysRandom: '0.006' Digest::SHA: '5.47' Encode: '2.35' LWP::UserAgent: '1' Test::More: '0.66' Test::Warn: '0.21' URI: '5.15' perl: '5.008001' resources: bugtracker: https://rt.cpan.org/Public/Dist/Display.html?Name=Net-OAuth repository: https://github.com/keeth/Net-OAuth.git version: '0.32' x_serialization_backend: 'CPAN::Meta::YAML version 0.020' Net-OAuth-0.32/MANIFEST0000644000175000017500000000232715240175617012177 0ustar rrrrChanges CONTRIBUTING.md lib/Net/OAuth.pm lib/Net/OAuth/AccessToken.pm lib/Net/OAuth/AccessTokenRequest.pm lib/Net/OAuth/AccessTokenResponse.pm lib/Net/OAuth/Client.pm lib/Net/OAuth/ConsumerRequest.pm lib/Net/OAuth/Message.pm lib/Net/OAuth/ProtectedResourceRequest.pm lib/Net/OAuth/Request.pm lib/Net/OAuth/RequestTokenRequest.pm lib/Net/OAuth/RequestTokenResponse.pm lib/Net/OAuth/Response.pm lib/Net/OAuth/SignatureMethod/HMAC_SHA1.pm lib/Net/OAuth/SignatureMethod/HMAC_SHA256.pm lib/Net/OAuth/SignatureMethod/PLAINTEXT.pm lib/Net/OAuth/SignatureMethod/RSA_SHA1.pm lib/Net/OAuth/UserAuthRequest.pm lib/Net/OAuth/UserAuthResponse.pm lib/Net/OAuth/V1_0A/AccessTokenRequest.pm lib/Net/OAuth/V1_0A/RequestTokenRequest.pm lib/Net/OAuth/V1_0A/RequestTokenResponse.pm lib/Net/OAuth/V1_0A/UserAuthResponse.pm lib/Net/OAuth/XauthAccessTokenRequest.pm lib/Net/OAuth/YahooAccessTokenRefreshRequest.pm Makefile.PL MANIFEST This list of files META.json META.yml README SECURITY.md t/01-spec.t t/02-rsa.t t/03-header.t t/04-response.t t/05-auth.t t/06-factory.t t/07-consumer-request.t t/09-encoding.t t/10-misc.t t/11-spec-1.0a.t t/12-xauth.t t/13-hmac-sha256.t t/15-client-v1a-downgrade.t t/rsakey t/rsakey.pub xt/author/manifest.t xt/author/pod.t Net-OAuth-0.32/Changes0000644000175000017500000002235615240175617012345 0ustar rrrrRevision history for Net-OAuth 0.32 Sun 16 Aug 00:51:04 BST 2026 [Security] - The Net::OAuth smart_require function no longer memoizes failures, which allowed attackers to exhaust memory with requests for invalid signature methods. CVE-2026-72888 - Net::OAuth::Client no longer allows silent downgrades from OAuth 1.0a to 1.0 when the remote provider drops the oauth_verifier. The behavior can be re-enabled with the allow_v1a_downgrade option. CVE-2026-72887 [Bug Fixes] - RSA-SHA1 now pins PKCS#1 v1.5 padding and the SHA-1 hash rather than inheriting Crypt::OpenSSL::RSA's defaults, which have drifted (SHA-256 in 0.29_01, RSA-PSS in 0.35). Against 0.35 and later this produced RSA-PSS signatures that no RFC 5849 3.4.3 compliant server will accept. Reported as Debian #1142954. [Other] - Switched to use Crypt::SysRandom for generating random bytes. [Tests] - t/02-rsa.t asserts the signature base string separately from the signature, so a failure distinguishes base-string construction from the crypto layer. - t/02-rsa.t skips with a diagnostic on Crypt::OpenSSL::RSA 0.35 through 0.37, which disabled the PKCS#1 v1.5 padding that OAuth RSA-SHA1 requires; 0.38 re-enabled it. [Toolchain] - Recommend Crypt::OpenSSL::RSA 0.38 or later for RSA-SHA1. - Declared MIN_PERL_VERSION as 5.008001, the floor imposed by URI and MIME::Base32. - Added GitHub Actions CI covering perl 5.16 through latest, and a matrix pinning the Crypt::OpenSSL::RSA versions that bracket the padding change behind Debian #1142954. - Added author tests under xt/, guarded by AUTHOR_TESTING. - Corrected the AUTHOR metadata, which credited only the current maintainer. Keith Grennan is the author and copyright holder; Robert Rothenberg maintains. - Updated .mailmap and the AUTHOR POD to canonicalise on reachable addresses, as cpan.org no longer forwards mail. - MANIFEST now ships CONTRIBUTING.md, and no longer lists the generated META.json and META.yml, which distmeta writes into the distribution directory regardless. [Documentation] - Removed the Dancer demo application and rewrote the SYNOPSIS and README to be framework-agnostic. The demo linked to a domain that is now parked. - Added =encoding utf8 to Net::OAuth, which had a non-ASCII contributor name in its POD without one. [Documentation] - Added missing version and timestamp to Changes for v0.31. - Added missing acknowledgement to Changes for v0.31. - Added CONTRIBUTORS section to the POD. - Added a "How to Contribute" document. 0.31 Thu, 03 Apr 2025 16:51 BST [Bug Fixes] - Added missing dependency RT#70407. - Removed use of Digest::HMAC_SHA1 (thanks to James Raspass). [Documentation] - Updated Changes for v0.29 with CVE. - Updated the security policy. [Toolchain] - Remove Build.PL and just use Makefile.PL. 0.30 Fri, 03 Jan 2025 09:46 GMT [Bug Fixes] - Fixed syntax error in Net::OAuth::Client (oops). - Added missing VERSION to Net::OAuth::Client. 0.29 Fri, 03 Jan 2025 09:15 GMT [Security] - Net::OAuth::Client uses a better source of randomness for generating the nonce CVE-2025-22376 [Bug Fixes] - Removed unnecessary prerequisite RT#69810 GH#4 GH#6 - Fix broken dependency for URI::Escape GH#4 (thanks oiami) - Fix handling of uri_escape_utf RT#73705 (thanks Tomaž Šolc) [Documentation] - Reorganised Changes to almost follow CPAN::Changes::Spec - Updated author and maintainer information - Changed to consistent copyright information - Fixed typo RT#125292 RT#90007 GH#6 (thanks Gregor Herrmann) - Added a Security Policy (SECURITY.md) to the distribution [Tests] - Fixed randomly failing t/02-rsa.t test RT#125291 RT#125482 (thanks Gregor Herrmann) [Other] - Maintenance taken over by Robert Rothenberg - Added .mailmap to the repo - Distribution metadata now has the git repository (thanks Sergey Romanov) GH#6 - Set up config_requires in Build.PL - Updated Build.PL configuration - Updated MANIFEST.SKIP rules 0.28 Fri, 06 Jan 2012 05:51:04 UTC - Added HMAC-SHA256 support 0.27 Wed, 16 Jun 2010 20:39:59 UTC - Added class for Yahoo! access token refresh request (thanks Marc Mims) 0.26 Wed, 16 Jun 2010 19:59:04 UTC - Message::encode no longer tries fix potential 'double-encoding' (in any case it appeared to be doing it wrong). Now it just complains if you try to pass in undecoded strings. (thanks Daisuke Maki and KATOU Akira) 0.25 Sun, 21 Mar 2010 03:50:40 UTC - Gah, $VERSION lameness 0.24 Sun, 21 Mar 2010 03:39:40 UTC - Fix test breakage in 0.23 0.23 Thu, 18 Mar 2010 17:23:36 UTC - Removed UNIVERSAL::require dependency - Net::OAuth->request constructor now dies if module fails to load (thanks Mike Schleif) - Fixed RT#55635 Incorrect dependencies (thanks Jens Rehsack) - Replaced die() with croak() 0.22 Thu, 11 Mar 2010 00:21:26 UTC - Renamed xAuthAccessTokenRequest to XauthAccessTokenRequest for CamelCaseConsistency - Added a couple tests for XauthAccessTokenRequest 0.21 Wed, 10 Mar 2010 22:20:49 UTC - Added xAuth support with xAuthAccessTokenRequest (thanks Masayoshi Sekimura and Simon Wistow) - Added performance patch to decrease stat() system calls when requiring modules (thanks Brad Whitaker) 0.20 Fri, 13 Nov 2009 18:56:55 UTC - Fixed RT#48867 - error in synopsis - thanks Adam Taylor! - Removed UTF8 double-encoding warning. Now Net::OAuth::Message::encode() uses Encode::is_utf8() to determine if the input is already UTF-8 encoded. If so, it runs decode_utf8() on it before sending it to uri_escape_utf8(). Thanks Hector Garcia Alvarez! - Potentially fixed an issue found by Marc Mims, where HMAC_SHA1 was failing to load, breaking some CPAN tests. Build.PL now explicitly requires Digest::SHA1 and Encode. Hopefully that fixes it. 0.19 Fri, 26 Jun 2009 17:30:06 UTC [Bug Fixes] - Fixed RT#47369 - Don't automatically set oauth_version parameter when message is created via from_hash (or from_url, from_post_body, etc). Thanks COSIMO! 0.18 Thu, 25 Jun 2009 17:18:04 UTC [Bug Fixes] - Fixed accidental (though probably harmless) regression in 0.17 0.17 Thu, 25 Jun 2009 16:59:50 UTC [Bug Fixes] - Fixed RT#47293 - Message->from_hash was validating using the incorrect class, causing a 'Parameter X not valid for a message of type Y' message on V1.0a messages. Thanks Jeff Dairiki! 0.16 Mon, 15 Jun 2009 18:36:17 UTC [Enhancements] - Added support for OAuth 1.0A - see POD section 'OAUTH 1.0A' for details - Net::OAuth still defaults to 1.0 for now 0.15 Fri, 05 Jun 2009 00:48:07 UTC - Added Twitter demo consumer - Warn if message parameter is already UTF-8 that it will be double-encoded; see I18N section of Net::OAuth manpage - Better handling of missing 'realm' parameter in Authorization header methods - Better handling of request_url parameter; see REQUEST_URL PARAMETER section of Net::OAuth manpage - Fixed RT#44699 - encode spaces to %20 rather than + in $message->to_url() 0.14 Sat, 13 Dec 2008 17:29:36 UTC - Add POD for consumer requests 0.13 Thu, 13 Nov 2008 22:45:46 UTC - Added support for Consumer Request (token-less / two-legged) message type 0.12 Fri, 04 Jul 2008 22:58:23 UTC - Added support for extensions - Net::OpenMicroBlogging in particular 0.11 Wed, 04 Jun 2008 16:50:14 UTC - Doc edits 0.1 Wed, 04 Jun 2008 16:27:50 UTC - Added demo, fixed docs 0.09 Tue, 03 Jun 2008 03:46:32 UTC - Fixed another annoying test failure 0.08 Mon, 02 Jun 2008 17:41:52 UTC - Fixed test failures found in 0.07. - More docs. - Added more deserialization methods. - Changed factory invocation from message('foo') to message('foo')->new(), to allow deserialization methods to be used instead of new(). 0.07 Sun, 01 Jun 2008 16:04:26 UTC - Added a factory class, Net::OAuth - Added several 'Response' classes - Added UserAuthRequest and UserAuthResponse - Created a Message base class from which Request and Response inherit - Added some introductory documentation - Added more tests 0.06 Sat, 08 Mar 2008 00:57:40 UTC - Removed live test that stopped working 0.05 Mon, 19 Nov 2007 03:30:05 UTC - Integrated patch from Nobuo Danjou, for Draft 6 spec compliance 0.04 Fri, 19 Oct 2007 16:45:03 UTC - Integrated patch from SARTAK, fixing signature for RequestTokenRequest with HMAC-SHA1 0.03 Mon, 15 Oct 2007 01:35:17 UTC - Fixed header parsing 0.02 Tue, 02 Oct 2007 07:35:17 UTC - Added RSA-SHA1 support 0.01 Sun, 30 Sep 2007 13:35:06 UTC - First version, released on an unsuspecting world. Net-OAuth-0.32/SECURITY.md0000644000175000017500000000645014773525465012652 0ustar rrrrThis is the Security Policy for the Perl distribution Net-OAuth. The latest version of this Security Policy can be found in the Git Repository for [Net-OAuth](https://github.com/keeth/Net-OAuth). This text is based on the CPAN Security Group's [Guidelines for Adding a Security Policy to Perl Distributions](https://security.metacpan.org/docs/guides/security-policy-for-authors.html) (version 1.2.0). # How to Report a Security Vulnerability Security vulnerabilities can be reported using this project's GitHub [Security Advisories](https://github.com/keeth/Net-OAuth/security/advisories). Please include as many details as possible, including code samples or test cases, so that we can reproduce the issue. Check that your report does not expose any sensitive data, such as passwords, tokens, or personal information. If you would like any help with triaging the issue, or if the issue is being actively exploited, please copy the report to the CPAN Security Group (CPANSec) at . Please *do not* use the public issue reporting system on RT or GitHub issues for reporting security vulnerabilities. Please do not disclose the security vulnerability in public forums until past any proposed date for public disclosure, or it has been made public by the maintainers or CPANSec. That includes patches or pull requests. For more information, see [Report a Security Issue](https://security.metacpan.org/docs/report.html) on the CPANSec website. ## Response to Reports The maintainer(s) aim to acknowledge your security report as soon as possible. However, this project is maintained by a small group of volunteers in their spare time, and they cannot guarantee a rapid response. If you have not received a response from them within a week, then please send a reminder to them and copy the report to CPANSec at . Please note that the initial response to your report will be an acknowledgement, with a possible query for more information. It will not necessarily include any fixes for the issue. The project maintainer(s) may forward this issue to the security contacts for other projects where we believe it is relevant. This may include embedded libraries, system libraries, prerequisite modules or downstream software that uses this software. They may also forward this issue to CPANSec. # What Software this Policy Applies to Any security vulnerabilities in Net-OAuth are covered by this policy. Security vulnerabilities are considered anything that allows users to execute unauthorised code, access unauthorised resources, or to have an adverse impact on accessibility or performance of a system. Security vulnerabilities in upstream software (embedded libraries, prerequisite modules or system libraries, or in Perl), are not covered by this policy unless they affect Net-OAuth, or Net-OAuth can be used to exploit vulnerabilities in them. Security vulnerabilities in downstream software (any software that uses Net-OAuth, or plugins to it that are not included with the Net-OAuth distribution) are not covered by this policy. ## Which Versions of this Software are Supported? The maintainer(s) will only commit to releasing security fixes for the latest version of Net-OAuth. # Installation and Usage Issues Please see the module documentation for more information. Net-OAuth-0.32/META.json0000664000175000017500000000336715240175731012473 0ustar rrrr{ "abstract" : "OAuth 1.0 for Perl", "author" : [ "Keith Grennan ", "Robert Rothenberg " ], "dynamic_config" : 1, "generated_by" : "ExtUtils::MakeMaker version 7.78, CPAN::Meta::Converter version 2.150010", "license" : [ "perl_5" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : 2 }, "name" : "Net-OAuth", "no_index" : { "directory" : [ "t", "inc" ] }, "prereqs" : { "build" : { "requires" : { "ExtUtils::MakeMaker" : "0" } }, "configure" : { "requires" : { "ExtUtils::MakeMaker" : "0" } }, "runtime" : { "recommends" : { "Crypt::OpenSSL::RSA" : "0.38", "Crypt::SysRandom::XS" : "0.010" }, "requires" : { "Class::Accessor" : "0.31", "Class::Data::Inheritable" : "0.06", "Crypt::SysRandom" : "0.006", "Digest::SHA" : "5.47", "Encode" : "2.35", "LWP::UserAgent" : "1", "Test::More" : "0.66", "Test::Warn" : "0.21", "URI" : "5.15", "perl" : "5.008001" } }, "test" : { "requires" : { "Test::More" : "0.66", "Test::Warn" : "0.21" } } }, "release_status" : "stable", "resources" : { "bugtracker" : { "web" : "https://rt.cpan.org/Public/Dist/Display.html?Name=Net-OAuth" }, "repository" : { "url" : "https://github.com/keeth/Net-OAuth.git" } }, "version" : "0.32", "x_serialization_backend" : "JSON::PP version 4.16" } Net-OAuth-0.32/t/0000755000175000017500000000000015240175731011302 5ustar rrrrNet-OAuth-0.32/t/13-hmac-sha256.t0000644000175000017500000000171015240167432013624 0ustar rrrr#!perl use strict; use warnings; use Test::More tests => 3; use Net::OAuth::ProtectedResourceRequest; SKIP: { skip "Digest::SHA not installed", 3 unless eval 'require Digest::SHA; 1'; my $request = Net::OAuth::ProtectedResourceRequest->new( consumer_key => 'dpf43f3p2l4k3l03', consumer_secret => 'kd94hf93k423kf44', request_url => 'http://photos.example.net/photos', request_method => 'GET', signature_method => 'HMAC-SHA256', timestamp => '1191242096', nonce => 'kllo9940pd9333jh', token => 'nnch734d00sl2jdk', token_secret => 'pfkkdhi9sl3r4s00', extra_params => { file => 'vacation.jpg', size => 'original', }, ); $request->sign; is(length($request->signature), 44); is($request->signature, "WVPzl1j6ZsnkIjWr7e3OZ3jkenL57KwaLFhYsroX1hg="); ok($request->verify()); } Net-OAuth-0.32/t/rsakey.pub0000644000175000017500000000070314733627432013316 0ustar rrrr-----BEGIN PUBLIC KEY----- MIIBIDANBgkqhkiG9w0BAQEFAAOCAQ0AMIIBCAKCAQEA35V2Kqf072yvnsZN+aY7 rIx+Osa8Akh52npNEBk63dIbnQuPvCoI6xg6w7bnGIsOtN5Uma//j0Fey/aOuzCj ++dTiIXBAFSD6iDkXZR3kAyYYvECt5XhDqiEO3h5CMQss0aopdnFvR/NFlBIxivY T14zxcoViZWrs5gbEyHzcVOpW7YL+S0jsEhQWPP31mPGVwhgn+fFBVU+0TvOzWXw Ewl6WCx/QUQop4jWwrOIqrmcl50X4ghCuGxN+HXd4mCf+HNK8mQJC0BLjeTPcwJF l4kk9ZBizwDSXxY5AIZLQbRxZcBME9s1tb2lpC/5yEWJYypjHCkArwkrWb26WLHS 5wIBIw== -----END PUBLIC KEY----- Net-OAuth-0.32/t/rsakey0000644000175000017500000000321314733627432012530 0ustar rrrr-----BEGIN RSA PRIVATE KEY----- MIIEogIBAAKCAQEA35V2Kqf072yvnsZN+aY7rIx+Osa8Akh52npNEBk63dIbnQuP vCoI6xg6w7bnGIsOtN5Uma//j0Fey/aOuzCj++dTiIXBAFSD6iDkXZR3kAyYYvEC t5XhDqiEO3h5CMQss0aopdnFvR/NFlBIxivYT14zxcoViZWrs5gbEyHzcVOpW7YL +S0jsEhQWPP31mPGVwhgn+fFBVU+0TvOzWXwEwl6WCx/QUQop4jWwrOIqrmcl50X 4ghCuGxN+HXd4mCf+HNK8mQJC0BLjeTPcwJFl4kk9ZBizwDSXxY5AIZLQbRxZcBM E9s1tb2lpC/5yEWJYypjHCkArwkrWb26WLHS5wIBIwKCAQAMxrZLlJGnSAoJEqVe uQq5Zx0n7hlfN1drkfXGZ9d6Y8cQSc2y+xZz1X+zaYmMX7eykFybEV8PgBQLp7Bi d87bMcpCUMkzOAeJuLyXohV18hdWHGaOJdJYm+pMioqSyWGj2Cbk599p5I9gXFvu ESJNrZyO9ZrUqXeGmvo7m4pA/VwFlEw9ogVxYwXDCI3s0v+ZHPIzmFznY5UI+M9x UEquqYkW60uZ7wAe+v1IET04VQqzFJvfnA1R7OatokIaRn5bN2ygy/cE9Y26uDXA +DwldzjBw6063F0h3RGs9/9iXl4bnFtq1Z1MQvlWi8mlPPJmdED/1g3G6tLEdzz8 hXE7AoGBAPpQ/LlTFmXAOyaMXzkE3IvEF8ujsLtexbzvadjiEW127WJOjQlsHlWi +QN4pVDT5E1qOb+DSnt2M+nPbgECLOeRxtZmP/tq2CW5sqmfqVnBs1zKnx9nODiO x9XiogSE9eMlFWcpoDySvo5WvO8+kGQNtwJNcVTmYD4XG6nn/vOrAoGBAOSpFhxv g16vyET3fwshGsGbdgZ1TK/VQNHEz8esV2erhTj4icrPT1DmZ4Lc4Ih9BRPverCV kt4ohp9KcFgUYhUqYoeOMqrJnvWQmnkiYM9GL2bsEOvhuDv/sa3K8FGDSx9deqUc oLhsawvi5MG+CpNUgO9Rlbqvm4TUe2Utk6G1AoGADk3FTGsl2e26PLeQaaiBoZYt PtYnWyn8q7XoypCTSBVspoglUP7dKXcG6kFoiEafVOF/pIso09reZSHLxYsYgkLY KYIvirWl84b0RDUCXOZ/RyGFb4I9uhbJlzGFmdu2R352QGjHU+sg1O8De2KpKknt M1Th55giwbgtd2xXticCgYEA3iCZIu/79ZTRLQ2unRjYKco4I4fkGIYEdAEEW5F5 eqaerF8mxQPmplwqChhlFt/ZDA01WxT1ElNA8oLTiMNX902+zNNHKZCpC85M6rOu gDWNIicmYXwvUDo3kuJly4bbQwpZ4jkRKC7OY1FwgbFMGheTMZ+2Bc8pXHajwV95 eIMCgYEAgjJCDDslCUwluUfOYeT11wuiij7AeCRn5Dh91eYZq1VhrZboB/r8yW4E HdWM8DkbsB1e9Z+WPLbFRVCcbWhiZ55hlGesEvUjbycT0ziQ8C0ohJx/Un7/oNuV slDK9TyG0jnvApQ8Mu4MU4fwx+3sIg2vAgFWUuUZ9E6V03uJCCM= -----END RSA PRIVATE KEY----- Net-OAuth-0.32/t/07-consumer-request.t0000644000175000017500000000225315240167432015235 0ustar rrrr#!perl use strict; use warnings; use Test::More tests => 6; BEGIN { use_ok( 'Net::OAuth' ); use_ok( 'Net::OAuth::ConsumerRequest' ); } my $request = Net::OAuth->request('consumer')->new( consumer_key => 'dpf43f3p2l4k3l03', consumer_secret => 'kd94hf93k423kf44', request_url => 'http://provider.example.net/profile', request_method => 'GET', signature_method => 'HMAC-SHA1', timestamp => '1191242096', nonce => 'kllo9940pd9333jh', ); $request->sign; ok($request->verify); is($request->signature_base_string, 'GET&http%3A%2F%2Fprovider.example.net%2Fprofile&oauth_consumer_key%3Ddpf43f3p2l4k3l03%26oauth_nonce%3Dkllo9940pd9333jh%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1191242096%26oauth_version%3D1.0'); is($request->signature, 'SGtGiOrgTGF5Dd4RUMguopweOSU='); is($request->to_authorization_header('http://provider.example.net/', ",\n")."\n", < 5; BEGIN { use Net::OAuth; $Net::OAuth::PROTOCOL_VERSION = Net::OAuth::PROTOCOL_VERSION_1_0; use_ok( 'Net::OAuth::Response' ); use_ok( 'Net::OAuth::RequestTokenResponse' ); use_ok( 'Net::OAuth::AccessTokenResponse' ); } my $response = Net::OAuth::RequestTokenResponse->new( token => 'abcdef', token_secret => '0123456', extra_params => { foo => 'bar', }, ); is($response->to_post_body, 'foo=bar&oauth_token=abcdef&oauth_token_secret=0123456'); $response = Net::OAuth::AccessTokenResponse->new( token => 'abcdef', token_secret => '0123456', extra_params => { foo => 'bar', }, ); is($response->to_post_body, 'foo=bar&oauth_token=abcdef&oauth_token_secret=0123456');Net-OAuth-0.32/t/02-rsa.t0000644000175000017500000000574715240167432012507 0ustar rrrr#!perl use strict; use warnings; use Test::More tests => 3; use Net::OAuth::ProtectedResourceRequest; sub slurp { my $file = shift; my $text = do { local( @ARGV, $/ ) = $file ; <> } ; return $text; } SKIP: { skip "Crypt::OpenSSL::RSA not installed", 3 unless eval 'require Crypt::OpenSSL::RSA'; my $publickey; my $privkey; eval { $privkey = Crypt::OpenSSL::RSA->new_private_key(slurp('t/rsakey')); } or die "unable to read private key"; eval { $publickey = Crypt::OpenSSL::RSA->new_public_key(slurp("t/rsakey.pub")); } or die "unable to read public key"; # Crypt::OpenSSL::RSA 0.35 through 0.37 disabled PKCS#1 v1.5 padding over # the Marvin attack; 0.38 re-enabled it (PR #103). RFC 5849 3.4.3 requires # it, so RSA-SHA1 simply cannot be done on those releases. skip "Crypt::OpenSSL::RSA $Crypt::OpenSSL::RSA::VERSION cannot do PKCS#1 " . "v1.5 padding, which OAuth RSA-SHA1 requires; upgrade to 0.38+", 3 unless eval { Crypt::OpenSSL::RSA->new_private_key(slurp('t/rsakey')) ->use_pkcs1_padding; 1 }; # Deliberately left un-tuned: Net::OAuth::SignatureMethod::RSA_SHA1 must # pin the hash and padding itself, since callers in the wild don't. my $request = Net::OAuth::ProtectedResourceRequest->new( consumer_key => 'dpf43f3p2l4k3l03', consumer_secret => 'kd94hf93k423kf44', request_url => 'http://photos.example.net/photos', request_method => 'GET', signature_method => 'RSA-SHA1', timestamp => '1191242096', nonce => 'kllo9940pd9333jh', token => 'nnch734d00sl2jdk', token_secret => 'pfkkdhi9sl3r4s00', extra_params => { file => 'vacation.jpg', size => 'original', }, signature_key => $privkey, ); # Assert the base string before the signature. It is pure Perl (sorting, # percent-encoding, no crypto), so checking it first splits a failure into # "we built the wrong string" vs "OpenSSL signed it differently" instead of # leaving you to diff two opaque base64 blobs. is($request->signature_base_string, 'GET&http%3A%2F%2Fphotos.example.net%2Fphotos&file%3Dvacation.jpg' . '%26oauth_consumer_key%3Ddpf43f3p2l4k3l03%26oauth_nonce%3Dkllo9940pd9333jh' . '%26oauth_signature_method%3DRSA-SHA1%26oauth_timestamp%3D1191242096' . '%26oauth_token%3Dnnch734d00sl2jdk%26oauth_version%3D1.0%26size%3Doriginal', 'signature base string (RFC 5849 3.4.1)'); $request->sign; is($request->signature, "mkZ/wOq5cS7UOyKKdo5Khd4fYpYVhs20K0E8k/DyumO74rjo7s1y+Y+mZ/hBvy2gu6ip/U4XqTRdT0QObAUvrKf+fH/Yfdc6kQsQ9kP3/IgRF1K5Po284UIy8p7DcJGC5udR01aTkNkpqo3XAw+8ljULguhwVC1l+EWHrzKKuZ6li7EOx1It5JxWqCRVn+1+NA8vGlIjcaPb+aIoUmyM2/ytu1041cnvdDGzuiibRgIv770cuXsfkFNtaK5rgjlmhZhDwqULHfWEN9oxcHxY+6EB/HOvwWkYE1CeUoo9Dgm6mn6+DsfkTjfRh4mJRTIyi6jEYaIgY5RaWwSHaXw44A=="); ok($request->verify($publickey)); } Net-OAuth-0.32/t/15-client-v1a-downgrade.t0000644000175000017500000001132015240175617015625 0ustar rrrr#!perl # Net::OAuth::Client selects OAuth 1.0a when the application configures a # callback. The service provider's request token response then decides # whether that choice survives: without oauth_callback_confirmed the client # used to drop back to 1.0 by itself, which also drops oauth_verifier from # the access token request, silently. These tests pin the three states the # client can be in, and the warning for a verifier that will not be sent. # # The user agent here is a stub returning canned responses. Nothing in this # file opens a socket. use strict; use warnings; use Test::More tests => 14; use Test::Warn; use Net::OAuth; use Net::OAuth::Client; use HTTP::Response; { package StubUA; sub new { my ($class, %a) = @_; return bless { confirm => $a{confirm}, seen => [] }, $class; } sub seen { @{ $_[0]{seen} } } sub request { my ($self, $http_req) = @_; push @{ $self->{seen} }, $http_req->uri->as_string; my $body; if (@{ $self->{seen} } == 1) { # Request token response. The presence of oauth_callback_confirmed # is the only thing that varies between these tests. $body = 'oauth_token=reqtok&oauth_token_secret=reqsec'; $body .= '&oauth_callback_confirmed=true' if $self->{confirm}; } else { $body = 'oauth_token=acctok&oauth_token_secret=accsec'; } my $res = HTTP::Response->new(200, 'OK', ['Content-Type' => 'application/x-www-form-urlencoded'], $body); $res->request($http_req); return $res; } } sub client { my %args = @_; my $ua = StubUA->new(confirm => delete $args{confirm}); my $client = Net::OAuth::Client->new( 'consumer-key', 'consumer-secret', site => 'https://provider.invalid/', request_token_path => '/oauth/request_token', authorize_path => '/oauth/authorize', access_token_path => '/oauth/access_token', user_agent => $ua, session => sub { 'reqsec' }, %args, ); return ($client, $ua); } my $CALLBACK = 'https://app.invalid/cb'; # A provider that confirms the callback: nothing changes, and the verifier # reaches the wire. { my ($client, $ua) = client(confirm => 1, callback => $CALLBACK); ok($client->is_v1a, 'configuring a callback selects 1.0a'); warnings_are { $client->get_request_token } [], 'a confirming provider produces no warning'; ok($client->is_v1a, 'and leaves the client on 1.0a'); warnings_are { $client->get_access_token('reqtok', 'the-verifier') } [], 'nor does the access token exchange'; my @urls = $ua->seen; is(scalar @urls, 2, 'both requests were sent'); like($urls[-1], qr/oauth_verifier=the-verifier/, 'the access token request carries oauth_verifier'); } # A provider that does not confirm it, with the client left at its defaults: # the exchange stops rather than continuing without the verifier. { my ($client, $ua) = client(confirm => 0, callback => $CALLBACK); # Run the whole flow, so that the last assertion has something to # observe: before this change the flow completed here and sent an # access token request with no oauth_verifier on it. my $completed = eval { $client->get_request_token; $client->get_access_token('reqtok', 'the-verifier'); 1; }; ok(!$completed, 'an unconfirmed callback is fatal by default'); like($@, qr/allow_v1a_downgrade/, '... and the message names the option that permits it'); is(scalar($ua->seen), 1, '... and the access token request is never sent'); } # The same provider, with the application opting in to the fallback. It # behaves as it always did, but says so both times. { my ($client, $ua) = client(confirm => 0, callback => $CALLBACK, allow_v1a_downgrade => 1); warning_like { $client->get_request_token } qr/falling back to OAuth 1\.0/, 'the opted-in fallback warns'; ok(!$client->is_v1a, '... and does fall back'); warning_like { $client->get_access_token('reqtok', 'the-verifier') } qr/oauth_verifier was supplied/, '... and the dropped verifier warns too'; my @urls = $ua->seen; unlike($urls[-1], qr/oauth_verifier/, '... which is accurate: it is not on the wire'); } # A client that never asked for 1.0a is in 1.0 mode legitimately, but a # verifier handed to it still goes nowhere, so it still warns. { my ($client, $ua) = client(confirm => 0); $client->get_request_token; warning_like { $client->get_access_token('reqtok', 'the-verifier') } qr/oauth_verifier was supplied/, 'a 1.0 client warns about a verifier it cannot send'; } Net-OAuth-0.32/t/09-encoding.t0000644000175000017500000000217714733627432013520 0ustar rrrr#!perl use strict; use warnings; use Test::More tests => 15; use Test::Warn; use Encode; use utf8; BEGIN { use_ok( 'Net::OAuth::Message' ); } sub is_encoding { my $orig = shift; my $encoded = shift; is(Net::OAuth::Message::encode($orig), $encoded); } is_encoding('abcABC123', 'abcABC123'); is_encoding('-._~', '-._~'); is_encoding('%', '%25'); is_encoding('+', '%2B'); is_encoding(' ', '%20'); is_encoding('&=*', '%26%3D%2A'); is_encoding("\x{000A}", '%0A'); is_encoding("\x{0020}", '%20'); is_encoding("\x{007F}", '%7F'); is_encoding("ç", '%C3%A7'); is_encoding("æ", '%C3%A6'); is_encoding("私はガラスを食べられます。それは私を傷つけません。", "%E7%A7%81%E3%81%AF%E3%82%AC%E3%83%A9%E3%82%B9%E3%82%92%E9%A3%9F%E3%81%B9%E3%82%89%E3%82%8C%E3%81%BE%E3%81%99%E3%80%82%E3%81%9D%E3%82%8C%E3%81%AF%E7%A7%81%E3%82%92%E5%82%B7%E3%81%A4%E3%81%91%E3%81%BE%E3%81%9B%E3%82%93%E3%80%82"); warning_like {is_encoding(Encode::encode_utf8("ç"), '%C3%83%C2%A7')} qr/your OAuth message appears to contain some multi-byte characters that need to be decoded/, "Should see warning about characters needing to be decoded"; Net-OAuth-0.32/t/12-xauth.t0000644000175000017500000000445015240167432013042 0ustar rrrr#!perl use strict; use warnings; use Test::More tests => 5; use Net::OAuth; my $request = Net::OAuth->request('xauth access token')->new( consumer_key => 'dpf43f3p2l4k3l03', consumer_secret => 'kd94hf93k423kf44', request_url => 'https://photos.example.net/access_token', request_method => 'POST', signature_method => 'PLAINTEXT', timestamp => '1191242092', nonce => 'dji430splmx33448', token => 'hh5s93j4hdidpola', token_secret => 'hdhd0244k9j7ao03', x_auth_username => 'keeth', x_auth_password => 'foobar', x_auth_mode => 'client_auth', ); $request->sign; ok($request->verify); is($request->to_post_body, 'oauth_consumer_key=dpf43f3p2l4k3l03&oauth_nonce=dji430splmx33448&oauth_signature=kd94hf93k423kf44%26hdhd0244k9j7ao03&oauth_signature_method=PLAINTEXT&oauth_timestamp=1191242092&oauth_version=1.0&x_auth_mode=client_auth&x_auth_password=foobar&x_auth_username=keeth'); eval { $request = Net::OAuth->request('xauth access token')->new( consumer_key => 'dpf43f3p2l4k3l03', consumer_secret => 'kd94hf93k423kf44', request_url => 'https://photos.example.net/access_token', request_method => 'POST', signature_method => 'PLAINTEXT', timestamp => '1191242092', nonce => 'dji430splmx33448', token => 'hh5s93j4hdidpola', token_secret => 'hdhd0244k9j7ao03', ); }; ok($@); $request = Net::OAuth->request('yahoo access token refresh')->new( consumer_key => 'dpf43f3p2l4k3l03', consumer_secret => 'kd94hf93k423kf44', request_url => 'https://photos.example.net/access_token', request_method => 'POST', signature_method => 'HMAC-SHA1', timestamp => '1191242092', nonce => 'dji430splmx33448', token => 'hh5s93j4hdidpola', token_secret => 'hdhd0244k9j7ao03', session_handle => 'this is my session handle', ); $request->sign; ok($request->verify); is($request->to_post_body, 'oauth_consumer_key=dpf43f3p2l4k3l03&oauth_nonce=dji430splmx33448&oauth_session_handle=this%20is%20my%20session%20handle&oauth_signature=cIkNa1a40fmnGuuWVYHWFOrTE3M%3D&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1191242092&oauth_token=hh5s93j4hdidpola&oauth_version=1.0'); Net-OAuth-0.32/t/03-header.t0000644000175000017500000000272515240167432013144 0ustar rrrr#!perl use strict; use warnings; use Test::More tests => 5; BEGIN { use_ok( 'Net::OAuth::Request' ); use_ok( 'Net::OAuth::ProtectedResourceRequest' ); } my $request = Net::OAuth::ProtectedResourceRequest->new( consumer_key => 'dpf43f3p2l4k3l03', consumer_secret => 'kd94hf93k423kf44', request_url => 'http://photos.example.net/photos', request_method => 'GET', signature_method => 'HMAC-SHA1', timestamp => '1191242096', nonce => 'kllo9940pd9333jh', token => 'nnch734d00sl2jdk', token_secret => 'pfkkdhi9sl3r4s00', extra_params => { file => 'vacation.jpg', size => 'original', } ); $request->sign; ok($request->verify); my $header = $request->to_authorization_header('My Realm', ",\n "); is("$header\n",<from_authorization_header( $header, request_method => 'GET', request_url => 'http://photos.example.net/photos', consumer_secret => 'kd94hf93k423kf44', token_secret => 'pfkkdhi9sl3r4s00', extra_params => { file => 'vacation.jpg', size => 'original', }, ); ok($parsed_req->verify);Net-OAuth-0.32/t/05-auth.t0000644000175000017500000000144614733627432012665 0ustar rrrr#!perl use strict; use warnings; use Test::More tests => 6; BEGIN { use Net::OAuth; $Net::OAuth::PROTOCOL_VERSION = Net::OAuth::PROTOCOL_VERSION_1_0; use_ok( 'Net::OAuth::Request' ); use_ok( 'Net::OAuth::Response' ); use_ok( 'Net::OAuth::UserAuthRequest' ); use_ok( 'Net::OAuth::UserAuthResponse' ); } my $request = Net::OAuth::UserAuthRequest->new( token => 'abcdef', callback => 'http://example.com/callback', extra_params => { foo => 'bar', }, ); is($request->to_post_body, 'foo=bar&oauth_callback=http%3A%2F%2Fexample.com%2Fcallback&oauth_token=abcdef'); my $response = Net::OAuth::UserAuthResponse->new( token => 'abcdef', extra_params => { foo => 'bar', }, ); is($response->to_post_body, 'foo=bar&oauth_token=abcdef');Net-OAuth-0.32/t/06-factory.t0000644000175000017500000000615015240167432013362 0ustar rrrruse strict; use warnings; use Test::More tests => 12; BEGIN { use Net::OAuth; $Net::OAuth::PROTOCOL_VERSION = Net::OAuth::PROTOCOL_VERSION_1_0; } my $request = Net::OAuth->request('user auth')->new( token => 'abcdef', callback => 'http://example.com/callback', extra_params => { foo => 'bar', }, ); is($request->to_post_body, 'foo=bar&oauth_callback=http%3A%2F%2Fexample.com%2Fcallback&oauth_token=abcdef'); my $response = Net::OAuth->response('UserAuth')->new( token => 'abcdef', extra_params => { foo => 'bar', }, ); is($response->to_post_body, 'foo=bar&oauth_token=abcdef'); $response = Net::OAuth->response('user_auth')->new( token => 'abcdef', extra_params => { foo => 'bar', }, ); is($response->to_post_body, 'foo=bar&oauth_token=abcdef'); $response = Net::OAuth->message('user authentication response')->new( token => 'abcdef', extra_params => { foo => 'bar', }, ); is($response->to_post_body, 'foo=bar&oauth_token=abcdef'); $request = Net::OAuth->request('Request Token')->from_hash( { oauth_consumer_key => 'dpf43f3p2l4k3l03', oauth_signature_method => 'PLAINTEXT', oauth_timestamp => '1191242090', oauth_nonce => 'hsu94j3884jdopsl', oauth_version => '1.0', }, consumer_secret => 'kd94hf93k423kf44', request_url => 'https://photos.example.net/request_token', request_method => 'POST', ); $request->sign; ok($request->verify); is($request->to_post_body, 'oauth_consumer_key=dpf43f3p2l4k3l03&oauth_nonce=hsu94j3884jdopsl&oauth_signature=kd94hf93k423kf44%26&oauth_signature_method=PLAINTEXT&oauth_timestamp=1191242090&oauth_version=1.0'); $request = Net::OAuth->request('Protected Resource')->from_hash( { oauth_consumer_key => 'dpf43f3p2l4k3l03', oauth_signature_method => 'HMAC-SHA1', oauth_timestamp => '1191242096', oauth_nonce => 'kllo9940pd9333jh', oauth_token => 'nnch734d00sl2jdk', oauth_signature => 'tR3+Ty81lMeYAr/Fid0kMTYa/WM=', oauth_version => '1.0', file => 'vacation.jpg', size => 'original', }, request_url => 'http://photos.example.net/photos', request_method => 'GET', token_secret => 'pfkkdhi9sl3r4s00', consumer_secret => 'kd94hf93k423kf44', ); ok($request->verify); is($request->signature_base_string, 'GET&http%3A%2F%2Fphotos.example.net%2Fphotos&file%3Dvacation.jpg%26oauth_consumer_key%3Ddpf43f3p2l4k3l03%26oauth_nonce%3Dkllo9940pd9333jh%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1191242096%26oauth_token%3Dnnch734d00sl2jdk%26oauth_version%3D1.0%26size%3Doriginal'); is($request->consumer_key, 'dpf43f3p2l4k3l03'); $request->consumer_key('foo'); is($request->consumer_key, 'foo'); is($request->signature_base_string, 'GET&http%3A%2F%2Fphotos.example.net%2Fphotos&file%3Dvacation.jpg%26oauth_consumer_key%3Dfoo%26oauth_nonce%3Dkllo9940pd9333jh%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1191242096%26oauth_token%3Dnnch734d00sl2jdk%26oauth_version%3D1.0%26size%3Doriginal'); eval { Net::OAuth->request('Foo Bar'); }; ok($@, 'should die');Net-OAuth-0.32/t/10-misc.t0000644000175000017500000000362515240167432012645 0ustar rrrruse strict; use warnings; use Test::More tests => 5; BEGIN { use Net::OAuth; $Net::OAuth::PROTOCOL_VERSION = Net::OAuth::PROTOCOL_VERSION_1_0; } my $request = Net::OAuth->request('user auth')->new( token => 'abcdef', callback => 'http://example.com/callback', extra_params => { foo => 'bar', }, ); is($request->to_post_body, 'foo=bar&oauth_callback=http%3A%2F%2Fexample.com%2Fcallback&oauth_token=abcdef'); use URI; my $url = URI->new('http://example.com?bar=baz'); is($request->to_url($url), 'http://example.com?foo=bar&oauth_callback=http%3A%2F%2Fexample.com%2Fcallback&oauth_token=abcdef'); is($url, 'http://example.com?bar=baz'); $request = Net::OAuth->request('Request Token')->new( consumer_key => 'dpf43f3p2l4k3l03', signature_method => 'PLAINTEXT', timestamp => '1191242090', nonce => 'hsu94j3884jdopsl', consumer_secret => 'kd94hf93k423kf44', request_url => 'https://photos.example.net/request_token', request_method => 'GET', extra_params => { foo => 'this value contains spaces' }, ); $request->sign; is($request->to_url(), 'https://photos.example.net/request_token?foo=this%20value%20contains%20spaces&oauth_consumer_key=dpf43f3p2l4k3l03&oauth_nonce=hsu94j3884jdopsl&oauth_signature=kd94hf93k423kf44%26&oauth_signature_method=PLAINTEXT&oauth_timestamp=1191242090&oauth_version=1.0'); # https://rt.cpan.org/Ticket/Display.html?id=47369 # Make sure signature works without oauth_version $request = Net::OAuth->request('request_token')->from_hash( { "oauth_signature" => "lcdJGdH4NRntuelnX+pAoxtIcLY=", "oauth_timestamp" => "1246037243", "oauth_nonce" => "288f21", "oauth_consumer_key" => "myKey", "oauth_signature_method" => "HMAC-SHA1" }, consumer_secret => 'mySecret', request_method => 'POST', request_url => 'http://localhost/provider/request-token.cgi', ); ok($request->verify);Net-OAuth-0.32/t/01-spec.t0000644000175000017500000001301215240167432012633 0ustar rrrr#!perl use strict; use warnings; use Test::More tests => 20; BEGIN { use Net::OAuth; $Net::OAuth::PROTOCOL_VERSION = Net::OAuth::PROTOCOL_VERSION_1_0; use_ok( 'Net::OAuth::Request' ); use_ok( 'Net::OAuth::RequestTokenRequest' ); use_ok( 'Net::OAuth::AccessTokenRequest' ); use_ok( 'Net::OAuth::ProtectedResourceRequest' ); } diag( "Testing Net::OAuth $Net::OAuth::VERSION, Perl $], $^X" ); my $request = Net::OAuth::RequestTokenRequest->new( consumer_key => 'dpf43f3p2l4k3l03', consumer_secret => 'kd94hf93k423kf44', request_url => 'https://photos.example.net/request_token', request_method => 'POST', signature_method => 'PLAINTEXT', timestamp => '1191242090', nonce => 'hsu94j3884jdopsl', ); $request->sign; ok($request->verify); is($request->to_post_body, 'oauth_consumer_key=dpf43f3p2l4k3l03&oauth_nonce=hsu94j3884jdopsl&oauth_signature=kd94hf93k423kf44%26&oauth_signature_method=PLAINTEXT&oauth_timestamp=1191242090&oauth_version=1.0'); sub sort_uri { my $uri = shift; my @uri = split /\?/, $uri; my @query = sort(split(/&/, pop @uri)); return join('?', @uri, join('&', @query)); } is(sort_uri($request->to_url), sort_uri('https://photos.example.net/request_token?oauth_consumer_key=dpf43f3p2l4k3l03&oauth_signature=kd94hf93k423kf44%26&oauth_signature_method=PLAINTEXT&oauth_timestamp=1191242090&oauth_version=1.0&oauth_nonce=hsu94j3884jdopsl')); # fanciness $request = $request->from_url($request->to_url, consumer_secret => 'kd94hf93k423kf44', request_url => 'https://photos.example.net/request_token', request_method => 'POST', ); is(sort_uri($request->to_url('https://someothersite.example.com/request_token')), sort_uri('https://someothersite.example.com/request_token?oauth_consumer_key=dpf43f3p2l4k3l03&oauth_nonce=hsu94j3884jdopsl&oauth_signature=kd94hf93k423kf44%26&oauth_signature_method=PLAINTEXT&oauth_timestamp=1191242090&oauth_version=1.0')); $request = Net::OAuth::AccessTokenRequest->new( consumer_key => 'dpf43f3p2l4k3l03', consumer_secret => 'kd94hf93k423kf44', request_url => 'https://photos.example.net/access_token', request_method => 'POST', signature_method => 'PLAINTEXT', timestamp => '1191242092', nonce => 'dji430splmx33448', token => 'hh5s93j4hdidpola', token_secret => 'hdhd0244k9j7ao03', ); $request->sign; ok($request->verify); is($request->to_post_body, 'oauth_consumer_key=dpf43f3p2l4k3l03&oauth_nonce=dji430splmx33448&oauth_signature=kd94hf93k423kf44%26hdhd0244k9j7ao03&oauth_signature_method=PLAINTEXT&oauth_timestamp=1191242092&oauth_token=hh5s93j4hdidpola&oauth_version=1.0'); $request = Net::OAuth::ProtectedResourceRequest->new( consumer_key => 'dpf43f3p2l4k3l03', consumer_secret => 'kd94hf93k423kf44', request_url => 'http://photos.example.net/photos', request_method => 'GET', signature_method => 'HMAC-SHA1', timestamp => '1191242096', nonce => 'kllo9940pd9333jh', token => 'nnch734d00sl2jdk', token_secret => 'pfkkdhi9sl3r4s00', extra_params => { file => 'vacation.jpg', size => 'original', } ); $request->sign; ok($request->verify); is($request->signature_base_string, 'GET&http%3A%2F%2Fphotos.example.net%2Fphotos&file%3Dvacation.jpg%26oauth_consumer_key%3Ddpf43f3p2l4k3l03%26oauth_nonce%3Dkllo9940pd9333jh%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1191242096%26oauth_token%3Dnnch734d00sl2jdk%26oauth_version%3D1.0%26size%3Doriginal'); is($request->signature, 'tR3+Ty81lMeYAr/Fid0kMTYa/WM='); is($request->to_authorization_header('http://photos.example.net/authorize', ",\n")."\n", <new( consumer_key => 'dpf43f3p2l4k3l03', consumer_secret => 'kd94hf93k423kf44', request_url => 'https://photos.example.net/request_token', request_method => 'POST', signature_method => 'HMAC-SHA1', timestamp => '1191242090', nonce => 'hsu94j3884jdopsl', ); $request->sign; ok($request->verify); is($request->signature_base_string, 'POST&https%3A%2F%2Fphotos.example.net%2Frequest_token&oauth_consumer_key%3Ddpf43f3p2l4k3l03%26oauth_nonce%3Dhsu94j3884jdopsl%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1191242090%26oauth_version%3D1.0'); is($request->signature, 'mBRi0bX78DgCdolSsSYibIGen7U='); $request = Net::OAuth::ProtectedResourceRequest->new( consumer_key => 'dpf43f3p2l4k3l03', consumer_secret => 'kd94hf93k423kf44', request_url => 'http://photos.example.net/photos?file=vacation.jpg&size=original', request_method => 'GET', signature_method => 'HMAC-SHA1', timestamp => '1191242096', nonce => 'kllo9940pd9333jh', token => 'nnch734d00sl2jdk', token_secret => 'pfkkdhi9sl3r4s00', ); $request->sign; ok($request->verify); is($request->signature_base_string, 'GET&http%3A%2F%2Fphotos.example.net%2Fphotos&file%3Dvacation.jpg%26oauth_consumer_key%3Ddpf43f3p2l4k3l03%26oauth_nonce%3Dkllo9940pd9333jh%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1191242096%26oauth_token%3Dnnch734d00sl2jdk%26oauth_version%3D1.0%26size%3Doriginal'); is($request->signature, 'tR3+Ty81lMeYAr/Fid0kMTYa/WM='); Net-OAuth-0.32/t/11-spec-1.0a.t0000644000175000017500000002072215240167432013277 0ustar rrrr#!perl use strict; use warnings; use Test::More tests => 28; use Carp 'confess'; $SIG{__DIE__} = \&confess; BEGIN { use Net::OAuth; $Net::OAuth::PROTOCOL_VERSION = Net::OAuth::PROTOCOL_VERSION_1_0A; use_ok( 'Net::OAuth::Request' ); use_ok( 'Net::OAuth::RequestTokenRequest' ); use_ok( 'Net::OAuth::AccessTokenRequest' ); use_ok( 'Net::OAuth::ProtectedResourceRequest' ); } my $request = Net::OAuth::RequestTokenRequest->new( consumer_key => 'dpf43f3p2l4k3l03', consumer_secret => 'kd94hf93k423kf44', request_url => 'https://photos.example.net/request_token', request_method => 'POST', signature_method => 'PLAINTEXT', timestamp => '1191242090', nonce => 'hsu94j3884jdopsl', callback => 'http://printer.example.com/request_token_ready', ); $request->sign; ok($request->verify); ok($request->isa('Net::OAuth::V1_0A::RequestTokenRequest')); eval { Net::OAuth::RequestTokenRequest->new( consumer_key => 'dpf43f3p2l4k3l03', consumer_secret => 'kd94hf93k423kf44', request_url => 'https://photos.example.net/request_token', request_method => 'POST', signature_method => 'PLAINTEXT', timestamp => '1191242090', nonce => 'hsu94j3884jdopsl', ); }; ok($@, 'should complain about missing callback parameter'); my $v1req; eval { $v1req = Net::OAuth::RequestTokenRequest->new( consumer_key => 'dpf43f3p2l4k3l03', consumer_secret => 'kd94hf93k423kf44', request_url => 'https://photos.example.net/request_token', request_method => 'POST', signature_method => 'PLAINTEXT', timestamp => '1191242090', nonce => 'hsu94j3884jdopsl', protocol_version => Net::OAuth::PROTOCOL_VERSION_1_0, ); }; ok(!$@, 'override default protocol version to produce v1.0 message'); ok(!$v1req->isa('Net::OAuth::V1_0A::RequestTokenRequest')); sub sort_uri { my $uri = shift; my @uri = split /\?/, $uri; my @query = sort(split(/&/, pop @uri)); return join('?', @uri, join('&', @query)); } is(sort_uri($request->to_post_body), sort_uri('oauth_callback=http%3A%2F%2Fprinter.example.com%2Frequest_token_ready&oauth_consumer_key=dpf43f3p2l4k3l03&oauth_nonce=hsu94j3884jdopsl&oauth_signature=kd94hf93k423kf44%26&oauth_signature_method=PLAINTEXT&oauth_timestamp=1191242090&oauth_version=1.0')); is(sort_uri($request->to_url), sort_uri('https://photos.example.net/request_token?oauth_callback=http%3A%2F%2Fprinter.example.com%2Frequest_token_ready&oauth_consumer_key=dpf43f3p2l4k3l03&oauth_signature_method=PLAINTEXT&oauth_signature=kd94hf93k423kf44%26&oauth_timestamp=1191242090&oauth_nonce=hsu94j3884jdopsl&oauth_version=1.0')); # fanciness $request = $request->from_url($request->to_url, consumer_secret => 'kd94hf93k423kf44', request_url => 'https://photos.example.net/request_token', request_method => 'POST', ); is(sort_uri($request->to_url('https://someothersite.example.com/request_token')), sort_uri('https://someothersite.example.com/request_token?oauth_callback=http%3A%2F%2Fprinter.example.com%2Frequest_token_ready&oauth_consumer_key=dpf43f3p2l4k3l03&oauth_signature_method=PLAINTEXT&oauth_signature=kd94hf93k423kf44%26&oauth_timestamp=1191242090&oauth_nonce=hsu94j3884jdopsl&oauth_version=1.0')); $request = Net::OAuth::AccessTokenRequest->new( consumer_key => 'dpf43f3p2l4k3l03', consumer_secret => 'kd94hf93k423kf44', request_url => 'https://photos.example.net/access_token', request_method => 'POST', signature_method => 'PLAINTEXT', timestamp => '1191242092', nonce => 'dji430splmx33448', token => 'hh5s93j4hdidpola', token_secret => 'hdhd0244k9j7ao03', verifier => 'hfdp7dh39dks9884', ); $request->sign; ok($request->verify); eval { Net::OAuth::AccessTokenRequest->new( consumer_key => 'dpf43f3p2l4k3l03', consumer_secret => 'kd94hf93k423kf44', request_url => 'https://photos.example.net/access_token', request_method => 'POST', signature_method => 'PLAINTEXT', timestamp => '1191242092', nonce => 'dji430splmx33448', token => 'hh5s93j4hdidpola', token_secret => 'hdhd0244k9j7ao03', ); }; ok($@); is(sort_uri($request->to_post_body), sort_uri('oauth_consumer_key=dpf43f3p2l4k3l03&oauth_token=hh5s93j4hdidpola&oauth_signature_method=PLAINTEXT&oauth_signature=kd94hf93k423kf44%26hdhd0244k9j7ao03&oauth_timestamp=1191242092&oauth_nonce=dji430splmx33448&oauth_verifier=hfdp7dh39dks9884&oauth_version=1.0')); $request = Net::OAuth::ProtectedResourceRequest->new( consumer_key => 'dpf43f3p2l4k3l03', consumer_secret => 'kd94hf93k423kf44', request_url => 'http://photos.example.net/photos', request_method => 'GET', signature_method => 'HMAC-SHA1', timestamp => '1191242096', nonce => 'kllo9940pd9333jh', token => 'nnch734d00sl2jdk', token_secret => 'pfkkdhi9sl3r4s00', extra_params => { file => 'vacation.jpg', size => 'original', } ); $request->sign; ok($request->verify); is($request->signature_base_string, 'GET&http%3A%2F%2Fphotos.example.net%2Fphotos&file%3Dvacation.jpg%26oauth_consumer_key%3Ddpf43f3p2l4k3l03%26oauth_nonce%3Dkllo9940pd9333jh%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1191242096%26oauth_token%3Dnnch734d00sl2jdk%26oauth_version%3D1.0%26size%3Doriginal'); is($request->signature, 'tR3+Ty81lMeYAr/Fid0kMTYa/WM='); is($request->to_authorization_header('http://photos.example.net/authorize', ",\n")."\n", <new( consumer_key => 'dpf43f3p2l4k3l03', consumer_secret => 'kd94hf93k423kf44', request_url => 'https://photos.example.net/request_token', request_method => 'POST', signature_method => 'HMAC-SHA1', timestamp => '1191242090', nonce => 'hsu94j3884jdopsl', callback => 'http://printer.example.com/request_token_ready', ); $request->sign; ok($request->verify); is($request->signature_base_string, 'POST&https%3A%2F%2Fphotos.example.net%2Frequest_token&oauth_callback%3Dhttp%253A%252F%252Fprinter.example.com%252Frequest_token_ready%26oauth_consumer_key%3Ddpf43f3p2l4k3l03%26oauth_nonce%3Dhsu94j3884jdopsl%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1191242090%26oauth_version%3D1.0'); is($request->signature, 'Uzhous9sjMdWH6Gte4VToiNQtMc='); $request = Net::OAuth::ProtectedResourceRequest->new( consumer_key => 'dpf43f3p2l4k3l03', consumer_secret => 'kd94hf93k423kf44', request_url => 'http://photos.example.net/photos?file=vacation.jpg&size=original', request_method => 'GET', signature_method => 'HMAC-SHA1', timestamp => '1191242096', nonce => 'kllo9940pd9333jh', token => 'nnch734d00sl2jdk', token_secret => 'pfkkdhi9sl3r4s00', ); $request->sign; ok($request->verify); is($request->signature_base_string, 'GET&http%3A%2F%2Fphotos.example.net%2Fphotos&file%3Dvacation.jpg%26oauth_consumer_key%3Ddpf43f3p2l4k3l03%26oauth_nonce%3Dkllo9940pd9333jh%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1191242096%26oauth_token%3Dnnch734d00sl2jdk%26oauth_version%3D1.0%26size%3Doriginal'); is($request->signature, 'tR3+Ty81lMeYAr/Fid0kMTYa/WM='); # Message->from_hash should validate the message using the correct class # https://rt.cpan.org/Public/Bug/Display.html?id=47293 $Net::OAuth::PROTOCOL_VERSION = Net::OAuth::PROTOCOL_VERSION_1_0; my $response = eval { Net::OAuth->response('request token') ->from_post_body('oauth_token=abc&oauth_token_secret=def&oauth_callback_confirmed=true') }; ok($@); $response = Net::OAuth->response('request token') ->from_post_body('oauth_token=abc&oauth_token_secret=def&oauth_callback_confirmed=true', protocol_version => Net::OAuth::PROTOCOL_VERSION_1_0A ); ok($response); $Net::OAuth::PROTOCOL_VERSION = Net::OAuth::PROTOCOL_VERSION_1_0A; $response = Net::OAuth->response('request token') ->from_post_body('oauth_token=abc&oauth_token_secret=def&oauth_callback_confirmed=true'); ok($response);Net-OAuth-0.32/Makefile.PL0000644000175000017500000000455615240175617013026 0ustar rrrr# Note: this file was auto-generated by Module::Build::Compat version 0.4234 use ExtUtils::MakeMaker; WriteMakefile( 'NAME' => 'Net::OAuth', 'AUTHOR' => [ 'Keith Grennan ', 'Robert Rothenberg ', ], "LICENSE" => 'perl', 'ABSTRACT_FROM' => 'lib/Net/OAuth.pm', 'VERSION_FROM' => 'lib/Net/OAuth.pm', 'TEST_REQUIRES' => { 'Test::More' => '0.66', 'Test::Warn' => '0.21', }, 'PREREQ_PM' => { 'Class::Accessor' => '0.31', 'Class::Data::Inheritable' => '0.06', 'Crypt::SysRandom' => '0.006', 'Digest::SHA' => '5.47', 'Encode' => '2.35', 'LWP::UserAgent' => '1', 'Test::More' => '0.66', 'Test::Warn' => '0.21', 'URI' => '5.15' }, # The source itself parses as 5.006, but URI and MIME::Base32 both require # 5.008001, so that is the real floor. CI covers 5.16 and up; anything # older is supported-but-untested rather than known-broken. 'MIN_PERL_VERSION' => '5.008001', 'INSTALLDIRS' => 'site', 'EXE_FILES' => [], 'PL_FILES' => {}, 'META_MERGE' => { # Deliberately meta-spec 1.4 shaped. A spec 2 "prereqs" key here does # not merge on ExtUtils::MakeMaker older than 7.x -- it replaces the # generated prereqs wholesale, silently dropping every runtime and # test requirement from META. Perl 5.16 ships 6.63_02, so that is a # live configuration. A top level "recommends" sits beside "requires" # instead of overwriting it, and newer toolchains still convert it to # prereqs.runtime.recommends in the spec 2 output. # # Only RSA-SHA1 needs this, hence a recommends rather than a hard # prereq. 0.38 is a floor rather than a preference: 0.35 through 0.37 # disabled the PKCS#1 v1.5 padding that RFC 5849 3.4.3 mandates, and # 0.38 re-enabled it. recommends => { 'Crypt::OpenSSL::RSA' => '0.38', 'Crypt::SysRandom::XS' => '0.010', }, resources => { bugtracker => 'https://rt.cpan.org/Public/Dist/Display.html?Name=Net-OAuth', repository => 'https://github.com/keeth/Net-OAuth.git', }, }, );