node.jshttpshttp-headershmactotp

How do I generate the correct TOTP with Node with correct Headers and SHA512 hashed Token?


A recent school project I was assigned has a coding challenge we have to complete. The challenge has multiple parts, and the final part is uploading to a private GitHub repo and submitting a completion request by making a POST request under certain conditions.

I have successfully completed the other parts of the challenge and am stuck on submitting the request. The submission has to follow these rules:

Build your solution request

First, construct a JSON string like below:

{

    "github_url": "https://github.com/YOUR_ACCOUNT/GITHUB_REPOSITORY",

    "contact_email": "YOUR_EMAIL"

}

Fill in your email address for YOUR_EMAIL, and the private Github repository with your solution in YOUR_ACCOUNT/GITHUB_REPOSITORY. Then, make an HTTP POST request to the following URL with the JSON string as the body part.

CHALLENGE_URL

Content type

The Content-Type: of the request must be application/json.

Authorization

The URL is protected by HTTP Basic Authentication, which is explained on Chapter 2 of RFC2617, so you have to provide an Authorization: header field in your POST request.

  • For the userid of HTTP Basic Authentication, use the same email address you put in the JSON string.
  • For the password , provide a 10-digit time-based one time password conforming to RFC6238 TOTP.

Authorization password

For generating the TOTP password, you will need to use the following setup:

  • You have to generate a correct TOTP password according to RFC6238
  • TOTP's Time Step X is 30 seconds. T0 is 0.
  • Use HMAC-SHA-512 for the hash function, instead of the default HMAC-SHA-1.
  • Token shared secret is the userid followed by ASCII string value "APICHALLENGE" (not including double quotations).

Shared secret examples

For example, if the userid is "email@example.com", the token shared secret is "email@example.comAPICHALLENGE" (without quotes).

If your POST request succeeds, the server returns HTTP status code 200 .

I have tried to follow this outline very carefully, and testing my work in different ways. However, it seems I can't get it right. We are supposed to make the request from a Node server backend. This is what I have done so far. I created a new npm project with npm init and installed the dependencies you will see in the code below:

const axios = require('axios');
const base64 = require('base-64');
const utf8 = require('utf8');

const { totp } = require('otplib');


const reqJSON = 
{
    github_url: GITHUB_URL,
    contact_email: MY_EMAIL
}
const stringData = JSON.stringify(reqJSON);

const URL = CHALLENGE_URL;
const sharedSecret = reqJSON.contact_email + "APICHALLENGE";

totp.options = { digits: 10, algorithm: "sha512" }

const myTotp = totp.generate(sharedSecret);
const isValid = totp.check(myTotp, sharedSecret);

console.log("Token Info:", {myTotp, isValid});




const authStringUTF = reqJSON.contact_email + ":" + myTotp;
const bytes = utf8.encode(authStringUTF);
const encoded = base64.encode(bytes);



const createReq = async () =>
{

    try 
    {

        // set the headers
        const config = {
            headers: {
                'Content-Type': 'application/json',
                "Authorization": "Basic " + encoded
            }
        };

        console.log("Making req", {URL, reqJSON, config});

        const res = await axios.post(URL, stringData, config);
        console.log(res.data);
    }
    catch (err)
    {
        console.error(err.response.data);
    }
};

createReq();

As far as I understand, I'm not sure where I'm making a mistake. I have tried to be very careful in my understanding of the requirements. I have briefly looked into all of the documents the challenge outlines, and gathered the necessary requirements needed to correctly generate a TOTP under the given conditions.

I have found the npm package otplib can satisfy these requirements with the options I have passed in.

However, my solution is incorrect. When I try to submit my solution, I get the error message, "Invalid token, wrong code". Can someone please help me see what I'm doing wrong?

I really don't want all my hard work to be for nothing, as this was a lengthy project.

Thank you so much in advance for your time and help on this. I am very grateful.


Solution

  • The Readme of the package otplib states:

    // TOTP defaults
    {
      // ...includes all HOTP defaults
      createHmacKey: totpCreateHmacKey,
      epoch: Date.now(),
      step: 30,
      window: 0,
    }
    

    So the default value for epoch (T0) is Date.now() which is the RFC standard. The task description defines that T0 is 0.

    You need to change the default value for epoch to 0:

    totp.options = { digits: 10, algorithm: "sha512", epoch: 0 }