Search code examples
node.jsauthenticationaxioscryptojs

API authorization using sha512, base64, UTC timestamp with Javascript/Node


I'm trying to get access to our payment providers API but I keep getting a 403 response (forbidden). I've triple checked the credentials and they are correct. Here is the authentication instructions:

Every request to the API must be authenticated by using the Authorization HTTP request-header.

Place the timestamp in the "Timestamp" header. The value should be the time the message was created and sent in UTC.

The authorization header is calculated for each request using the following formula.

base64 ({MerchantId}: sha512 (RequestBody + SecretWord + Timestamp))

Example:

'Timestamp': 2016-11-16 13:21:02

'Authorization': Svea TQ1Q0MzNDJERkQxRDRDRTgxQzM2NjNGRjAwMTg3RTE3M0NDNg==

full documentation Here.

Here is the code I've got:

import axios from "axios";
import CryptoJS from "crypto-js";

// Below function returns the date in the following format "#YYYY#-#MM#-#DD# #hh#:#mm#:#ss#" in UTC time. 
//Code for customFormat is omitted but it returns a string in the expected for`enter code here`mat.
 
      function customDate() {
        let now = new Date();
        return now.customFormat("#YYYY#-#MM#-#DD# #hh#:#mm#:#ss#");
      }

      let timeStamp = customDate();
      let id = 123456; //Not the actual id, but same format (6 digits).
      let secret = "AaBb123C345De"; //Not the actual secret. Actual secret is a long string of digits and letters
      let body = "";

      let hashString = CryptoJS.SHA512(
        `${body}${secret}${timeStamp}`
      ).toString();

      hashString = hashString.replace(/\-/, "");

      console.log(timeStamp);

      axios
        .get(
          "https://paymentadminapi.svea.com/api/v1/orders/123",
          {
            headers: {
              "Timestamp": timeStamp,
              "Authorization": "Svea " + btoa(`${id}:${hashString}`),
            },
          }
        )
        .then((res) => {
          console.log(res.data);
        })
        .catch((error) => {
          console.error(error);
        });

This is supposed to get a certain order number (123 in this example code) but it's not working (response 403), so can anyone please tell me what I'm doing wrong? Thanks!


Solution

  • I figured it out. Simple human error. customDate return today's date in this format, 2021-05-25 08:20:02 but this is the expected format, 2021-5-25 8:20:2. Single digits when the number is less than 10.

    I replaced the customDate function with this:

          const now = new Date();
          const year = now.getUTCFullYear();
          const month = now.getUTCMonth() +1; // January = 0
          const day = now.getUTCDate();
          const hour = now.getUTCHours();
          const minute = now.getUTCMinutes();
          const sec = now.getUTCSeconds();
    
          const timeStamp = `${year}-${month}-${day} ${hour}:${minute}:${sec}`;
    

    Now it works. Maybe there are better ways to get the date in a specific UTC format but this is what worked for me.