2

I'm trying to authenticate to the Here.com API via Oauth 1.0. I have a working Postman request that successfully gets an authentication token. I tried implementing the signature-generating procedure in Perl, but the signature I get is different from the one Postman gets. I also checked this sandbox using the same parameters, and it seem to generate the same signature I get, however this signature fails and the one that Postman generates succeeds, and I honestly cannot figure out why. Let me share some examples:

This is the code I'm playing with in Perl, with test parameters:

use URI::Encode;
use Digest::SHA qw(hmac_sha256 hmac_sha1 hmac_sha256_base64);
use MIME::Base64;

my $oauth_values = {
        consumer_key => "my-test-key",
        consumer_secret => "my-test-secret",
        request_url => "https://account.api.here.com/oauth2/token",
        request_method => "POST",
        signature_method => "HMAC-SHA256",
        timestamp => 1234567890,
        nonce => "test-nonce",
        protocol_version => "1.0",
};

my $encoder = URI::Encode->new( { encode_reserved => 1 } );

my $signature_base_string = "oauth_consumer_key=$oauth_values->{consumer_key}" .
                                "&oauth_nonce=$oauth_values->{nonce}" .
                                "&oauth_signature_method=$oauth_values->{signature_method}" .
                                "&oauth_timestamp=$oauth_values->{timestamp}" .
                                "&oauth_version=$oauth_values->{protocol_version}";

my $base_string = "POST&" . $encoder->encode($oauth_values->{request_url}) . "&" . $encoder->encode($signature_base_string);
print "Signature base string: $signature_base_string\n";
print "Base string: $base_string\n";


my $signature = encode_base64(hmac_sha256($base_string, $oauth_values->{consumer_secret} . "&"));
print "Signature: $signature\n";

Note that the params on the base string are in alphabetical order, as they should.

The output I get from that code is the following:

Signature base string: oauth_consumer_key=my-test-key&oauth_nonce=test-nonce&oauth_signature_method=HMAC-SHA256&oauth_timestamp=1234567890&oauth_version=1.0
Base string: POST&https%3A%2F%2Faccount.api.here.com%2Foauth2%2Ftoken&oauth_consumer_key%3Dmy-test-key%26oauth_nonce%3Dtest-nonce%26oauth_signature_method%3DHMAC-SHA256%26oauth_timestamp%3D1234567890%26oauth_version%3D1.0
Signature: KOXTa8e/Vw083CAwZctnZiJVIvAjH1aw4/5RWXeIhX4=

If I put these same parameters on the sandbox, I get the same signature: sandbox signature screenshot

However, when I put the exact same parameters in Postman: Postman parameter settings

then the signature that Postman generates is different:

OxhDiuqUEBAd45vNn4zIy/0etSVOn2fvquw+kQMxwsg=

This is what I get when I generate the code snippet in Python:

import requests

url = "https://account.api.here.com/oauth2/token"

payload = ""
headers = {
  'Authorization': 'OAuth oauth_consumer_key="my-test-key",oauth_signature_method="HMAC-SHA256",oauth_timestamp="1234567890",oauth_nonce="test-nonce",oauth_version="1.0",oauth_signature="OxhDiuqUEBAd45vNn4zIy/0etSVOn2fvquw+kQMxwsg="'
}

response = requests.request("POST", url, headers=headers, data=payload)

print(response.text)

I've even read the RFC with the steps, and I cannot spot an error in my method.

So how come that Postman signature is correct and the one I generate is not? What am I missing or doing wrong?

  • I'm able to reproduce your signature using `openssl dgst` on the command line. So your Base string may be different from the one generated by Postman. – jo-37 Jun 16 '21 at 16:05
  • Cross checked: I generated an OAuth 1.0 authenticated request in Postman and assembled the Base String for this request according to the spec. Then created a signature in the same way that reproduced your signature from above. The result is identical to Postman's. I'd say your Perl request is different from your Postman request. – jo-37 Jun 17 '21 at 13:50
  • Hey @jo-37, indeed after you pointed this out I looked deeper into the code, and figured it out. I'll add more details in an answer below. – nikkitousen Jun 24 '21 at 10:44

1 Answers1

2

I was able to figure it out. It turns out that encode_base64 is adding a new line at the end, which was breaking the signature I sent in the request. Adding chomp right after it fixed it.

Also, the difference I was getting between Postman and Perl signatures was due to the way Postman calculates the base string when the URL is parametrised, apparently, as switching to a "hardcoded" URL made the signatures coincide. Surprisingly, in both cases Postman is able to get an auth token, which leads me to think that the signature I get when I peek into the "Code" option in Postman is not necessarily the same one that is being sent in the request.

In a nutshell, doing this works:

my $digest = encode_base64(hmac_sha256($base_string, $oauth_values->{consumer_secret} . "&"));
chomp $digest;
my $signature_encoded = $encoder->encode($digest);