How do we send post request with Kerberos authentication with axios on linux?

Viewed 378

we are trying to call POST api to generate certificate for renewal of certification. However as per the 3rd party API reqirement, we need to validate Kerberos authentication. We have tried many thhings with no luck.

We are getting 401 unauthorized error when we are trying to run it.

Tech stack: Node.js, Javascript, Kerberos auth, Linux OS.

Code snippet:

const axios = require('axios');
const data = {
      Request: "-----BEGIN CERTIFICATE REQUEST-----<csr key>-----END CERTIFICATE REQUEST-----",
      CertificateTemplateName: "DBAPI1Y",
      PrimaryEmail: "test@test.com"
  };
  
  axios.post('http://dummyurl.com/webapi/SubmitRequest', data, "Negotiate")
      .then((res) => {
          console.log(`Status: ${res.status}`);
          console.log('Body: ', res.data);
      }).catch((err) => {
          console.error(err);
      });

Tried this approach with no luck: How do I use Negotiate or Kerberos authentication with axios?

Can someone please help?

2 Answers

I was unable to find any traces of Negotiate support within axios. Your linked post says that in browsers it would work automatically, which is indeed true for any in-browser JavaScript (that uses Fetch or XMLHTTPRequest behind the scenes) – but the node CLI is a different world. When run through Node CLI, axios will use the HTTP client provided by Node, which doesn't do Kerberos.

It seems that you will need to implement this manually, by using the krb5 module to get a token, then telling axios to send it in the Authorization header – similar to Bearer tokens.

The following example seems to kind of work, although not very pretty – it cannot cope with '30x' redirects:

const axios = require("axios");
const krb5 = require("krb5");

// The service is "HTTP" (uppercase), regardless of the URL being http or https.
token = await krb5.spnego({hostbased_service: "HTTP@dummyurl.com"});

resp = await axios.post("https://dummyurl.com/webapi/SubmitRequest",
                        data,
                        {
                            headers: {
                                "Authorization": `Negotiate ${token}`,
                            },
                            // SPNEGO tokens are single-use, so if Axios tries to
                            // follow redirects, the 2nd request will be rejected
                            // as a "replay". So tell it to not even try.
                            maxRedirects: 0,
                        });

(I have no experience with writing "proper" Node.js code, especially async-based code, and while in theory it should be possible to use axios' transformRequest to dynamically get a new token for each request, I was unable to figure out how to do it within a sync function.)

In general, I would probably do the task in Python instead (which has well-maintained Kerberos integration using requests-gssapi or httpx-gssapi for Requests or httpx respectively).

Note that Kerberos doesn't ensure data integrity for HTTP, so you must still use HTTPS with it, otherwise someone could still simply MitM the requests.

Apart from the above approach suggested by @user1686, I have solved the problem using NTLM authentication. Specifically, I have used the httpntlm module.

By using the httpntlm package, we don't need to deal with kerberos packages as all the kerberos packages have many dependencies on node-gyp.

Thus, it's better to use some other solution apart from the kerberos related packages.

Note: This solution worked for me, but it will vary from use case to use case.

Related