Am I generating the OAuth signature incorrectly or is there another issue with this Perl / OAuth client code?
OK, I'm going nuts here. I've spent the better part of a week working on this with Fiddler, Rest API Log, Apache logs, Postman, etc. and am no closer to a solution. Hopefully this will provide someone with a good laugh (as it's easy) and me with a solution (for my sanity).
I have a Wordpress 4.9.8 install hosted on hostgator. I have the WP REST API - OAuth 1.0a Server plugin installed and am attempting to authenticate with OAuth from a Perl script. I've been successful connecting with Postman using the credential generated by registering an application in the UI (Wordpress > Users > Applications) but cannot seem to crack the code using curl or a perl script (or php or anything else I've tried). As Postman works (whenever it does not generate a space in the OAuth signature) I believe the plugin does, in fact, work. Below is my code where I've attempted to follow the spec regarding parameters, sorting, URI encoding, utf8 encoding, etc. Everything 'looks' ok when examining headers/query params in either Fiddle or the REST API Log plugin (pretty great little tool, that) and yet, no love.
Thanks for any advice or direction.
Client code:
#!/usr/bin/perl
use strict;
use warnings;
use LWP::UserAgent;
use JSON;
use URI::Escape;
use Digest::HMAC_SHA1 qw( hmac_sha1 );
use MIME::Base64 qw( encode_base64 );
use Encode;
use Data::Dumper;
my $timestamp = time();
my $method = 'GET';
my $url = "https://hoppingmadmonkey.com/wp-json/myapiplugin/v2/greeting";
my $client_secret = "GelrnAAr1nCe5fzmTqzrU82PsfKCmKlDOZrLPakQRkH4sizJ";
my $token_secret = "mdeVuJnrs8VSDJNJfMNPQRqBkG8xadfK0jAYjDGhmKOeaY7O";
#my $nonce = $ARGV[0]; # test with Postman generated parameters
#$timestamp = $ARGV[1]; # test with Postman generated parameters
#my $signature = $ARGV[2]; # test with Postman generated parameters
my %params = (
oauth_consumer_key => "NCo8bflKU9LI",
oauth_signature_method => "HMAC-SHA1",
oauth_realm => "https://hoppingmadmonkey.com",
oauth_timestamp => $timestamp,
oauth_token => "2GeFG7MkXliq2OBOSSCSRBPX",
oauth_version => "1.0",
);
$paramsoauth_nonce = create_nonce();
#$paramsoauth_nonce = $nonce; # test with Postman generated parameters
$paramsoauth_timestamp = $timestamp;
my $key = create_key($client_secret,$token_secret);
my ($params,$base) = build_base_string($method, $url, %params);
my $signature = create_signature($base, $key);
#for (sort keys %params) print "$_=$params$_", "n";
print "params: $paramsnn";
print "basestring: $basenn";
print "key: $keynn";
print "signature [$signature]nn";
$paramsoauth_signature = $signature; # -- set signature for GET query string
my $request_string = build_request_string($url,%params);
print "nrequest_string [$request_string]nn";
my $ua = LWP::UserAgent->new();
$ua->default_header("Authorization", "Basic user:pass");
my $response = $ua->get($request_string);
print Dumper $response, "n";
exit;
my $curlcmd = qq/usr/bin/curl -i -X GET "$request_string";
#`$curlcmd 2>&1`;
sub create_signature
my ($t,$k) = @_;
my $str = encode_base64(hmac_sha1($t,$k));
chomp $str;
return $str;
# Create unique nonce
#
sub create_nonce
my $str = `/bin/cat /dev/urandom
# Create oauth key for generating hmac-sha1 signature
#
sub create_key
my ($cs,$ts) = @_;
$cs = encode('utf8',uri_escape($cs));
$ts = encode('utf8',uri_escape($ts));
return "$cs&$ts";
# Build basestring for generating hmac-sha1 signature
#
sub build_request_string
my ($u,$p) = @_;
my %params = %$p;
my $str = $u . '?';
my @tmp;
for (sort keys %params)
$p = uri_escape($_) . '=' . uri_escape($params$_);
push @tmp, $p;
$str .= join '&', @tmp;
return $str;
# build the base string parameter for creating the signature
#
sub build_base_string
my ($m,$u,$phash) = @_;
my %params = %$phash;
my $str = $method;
$str .= '&' . uri_escape($u) . '&';
my @tmp;
for (sort keys %params)
push @tmp, uri_escape("$_=$params$_");
$params = join '&', @tmp;
$str .= join '&', @tmp;
return $params,$str;
1;
The result of running this from the command line is:
dnu [test] ::>./oauth-perl.pl
params: oauth_consumer_key%3DNCo8bflKU9LI&oauth_nonce%3DJrGdlVLXpB4&oauth_realm%3Dhttps%3A%2F%2Fhoppingmadmonkey.com&oauth_signature_method%3DHMAC-SHA1&oauth_timestamp%3D1542134239&oauth_token%3D2GeFG7MkXliq2OBOSSCSRBPX&oauth_version%3D1.0
basestring: GET&https%3A%2F%2Fhoppingmadmonkey.com%2Fwp-json%2Fmyapiplugin%2Fv2%2Fgreeting&oauth_consumer_key%3DNCo8bflKU9LI&oauth_nonce%3DJrGdlVLXpB4&oauth_realm%3Dhttps%3A%2F%2Fhoppingmadmonkey.com&oauth_signature_method%3DHMAC-SHA1&oauth_timestamp%3D1542134239&oauth_token%3D2GeFG7MkXliq2OBOSSCSRBPX&oauth_version%3D1.0
key: GelrnAAr1nCe5fzmTqzrU82PsfKCmKlDOZrLPakQRkH4sizJ&mdeVuJnrs8VSDJNJfMNPQRqBkG8xadfK0jAYjDGhmKOeaY7O
signature [2pJRR1fz0uUdUWHlUjHFWlXFbL4=]
request_string [https://hoppingmadmonkey.com/wp-json/myapiplugin/v2/greeting?oauth_consumer_key=NCo8bflKU9LI&oauth_nonce=JrGdlVLXpB4&oauth_realm=https%3A%2F%2Fhoppingmadmonkey.com&oauth_signature=2pJRR1fz0uUdUWHlUjHFWlXFbL4%3D&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1542134239&oauth_token=2GeFG7MkXliq2OBOSSCSRBPX&oauth_version=1.0]
$VAR1 = bless(
'_protocol' => 'HTTP/1.1',
'_content' => '
"code":"json_oauth1_signature_mismatch","message":"OAuth signature does not match","data":"status":401',
'_rc' => '401',
'_headers' => bless(
'connection' => 'close',
'cache-control' => 'no-cache, must-revalidate, max-age=0',
'date' => 'Tue, 13 Nov 2018 18:37:19 GMT',
'client-ssl-cert-issuer' => '/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Domain Validation Secure Server CA',
'client-ssl-cipher' => 'ECDHE-RSA-AES256-GCM-SHA384',
'client-peer' => '192.185.236.193:443',
'access-control-expose-headers' => 'X-WP-Total, X-WP-TotalPages',
'x-robots-tag' => 'noindex',
'client-warning' => 'Missing Authenticate header',
'client-date' => 'Tue, 13 Nov 2018 18:37:22 GMT',
'client-ssl-warning' => 'Peer certificate not verified',
'content-type' => 'application/json; charset=UTF-8',
'client-transfer-encoding' => [
'chunked'
],
'server' => 'Apache',
'x-endurance-cache-level' => '2',
'client-ssl-socket-class' => 'IO::Socket::SSL',
'link' => '<https://hoppingmadmonkey.com/index.php/wp-json/>; rel="https://api.w.org/"',
'access-control-allow-headers' => 'Authorization, Content-Type',
'client-response-num' => 1,
'x-content-type-options' => 'nosniff',
'client-ssl-cert-subject' => '/OU=Domain Control Validated/OU=Hosted by HostGator.com, LLC./OU=PositiveSSL Wildcard/CN=*.hostgator.com',
'expires' => 'Wed, 11 Jan 1984 05:00:00 GMT'
, 'HTTP::Headers' ),
'_msg' => 'Unauthorized',
'_request' => bless(
'_content' => '',
'_uri' => bless( do(my $o = 'https://hoppingmadmonkey.com/wp-json/myapiplugin/v2/greeting?oauth_consumer_key=NCo8bflKU9LI&oauth_nonce=JrGdlVLXpB4&oauth_realm=https%3A%2F%2Fhoppingmadmonkey.com&oauth_signature=2pJRR1fz0uUdUWHlUjHFWlXFbL4%3D&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1542134239&oauth_token=2GeFG7MkXliq2OBOSSCSRBPX&oauth_version=1.0'), 'URI::https' ),
'_headers' => bless(
'user-agent' => 'libwww-perl/5.833',
'authorization' => 'Basic user:pass'
, 'HTTP::Headers' ),
'_method' => 'GET',
'_uri_canonical' => bless( do(my $o = 'https://hoppingmadmonkey.com/wp-json/myapiplugin/v2/greeting?oauth_consumer_key=NCo8bflKU9LI&oauth_nonce=JrGdlVLXpB4&oauth_realm=https%3A%2F%2Fhoppingmadmonkey.com&oauth_signature=2pJRR1fz0uUdUWHlUjHFWlXFbL4%3D&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1542134239&oauth_token=2GeFG7MkXliq2OBOSSCSRBPX&oauth_version=1.0'), 'URI::https' )
, 'HTTP::Request' )
, 'HTTP::Response' );
$VAR2 = '
';
In the interests of expedience, I've included my real secrets and website. It's all test at the moment. Feel free to try a solution if you have that kind of time on your hands. I can always invalidate the tokens if/when they get abused and will obviously change once/if I can understand the problem.
The obvious thought is that I am not generating the signature correctly (Big Hint:
"code":"json_oauth1_signature_mismatch","message":"OAuth signature does not match","data":"status":401',
)
I think I've ready everything on the entire Internet to no avail. Thanks in advance for any thoughts. And if you are near Atlanta, GA and help me out, the beer's on me.
Cheers.
wordpress perl oauth signature
add a comment |
OK, I'm going nuts here. I've spent the better part of a week working on this with Fiddler, Rest API Log, Apache logs, Postman, etc. and am no closer to a solution. Hopefully this will provide someone with a good laugh (as it's easy) and me with a solution (for my sanity).
I have a Wordpress 4.9.8 install hosted on hostgator. I have the WP REST API - OAuth 1.0a Server plugin installed and am attempting to authenticate with OAuth from a Perl script. I've been successful connecting with Postman using the credential generated by registering an application in the UI (Wordpress > Users > Applications) but cannot seem to crack the code using curl or a perl script (or php or anything else I've tried). As Postman works (whenever it does not generate a space in the OAuth signature) I believe the plugin does, in fact, work. Below is my code where I've attempted to follow the spec regarding parameters, sorting, URI encoding, utf8 encoding, etc. Everything 'looks' ok when examining headers/query params in either Fiddle or the REST API Log plugin (pretty great little tool, that) and yet, no love.
Thanks for any advice or direction.
Client code:
#!/usr/bin/perl
use strict;
use warnings;
use LWP::UserAgent;
use JSON;
use URI::Escape;
use Digest::HMAC_SHA1 qw( hmac_sha1 );
use MIME::Base64 qw( encode_base64 );
use Encode;
use Data::Dumper;
my $timestamp = time();
my $method = 'GET';
my $url = "https://hoppingmadmonkey.com/wp-json/myapiplugin/v2/greeting";
my $client_secret = "GelrnAAr1nCe5fzmTqzrU82PsfKCmKlDOZrLPakQRkH4sizJ";
my $token_secret = "mdeVuJnrs8VSDJNJfMNPQRqBkG8xadfK0jAYjDGhmKOeaY7O";
#my $nonce = $ARGV[0]; # test with Postman generated parameters
#$timestamp = $ARGV[1]; # test with Postman generated parameters
#my $signature = $ARGV[2]; # test with Postman generated parameters
my %params = (
oauth_consumer_key => "NCo8bflKU9LI",
oauth_signature_method => "HMAC-SHA1",
oauth_realm => "https://hoppingmadmonkey.com",
oauth_timestamp => $timestamp,
oauth_token => "2GeFG7MkXliq2OBOSSCSRBPX",
oauth_version => "1.0",
);
$paramsoauth_nonce = create_nonce();
#$paramsoauth_nonce = $nonce; # test with Postman generated parameters
$paramsoauth_timestamp = $timestamp;
my $key = create_key($client_secret,$token_secret);
my ($params,$base) = build_base_string($method, $url, %params);
my $signature = create_signature($base, $key);
#for (sort keys %params) print "$_=$params$_", "n";
print "params: $paramsnn";
print "basestring: $basenn";
print "key: $keynn";
print "signature [$signature]nn";
$paramsoauth_signature = $signature; # -- set signature for GET query string
my $request_string = build_request_string($url,%params);
print "nrequest_string [$request_string]nn";
my $ua = LWP::UserAgent->new();
$ua->default_header("Authorization", "Basic user:pass");
my $response = $ua->get($request_string);
print Dumper $response, "n";
exit;
my $curlcmd = qq/usr/bin/curl -i -X GET "$request_string";
#`$curlcmd 2>&1`;
sub create_signature
my ($t,$k) = @_;
my $str = encode_base64(hmac_sha1($t,$k));
chomp $str;
return $str;
# Create unique nonce
#
sub create_nonce
my $str = `/bin/cat /dev/urandom
# Create oauth key for generating hmac-sha1 signature
#
sub create_key
my ($cs,$ts) = @_;
$cs = encode('utf8',uri_escape($cs));
$ts = encode('utf8',uri_escape($ts));
return "$cs&$ts";
# Build basestring for generating hmac-sha1 signature
#
sub build_request_string
my ($u,$p) = @_;
my %params = %$p;
my $str = $u . '?';
my @tmp;
for (sort keys %params)
$p = uri_escape($_) . '=' . uri_escape($params$_);
push @tmp, $p;
$str .= join '&', @tmp;
return $str;
# build the base string parameter for creating the signature
#
sub build_base_string
my ($m,$u,$phash) = @_;
my %params = %$phash;
my $str = $method;
$str .= '&' . uri_escape($u) . '&';
my @tmp;
for (sort keys %params)
push @tmp, uri_escape("$_=$params$_");
$params = join '&', @tmp;
$str .= join '&', @tmp;
return $params,$str;
1;
The result of running this from the command line is:
dnu [test] ::>./oauth-perl.pl
params: oauth_consumer_key%3DNCo8bflKU9LI&oauth_nonce%3DJrGdlVLXpB4&oauth_realm%3Dhttps%3A%2F%2Fhoppingmadmonkey.com&oauth_signature_method%3DHMAC-SHA1&oauth_timestamp%3D1542134239&oauth_token%3D2GeFG7MkXliq2OBOSSCSRBPX&oauth_version%3D1.0
basestring: GET&https%3A%2F%2Fhoppingmadmonkey.com%2Fwp-json%2Fmyapiplugin%2Fv2%2Fgreeting&oauth_consumer_key%3DNCo8bflKU9LI&oauth_nonce%3DJrGdlVLXpB4&oauth_realm%3Dhttps%3A%2F%2Fhoppingmadmonkey.com&oauth_signature_method%3DHMAC-SHA1&oauth_timestamp%3D1542134239&oauth_token%3D2GeFG7MkXliq2OBOSSCSRBPX&oauth_version%3D1.0
key: GelrnAAr1nCe5fzmTqzrU82PsfKCmKlDOZrLPakQRkH4sizJ&mdeVuJnrs8VSDJNJfMNPQRqBkG8xadfK0jAYjDGhmKOeaY7O
signature [2pJRR1fz0uUdUWHlUjHFWlXFbL4=]
request_string [https://hoppingmadmonkey.com/wp-json/myapiplugin/v2/greeting?oauth_consumer_key=NCo8bflKU9LI&oauth_nonce=JrGdlVLXpB4&oauth_realm=https%3A%2F%2Fhoppingmadmonkey.com&oauth_signature=2pJRR1fz0uUdUWHlUjHFWlXFbL4%3D&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1542134239&oauth_token=2GeFG7MkXliq2OBOSSCSRBPX&oauth_version=1.0]
$VAR1 = bless(
'_protocol' => 'HTTP/1.1',
'_content' => '
"code":"json_oauth1_signature_mismatch","message":"OAuth signature does not match","data":"status":401',
'_rc' => '401',
'_headers' => bless(
'connection' => 'close',
'cache-control' => 'no-cache, must-revalidate, max-age=0',
'date' => 'Tue, 13 Nov 2018 18:37:19 GMT',
'client-ssl-cert-issuer' => '/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Domain Validation Secure Server CA',
'client-ssl-cipher' => 'ECDHE-RSA-AES256-GCM-SHA384',
'client-peer' => '192.185.236.193:443',
'access-control-expose-headers' => 'X-WP-Total, X-WP-TotalPages',
'x-robots-tag' => 'noindex',
'client-warning' => 'Missing Authenticate header',
'client-date' => 'Tue, 13 Nov 2018 18:37:22 GMT',
'client-ssl-warning' => 'Peer certificate not verified',
'content-type' => 'application/json; charset=UTF-8',
'client-transfer-encoding' => [
'chunked'
],
'server' => 'Apache',
'x-endurance-cache-level' => '2',
'client-ssl-socket-class' => 'IO::Socket::SSL',
'link' => '<https://hoppingmadmonkey.com/index.php/wp-json/>; rel="https://api.w.org/"',
'access-control-allow-headers' => 'Authorization, Content-Type',
'client-response-num' => 1,
'x-content-type-options' => 'nosniff',
'client-ssl-cert-subject' => '/OU=Domain Control Validated/OU=Hosted by HostGator.com, LLC./OU=PositiveSSL Wildcard/CN=*.hostgator.com',
'expires' => 'Wed, 11 Jan 1984 05:00:00 GMT'
, 'HTTP::Headers' ),
'_msg' => 'Unauthorized',
'_request' => bless(
'_content' => '',
'_uri' => bless( do(my $o = 'https://hoppingmadmonkey.com/wp-json/myapiplugin/v2/greeting?oauth_consumer_key=NCo8bflKU9LI&oauth_nonce=JrGdlVLXpB4&oauth_realm=https%3A%2F%2Fhoppingmadmonkey.com&oauth_signature=2pJRR1fz0uUdUWHlUjHFWlXFbL4%3D&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1542134239&oauth_token=2GeFG7MkXliq2OBOSSCSRBPX&oauth_version=1.0'), 'URI::https' ),
'_headers' => bless(
'user-agent' => 'libwww-perl/5.833',
'authorization' => 'Basic user:pass'
, 'HTTP::Headers' ),
'_method' => 'GET',
'_uri_canonical' => bless( do(my $o = 'https://hoppingmadmonkey.com/wp-json/myapiplugin/v2/greeting?oauth_consumer_key=NCo8bflKU9LI&oauth_nonce=JrGdlVLXpB4&oauth_realm=https%3A%2F%2Fhoppingmadmonkey.com&oauth_signature=2pJRR1fz0uUdUWHlUjHFWlXFbL4%3D&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1542134239&oauth_token=2GeFG7MkXliq2OBOSSCSRBPX&oauth_version=1.0'), 'URI::https' )
, 'HTTP::Request' )
, 'HTTP::Response' );
$VAR2 = '
';
In the interests of expedience, I've included my real secrets and website. It's all test at the moment. Feel free to try a solution if you have that kind of time on your hands. I can always invalidate the tokens if/when they get abused and will obviously change once/if I can understand the problem.
The obvious thought is that I am not generating the signature correctly (Big Hint:
"code":"json_oauth1_signature_mismatch","message":"OAuth signature does not match","data":"status":401',
)
I think I've ready everything on the entire Internet to no avail. Thanks in advance for any thoughts. And if you are near Atlanta, GA and help me out, the beer's on me.
Cheers.
wordpress perl oauth signature
add a comment |
OK, I'm going nuts here. I've spent the better part of a week working on this with Fiddler, Rest API Log, Apache logs, Postman, etc. and am no closer to a solution. Hopefully this will provide someone with a good laugh (as it's easy) and me with a solution (for my sanity).
I have a Wordpress 4.9.8 install hosted on hostgator. I have the WP REST API - OAuth 1.0a Server plugin installed and am attempting to authenticate with OAuth from a Perl script. I've been successful connecting with Postman using the credential generated by registering an application in the UI (Wordpress > Users > Applications) but cannot seem to crack the code using curl or a perl script (or php or anything else I've tried). As Postman works (whenever it does not generate a space in the OAuth signature) I believe the plugin does, in fact, work. Below is my code where I've attempted to follow the spec regarding parameters, sorting, URI encoding, utf8 encoding, etc. Everything 'looks' ok when examining headers/query params in either Fiddle or the REST API Log plugin (pretty great little tool, that) and yet, no love.
Thanks for any advice or direction.
Client code:
#!/usr/bin/perl
use strict;
use warnings;
use LWP::UserAgent;
use JSON;
use URI::Escape;
use Digest::HMAC_SHA1 qw( hmac_sha1 );
use MIME::Base64 qw( encode_base64 );
use Encode;
use Data::Dumper;
my $timestamp = time();
my $method = 'GET';
my $url = "https://hoppingmadmonkey.com/wp-json/myapiplugin/v2/greeting";
my $client_secret = "GelrnAAr1nCe5fzmTqzrU82PsfKCmKlDOZrLPakQRkH4sizJ";
my $token_secret = "mdeVuJnrs8VSDJNJfMNPQRqBkG8xadfK0jAYjDGhmKOeaY7O";
#my $nonce = $ARGV[0]; # test with Postman generated parameters
#$timestamp = $ARGV[1]; # test with Postman generated parameters
#my $signature = $ARGV[2]; # test with Postman generated parameters
my %params = (
oauth_consumer_key => "NCo8bflKU9LI",
oauth_signature_method => "HMAC-SHA1",
oauth_realm => "https://hoppingmadmonkey.com",
oauth_timestamp => $timestamp,
oauth_token => "2GeFG7MkXliq2OBOSSCSRBPX",
oauth_version => "1.0",
);
$paramsoauth_nonce = create_nonce();
#$paramsoauth_nonce = $nonce; # test with Postman generated parameters
$paramsoauth_timestamp = $timestamp;
my $key = create_key($client_secret,$token_secret);
my ($params,$base) = build_base_string($method, $url, %params);
my $signature = create_signature($base, $key);
#for (sort keys %params) print "$_=$params$_", "n";
print "params: $paramsnn";
print "basestring: $basenn";
print "key: $keynn";
print "signature [$signature]nn";
$paramsoauth_signature = $signature; # -- set signature for GET query string
my $request_string = build_request_string($url,%params);
print "nrequest_string [$request_string]nn";
my $ua = LWP::UserAgent->new();
$ua->default_header("Authorization", "Basic user:pass");
my $response = $ua->get($request_string);
print Dumper $response, "n";
exit;
my $curlcmd = qq/usr/bin/curl -i -X GET "$request_string";
#`$curlcmd 2>&1`;
sub create_signature
my ($t,$k) = @_;
my $str = encode_base64(hmac_sha1($t,$k));
chomp $str;
return $str;
# Create unique nonce
#
sub create_nonce
my $str = `/bin/cat /dev/urandom
# Create oauth key for generating hmac-sha1 signature
#
sub create_key
my ($cs,$ts) = @_;
$cs = encode('utf8',uri_escape($cs));
$ts = encode('utf8',uri_escape($ts));
return "$cs&$ts";
# Build basestring for generating hmac-sha1 signature
#
sub build_request_string
my ($u,$p) = @_;
my %params = %$p;
my $str = $u . '?';
my @tmp;
for (sort keys %params)
$p = uri_escape($_) . '=' . uri_escape($params$_);
push @tmp, $p;
$str .= join '&', @tmp;
return $str;
# build the base string parameter for creating the signature
#
sub build_base_string
my ($m,$u,$phash) = @_;
my %params = %$phash;
my $str = $method;
$str .= '&' . uri_escape($u) . '&';
my @tmp;
for (sort keys %params)
push @tmp, uri_escape("$_=$params$_");
$params = join '&', @tmp;
$str .= join '&', @tmp;
return $params,$str;
1;
The result of running this from the command line is:
dnu [test] ::>./oauth-perl.pl
params: oauth_consumer_key%3DNCo8bflKU9LI&oauth_nonce%3DJrGdlVLXpB4&oauth_realm%3Dhttps%3A%2F%2Fhoppingmadmonkey.com&oauth_signature_method%3DHMAC-SHA1&oauth_timestamp%3D1542134239&oauth_token%3D2GeFG7MkXliq2OBOSSCSRBPX&oauth_version%3D1.0
basestring: GET&https%3A%2F%2Fhoppingmadmonkey.com%2Fwp-json%2Fmyapiplugin%2Fv2%2Fgreeting&oauth_consumer_key%3DNCo8bflKU9LI&oauth_nonce%3DJrGdlVLXpB4&oauth_realm%3Dhttps%3A%2F%2Fhoppingmadmonkey.com&oauth_signature_method%3DHMAC-SHA1&oauth_timestamp%3D1542134239&oauth_token%3D2GeFG7MkXliq2OBOSSCSRBPX&oauth_version%3D1.0
key: GelrnAAr1nCe5fzmTqzrU82PsfKCmKlDOZrLPakQRkH4sizJ&mdeVuJnrs8VSDJNJfMNPQRqBkG8xadfK0jAYjDGhmKOeaY7O
signature [2pJRR1fz0uUdUWHlUjHFWlXFbL4=]
request_string [https://hoppingmadmonkey.com/wp-json/myapiplugin/v2/greeting?oauth_consumer_key=NCo8bflKU9LI&oauth_nonce=JrGdlVLXpB4&oauth_realm=https%3A%2F%2Fhoppingmadmonkey.com&oauth_signature=2pJRR1fz0uUdUWHlUjHFWlXFbL4%3D&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1542134239&oauth_token=2GeFG7MkXliq2OBOSSCSRBPX&oauth_version=1.0]
$VAR1 = bless(
'_protocol' => 'HTTP/1.1',
'_content' => '
"code":"json_oauth1_signature_mismatch","message":"OAuth signature does not match","data":"status":401',
'_rc' => '401',
'_headers' => bless(
'connection' => 'close',
'cache-control' => 'no-cache, must-revalidate, max-age=0',
'date' => 'Tue, 13 Nov 2018 18:37:19 GMT',
'client-ssl-cert-issuer' => '/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Domain Validation Secure Server CA',
'client-ssl-cipher' => 'ECDHE-RSA-AES256-GCM-SHA384',
'client-peer' => '192.185.236.193:443',
'access-control-expose-headers' => 'X-WP-Total, X-WP-TotalPages',
'x-robots-tag' => 'noindex',
'client-warning' => 'Missing Authenticate header',
'client-date' => 'Tue, 13 Nov 2018 18:37:22 GMT',
'client-ssl-warning' => 'Peer certificate not verified',
'content-type' => 'application/json; charset=UTF-8',
'client-transfer-encoding' => [
'chunked'
],
'server' => 'Apache',
'x-endurance-cache-level' => '2',
'client-ssl-socket-class' => 'IO::Socket::SSL',
'link' => '<https://hoppingmadmonkey.com/index.php/wp-json/>; rel="https://api.w.org/"',
'access-control-allow-headers' => 'Authorization, Content-Type',
'client-response-num' => 1,
'x-content-type-options' => 'nosniff',
'client-ssl-cert-subject' => '/OU=Domain Control Validated/OU=Hosted by HostGator.com, LLC./OU=PositiveSSL Wildcard/CN=*.hostgator.com',
'expires' => 'Wed, 11 Jan 1984 05:00:00 GMT'
, 'HTTP::Headers' ),
'_msg' => 'Unauthorized',
'_request' => bless(
'_content' => '',
'_uri' => bless( do(my $o = 'https://hoppingmadmonkey.com/wp-json/myapiplugin/v2/greeting?oauth_consumer_key=NCo8bflKU9LI&oauth_nonce=JrGdlVLXpB4&oauth_realm=https%3A%2F%2Fhoppingmadmonkey.com&oauth_signature=2pJRR1fz0uUdUWHlUjHFWlXFbL4%3D&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1542134239&oauth_token=2GeFG7MkXliq2OBOSSCSRBPX&oauth_version=1.0'), 'URI::https' ),
'_headers' => bless(
'user-agent' => 'libwww-perl/5.833',
'authorization' => 'Basic user:pass'
, 'HTTP::Headers' ),
'_method' => 'GET',
'_uri_canonical' => bless( do(my $o = 'https://hoppingmadmonkey.com/wp-json/myapiplugin/v2/greeting?oauth_consumer_key=NCo8bflKU9LI&oauth_nonce=JrGdlVLXpB4&oauth_realm=https%3A%2F%2Fhoppingmadmonkey.com&oauth_signature=2pJRR1fz0uUdUWHlUjHFWlXFbL4%3D&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1542134239&oauth_token=2GeFG7MkXliq2OBOSSCSRBPX&oauth_version=1.0'), 'URI::https' )
, 'HTTP::Request' )
, 'HTTP::Response' );
$VAR2 = '
';
In the interests of expedience, I've included my real secrets and website. It's all test at the moment. Feel free to try a solution if you have that kind of time on your hands. I can always invalidate the tokens if/when they get abused and will obviously change once/if I can understand the problem.
The obvious thought is that I am not generating the signature correctly (Big Hint:
"code":"json_oauth1_signature_mismatch","message":"OAuth signature does not match","data":"status":401',
)
I think I've ready everything on the entire Internet to no avail. Thanks in advance for any thoughts. And if you are near Atlanta, GA and help me out, the beer's on me.
Cheers.
wordpress perl oauth signature
OK, I'm going nuts here. I've spent the better part of a week working on this with Fiddler, Rest API Log, Apache logs, Postman, etc. and am no closer to a solution. Hopefully this will provide someone with a good laugh (as it's easy) and me with a solution (for my sanity).
I have a Wordpress 4.9.8 install hosted on hostgator. I have the WP REST API - OAuth 1.0a Server plugin installed and am attempting to authenticate with OAuth from a Perl script. I've been successful connecting with Postman using the credential generated by registering an application in the UI (Wordpress > Users > Applications) but cannot seem to crack the code using curl or a perl script (or php or anything else I've tried). As Postman works (whenever it does not generate a space in the OAuth signature) I believe the plugin does, in fact, work. Below is my code where I've attempted to follow the spec regarding parameters, sorting, URI encoding, utf8 encoding, etc. Everything 'looks' ok when examining headers/query params in either Fiddle or the REST API Log plugin (pretty great little tool, that) and yet, no love.
Thanks for any advice or direction.
Client code:
#!/usr/bin/perl
use strict;
use warnings;
use LWP::UserAgent;
use JSON;
use URI::Escape;
use Digest::HMAC_SHA1 qw( hmac_sha1 );
use MIME::Base64 qw( encode_base64 );
use Encode;
use Data::Dumper;
my $timestamp = time();
my $method = 'GET';
my $url = "https://hoppingmadmonkey.com/wp-json/myapiplugin/v2/greeting";
my $client_secret = "GelrnAAr1nCe5fzmTqzrU82PsfKCmKlDOZrLPakQRkH4sizJ";
my $token_secret = "mdeVuJnrs8VSDJNJfMNPQRqBkG8xadfK0jAYjDGhmKOeaY7O";
#my $nonce = $ARGV[0]; # test with Postman generated parameters
#$timestamp = $ARGV[1]; # test with Postman generated parameters
#my $signature = $ARGV[2]; # test with Postman generated parameters
my %params = (
oauth_consumer_key => "NCo8bflKU9LI",
oauth_signature_method => "HMAC-SHA1",
oauth_realm => "https://hoppingmadmonkey.com",
oauth_timestamp => $timestamp,
oauth_token => "2GeFG7MkXliq2OBOSSCSRBPX",
oauth_version => "1.0",
);
$paramsoauth_nonce = create_nonce();
#$paramsoauth_nonce = $nonce; # test with Postman generated parameters
$paramsoauth_timestamp = $timestamp;
my $key = create_key($client_secret,$token_secret);
my ($params,$base) = build_base_string($method, $url, %params);
my $signature = create_signature($base, $key);
#for (sort keys %params) print "$_=$params$_", "n";
print "params: $paramsnn";
print "basestring: $basenn";
print "key: $keynn";
print "signature [$signature]nn";
$paramsoauth_signature = $signature; # -- set signature for GET query string
my $request_string = build_request_string($url,%params);
print "nrequest_string [$request_string]nn";
my $ua = LWP::UserAgent->new();
$ua->default_header("Authorization", "Basic user:pass");
my $response = $ua->get($request_string);
print Dumper $response, "n";
exit;
my $curlcmd = qq/usr/bin/curl -i -X GET "$request_string";
#`$curlcmd 2>&1`;
sub create_signature
my ($t,$k) = @_;
my $str = encode_base64(hmac_sha1($t,$k));
chomp $str;
return $str;
# Create unique nonce
#
sub create_nonce
my $str = `/bin/cat /dev/urandom
# Create oauth key for generating hmac-sha1 signature
#
sub create_key
my ($cs,$ts) = @_;
$cs = encode('utf8',uri_escape($cs));
$ts = encode('utf8',uri_escape($ts));
return "$cs&$ts";
# Build basestring for generating hmac-sha1 signature
#
sub build_request_string
my ($u,$p) = @_;
my %params = %$p;
my $str = $u . '?';
my @tmp;
for (sort keys %params)
$p = uri_escape($_) . '=' . uri_escape($params$_);
push @tmp, $p;
$str .= join '&', @tmp;
return $str;
# build the base string parameter for creating the signature
#
sub build_base_string
my ($m,$u,$phash) = @_;
my %params = %$phash;
my $str = $method;
$str .= '&' . uri_escape($u) . '&';
my @tmp;
for (sort keys %params)
push @tmp, uri_escape("$_=$params$_");
$params = join '&', @tmp;
$str .= join '&', @tmp;
return $params,$str;
1;
The result of running this from the command line is:
dnu [test] ::>./oauth-perl.pl
params: oauth_consumer_key%3DNCo8bflKU9LI&oauth_nonce%3DJrGdlVLXpB4&oauth_realm%3Dhttps%3A%2F%2Fhoppingmadmonkey.com&oauth_signature_method%3DHMAC-SHA1&oauth_timestamp%3D1542134239&oauth_token%3D2GeFG7MkXliq2OBOSSCSRBPX&oauth_version%3D1.0
basestring: GET&https%3A%2F%2Fhoppingmadmonkey.com%2Fwp-json%2Fmyapiplugin%2Fv2%2Fgreeting&oauth_consumer_key%3DNCo8bflKU9LI&oauth_nonce%3DJrGdlVLXpB4&oauth_realm%3Dhttps%3A%2F%2Fhoppingmadmonkey.com&oauth_signature_method%3DHMAC-SHA1&oauth_timestamp%3D1542134239&oauth_token%3D2GeFG7MkXliq2OBOSSCSRBPX&oauth_version%3D1.0
key: GelrnAAr1nCe5fzmTqzrU82PsfKCmKlDOZrLPakQRkH4sizJ&mdeVuJnrs8VSDJNJfMNPQRqBkG8xadfK0jAYjDGhmKOeaY7O
signature [2pJRR1fz0uUdUWHlUjHFWlXFbL4=]
request_string [https://hoppingmadmonkey.com/wp-json/myapiplugin/v2/greeting?oauth_consumer_key=NCo8bflKU9LI&oauth_nonce=JrGdlVLXpB4&oauth_realm=https%3A%2F%2Fhoppingmadmonkey.com&oauth_signature=2pJRR1fz0uUdUWHlUjHFWlXFbL4%3D&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1542134239&oauth_token=2GeFG7MkXliq2OBOSSCSRBPX&oauth_version=1.0]
$VAR1 = bless(
'_protocol' => 'HTTP/1.1',
'_content' => '
"code":"json_oauth1_signature_mismatch","message":"OAuth signature does not match","data":"status":401',
'_rc' => '401',
'_headers' => bless(
'connection' => 'close',
'cache-control' => 'no-cache, must-revalidate, max-age=0',
'date' => 'Tue, 13 Nov 2018 18:37:19 GMT',
'client-ssl-cert-issuer' => '/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Domain Validation Secure Server CA',
'client-ssl-cipher' => 'ECDHE-RSA-AES256-GCM-SHA384',
'client-peer' => '192.185.236.193:443',
'access-control-expose-headers' => 'X-WP-Total, X-WP-TotalPages',
'x-robots-tag' => 'noindex',
'client-warning' => 'Missing Authenticate header',
'client-date' => 'Tue, 13 Nov 2018 18:37:22 GMT',
'client-ssl-warning' => 'Peer certificate not verified',
'content-type' => 'application/json; charset=UTF-8',
'client-transfer-encoding' => [
'chunked'
],
'server' => 'Apache',
'x-endurance-cache-level' => '2',
'client-ssl-socket-class' => 'IO::Socket::SSL',
'link' => '<https://hoppingmadmonkey.com/index.php/wp-json/>; rel="https://api.w.org/"',
'access-control-allow-headers' => 'Authorization, Content-Type',
'client-response-num' => 1,
'x-content-type-options' => 'nosniff',
'client-ssl-cert-subject' => '/OU=Domain Control Validated/OU=Hosted by HostGator.com, LLC./OU=PositiveSSL Wildcard/CN=*.hostgator.com',
'expires' => 'Wed, 11 Jan 1984 05:00:00 GMT'
, 'HTTP::Headers' ),
'_msg' => 'Unauthorized',
'_request' => bless(
'_content' => '',
'_uri' => bless( do(my $o = 'https://hoppingmadmonkey.com/wp-json/myapiplugin/v2/greeting?oauth_consumer_key=NCo8bflKU9LI&oauth_nonce=JrGdlVLXpB4&oauth_realm=https%3A%2F%2Fhoppingmadmonkey.com&oauth_signature=2pJRR1fz0uUdUWHlUjHFWlXFbL4%3D&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1542134239&oauth_token=2GeFG7MkXliq2OBOSSCSRBPX&oauth_version=1.0'), 'URI::https' ),
'_headers' => bless(
'user-agent' => 'libwww-perl/5.833',
'authorization' => 'Basic user:pass'
, 'HTTP::Headers' ),
'_method' => 'GET',
'_uri_canonical' => bless( do(my $o = 'https://hoppingmadmonkey.com/wp-json/myapiplugin/v2/greeting?oauth_consumer_key=NCo8bflKU9LI&oauth_nonce=JrGdlVLXpB4&oauth_realm=https%3A%2F%2Fhoppingmadmonkey.com&oauth_signature=2pJRR1fz0uUdUWHlUjHFWlXFbL4%3D&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1542134239&oauth_token=2GeFG7MkXliq2OBOSSCSRBPX&oauth_version=1.0'), 'URI::https' )
, 'HTTP::Request' )
, 'HTTP::Response' );
$VAR2 = '
';
In the interests of expedience, I've included my real secrets and website. It's all test at the moment. Feel free to try a solution if you have that kind of time on your hands. I can always invalidate the tokens if/when they get abused and will obviously change once/if I can understand the problem.
The obvious thought is that I am not generating the signature correctly (Big Hint:
"code":"json_oauth1_signature_mismatch","message":"OAuth signature does not match","data":"status":401',
)
I think I've ready everything on the entire Internet to no avail. Thanks in advance for any thoughts. And if you are near Atlanta, GA and help me out, the beer's on me.
Cheers.
wordpress perl oauth signature
wordpress perl oauth signature
asked Nov 13 '18 at 18:45
mifydnumifydnu
213
213
add a comment |
add a comment |
2 Answers
2
active
oldest
votes
Try using Net::OAuth
If you really need to fix your implementation then try removing all uri_escape and testing with data that doesn't require any escaping.
It looks like you have some unnecessary or double escaping. Start with build_base_string function.
I thinks that = sign should be unescaped.
Thanks. I could not get things working with Net::OAuth so I tried writing my code again from scratch and explicitly following the guidelines at lti.tools/oauth until my code output matched theirs. Hallelujah! It's now working.
– mifydnu
Nov 15 '18 at 18:32
add a comment |
I could not get things working with Net::OAuth so I tried writing my code again from scratch and explicitly following the guidelines at http://lti.tools/oauth/ until my code output matched theirs. Hallelujah! It's now working.
One thing I had to add, and Postman fails to do this as well, is to url encode the signature. Makes sense, of course, but odd that Postman misses it and sends an occasional unescaped '+'.
add a comment |
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53287622%2fam-i-generating-the-oauth-signature-incorrectly-or-is-there-another-issue-with-t%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
Try using Net::OAuth
If you really need to fix your implementation then try removing all uri_escape and testing with data that doesn't require any escaping.
It looks like you have some unnecessary or double escaping. Start with build_base_string function.
I thinks that = sign should be unescaped.
Thanks. I could not get things working with Net::OAuth so I tried writing my code again from scratch and explicitly following the guidelines at lti.tools/oauth until my code output matched theirs. Hallelujah! It's now working.
– mifydnu
Nov 15 '18 at 18:32
add a comment |
Try using Net::OAuth
If you really need to fix your implementation then try removing all uri_escape and testing with data that doesn't require any escaping.
It looks like you have some unnecessary or double escaping. Start with build_base_string function.
I thinks that = sign should be unescaped.
Thanks. I could not get things working with Net::OAuth so I tried writing my code again from scratch and explicitly following the guidelines at lti.tools/oauth until my code output matched theirs. Hallelujah! It's now working.
– mifydnu
Nov 15 '18 at 18:32
add a comment |
Try using Net::OAuth
If you really need to fix your implementation then try removing all uri_escape and testing with data that doesn't require any escaping.
It looks like you have some unnecessary or double escaping. Start with build_base_string function.
I thinks that = sign should be unescaped.
Try using Net::OAuth
If you really need to fix your implementation then try removing all uri_escape and testing with data that doesn't require any escaping.
It looks like you have some unnecessary or double escaping. Start with build_base_string function.
I thinks that = sign should be unescaped.
answered Nov 13 '18 at 22:17
UjinT34UjinT34
65910
65910
Thanks. I could not get things working with Net::OAuth so I tried writing my code again from scratch and explicitly following the guidelines at lti.tools/oauth until my code output matched theirs. Hallelujah! It's now working.
– mifydnu
Nov 15 '18 at 18:32
add a comment |
Thanks. I could not get things working with Net::OAuth so I tried writing my code again from scratch and explicitly following the guidelines at lti.tools/oauth until my code output matched theirs. Hallelujah! It's now working.
– mifydnu
Nov 15 '18 at 18:32
Thanks. I could not get things working with Net::OAuth so I tried writing my code again from scratch and explicitly following the guidelines at lti.tools/oauth until my code output matched theirs. Hallelujah! It's now working.
– mifydnu
Nov 15 '18 at 18:32
Thanks. I could not get things working with Net::OAuth so I tried writing my code again from scratch and explicitly following the guidelines at lti.tools/oauth until my code output matched theirs. Hallelujah! It's now working.
– mifydnu
Nov 15 '18 at 18:32
add a comment |
I could not get things working with Net::OAuth so I tried writing my code again from scratch and explicitly following the guidelines at http://lti.tools/oauth/ until my code output matched theirs. Hallelujah! It's now working.
One thing I had to add, and Postman fails to do this as well, is to url encode the signature. Makes sense, of course, but odd that Postman misses it and sends an occasional unescaped '+'.
add a comment |
I could not get things working with Net::OAuth so I tried writing my code again from scratch and explicitly following the guidelines at http://lti.tools/oauth/ until my code output matched theirs. Hallelujah! It's now working.
One thing I had to add, and Postman fails to do this as well, is to url encode the signature. Makes sense, of course, but odd that Postman misses it and sends an occasional unescaped '+'.
add a comment |
I could not get things working with Net::OAuth so I tried writing my code again from scratch and explicitly following the guidelines at http://lti.tools/oauth/ until my code output matched theirs. Hallelujah! It's now working.
One thing I had to add, and Postman fails to do this as well, is to url encode the signature. Makes sense, of course, but odd that Postman misses it and sends an occasional unescaped '+'.
I could not get things working with Net::OAuth so I tried writing my code again from scratch and explicitly following the guidelines at http://lti.tools/oauth/ until my code output matched theirs. Hallelujah! It's now working.
One thing I had to add, and Postman fails to do this as well, is to url encode the signature. Makes sense, of course, but odd that Postman misses it and sends an occasional unescaped '+'.
answered Nov 15 '18 at 18:46
mifydnumifydnu
213
213
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53287622%2fam-i-generating-the-oauth-signature-incorrectly-or-is-there-another-issue-with-t%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown