Search code examples
node.jsoauthoauth-2.0http-posthere-api

Here Map API request token with NodeJS


I am trying to request a token to the Here Map API with NodeJS in order to obtain OAuth 2.0 Token Credentials. I am blocked a the request level and constantly having the same error but according to the documentation I don't do anything wrong.

Here is the necessary code in NodeJS to make the request :

const keyID = "MyKeyID";
const keySecret = "MySecretKey";

const httpMethod = "POST";
const httpUrl = "https://account.api.here.com/oauth2/token";

let oauthNonce = Math.random().toString(36).substring(6);
let oauthTimestamp = Date.now();
let oauthSignatureMethod = "HMAC-SHA256";
let oauthVersion = "1.0";

let baseString = httpMethod + "&" + httpUrl;

let oauth1Param = [];
oauth1Param.oauth_consumer_key = keyID;
oauth1Param.oauth_signature_method = oauthSignatureMethod;
oauth1Param.oauth_signature = "";
oauth1Param.oauth_timestamp = oauthTimestamp;
oauth1Param.oauth_nonce = oauthNonce;
oauth1Param.oauth_version = oauthVersion;

let paramString = "grant_type=client_credentials"
                    + "&oauth_consumer_key=" + oauth1Param.oauth_consumer_key
                    + "&oauth_nonce=" + oauth1Param.oauth_nonce
                    + '&oauth_signature_method=' + oauth1Param.oauth_signature_method
                    + "&oauth_timestamp=" + oauth1Param.oauth_timestamp
                    + "&oauth_version=" + oauth1Param.oauth_version;

baseString += "&" + paramString;

let signingKey = keySecret + "&";

let signature = crypto.createHmac('SHA256', signingKey).update(baseString).digest('base64');

oauth1Param.oauth_signature = signature;

console.log(JSON.stringify(paramString));
console.log(oauth1Param);

let headerOauth = "OAuth ";
for (let key in oauth1Param) {
    headerOauth += key + "="  + oauth1Param[key] + ",";
}

headerOauth = headerOauth.slice(0, -1);
console.log(headerOauth);

var request = require('request');
request.post({
    url : httpUrl,
    headers: {
        'content-type' : 'application/x-www-form-urlencoded',
        'Authorization' : headerOauth
    },
    body : JSON.stringify({
        "grant_type" : "client_credentials"
    })
}, function(error, response, body){
    if(error){
        console.log("------ ERROR -------");
        throw error;
    }
    //console.log(response);
    console.log(body);
});

And this is the error that I keep getting :

{"errorId":"ERROR-51fa3a57-1dfa-4da7-b2e9-5f94574a4f75", 
"httpStatus":401, 
"errorCode":401205,
"message":"Unsupported signature method in the header. Require HMAC-SHA256",
"error":"invalid_request",
"error_description":"errorCode: '401205'. Unsupported signature method in the header. Require HMAC-SHA256"}

According to the documentation, https://developer.here.com/documentation/authentication/dev_guide/topics/error-messages.html, I have an error with the signature method and that it's required to be HMAC-SHA256 but actually this is what I have put at the beginning of my code : let oauthSignatureMethod = "HMAC-SHA256";

Does anyone know how to fix this issue?


Solution

  • The library you're using, request, supports OAuth signing. Therefore the code can be significantly shorter:

    const request = require('request');
    
    const OAUTH_URL = 'https://account.api.here.com/oauth2/token';
    const KEY_ID = '<KEY_ID>';
    const KEY_SECRET = '<KEY_SECRET>';
    
    request.post({
      url: OAUTH_URL,
      oauth: {
        consumer_key: KEY_ID,
        consumer_secret: KEY_SECRET,
        signature_method: 'HMAC-SHA256'
      },
      headers: {
        'Content-Type' : 'application/x-www-form-urlencoded',
      },
      form: {
        'grant_type': 'client_credentials'
      }
    }, function (e, r, body) {
      console.log(body);
    });
    

    As for your code snippet, JSON.stringify(obj) is not appropriate as it will encode the curly bracket of the object as well. Additionally, the values in the OAuth header need to be surrounded by double quotes. It's easy to get little things wrong with OAuth :)