30

When using node.js as a client, is it possible to connect to a server using Windows integrated authentication (e.g. when connecting to IIS)?

My searches for this only turn up results where node.js is used as a server.

TylerH
  • 20,799
  • 66
  • 75
  • 101
laktak
  • 57,064
  • 17
  • 134
  • 164

3 Answers3

39

2015 Update: There are now some modules that implement Windows-integrated authentication. node-sspi uses SSPI (the Windows security API) to handle the server side of things, but does not do client auth. There are several client implementations such as http-ntlm, but they are not truly integrated since they require the user password -- they do not use SSPI to do transparent auth.

2019 Update: It appears to be possible to use the kerberos library to do true Windows-integrated HTTP auth using SSPI (ie, use the node process' token to do transparent auth). See kerberos-agent. Obviously this uses Kerberos rather than NTLM/Negotiate, so this may or may not work depending on your exact situation.


"Windows integrated authentication" is what's known as NTLM authentication. When you receive a HTTP 401 from IIS with a WWW-Authenticate header containing NTLM, you now have the fun of implementing the NTLM authentication protocol. Quoting from this document about the NTLM authentication protocol:


  1. The client requests a protected resource from the server:

    GET /index.html HTTP/1.1
    
  2. The server responds with a 401 status, indicating that the client must authenticate. NTLM is presented as a supported authentication mechanism via the WWW-Authenticate header. Typically, the server closes the connection at this time:

    HTTP/1.1 401 Unauthorized
    WWW-Authenticate: NTLM
    Connection: close
    

    Note that Internet Explorer will only select NTLM if it is the first mechanism offered; this is at odds with RFC 2616, which states that the client must select the strongest supported authentication scheme.

  3. The client resubmits the request with an Authorization header containing a Type 1 message parameter. The Type 1 message is Base-64 encoded for transmission. From this point forward, the connection is kept open; closing the connection requires reauthentication of subsequent requests. This implies that the server and client must support persistent connections, via either the HTTP 1.0-style "Keep-Alive" header or HTTP 1.1 (in which persistent connections are employed by default). The relevant request headers appear as follows:

    GET /index.html HTTP/1.1
    Authorization: NTLM TlRMTVNTUAABAAAABzIAAAYABgArAAAACwALACAAAABXT1JLU1RBVElPTkRPTUFJTg==
    
  4. The server replies with a 401 status containing a Type 2 message in the WWW-Authenticate header (again, Base-64 encoded). This is shown below.

    HTTP/1.1 401 Unauthorized
    WWW-Authenticate: NTLM TlRMTVNTUAACAAAADAAMADAAAAABAoEAASNFZ4mrze8AAAAAAAAAAGIAYgA8AAAARABPAE0AQQBJAE4AAgAMAEQATwBNAEEASQBOAAEADABTAEUAUgBWAEUAUgAEABQAZABvAG0AYQBpAG4ALgBjAG8AbQADACIAcwBlAHIAdgBlAHIALgBkAG8AbQBhAGkAbgAuAGMAbwBtAAAAAAA=
    
  5. The client responds to the Type 2 message by resubmitting the request with an Authorization header containing a Base-64 encoded Type 3 message:

    GET /index.html HTTP/1.1
    Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGoAAAAYABgAggAAAAwADABAAAAACAAIAEwAAAAWABYAVAAAAAAAAACaAAAAAQIAAEQATwBNAEEASQBOAHUAcwBlAHIAVwBPAFIASwBTAFQAQQBUAEkATwBOAMM3zVy9RPyXgqZnr21CfG3mfCDC0+d8ViWpjBwx6BhHRmspst9GgPOZWPuMITqcxg==
    
  6. Finally, the server validates the responses in the client's Type 3 message and allows access to the resource.

     HTTP/1.1 200 OK
    

You'll have to figure out how you'll reply to the Type 2 message's challenge, where the user's password is MD4 hashed and used to create DES keys to encrypt the challenge data.

I'm not sure how you'd get access to the logged in user's credential data which would allow you to accomplish this, though I'm sure it would involve writing a native C++ addon so you could talk to the necessary Windows API. Or, I suppose you could just ask for the user's password.

Alternatively, you could proxy your Node requests through software that handles the NTLM mess for you.

josh3736
  • 139,160
  • 33
  • 216
  • 263
  • You can also see Negotiate, especially in a domain environment. In that case, a Kerberos ticket will be included in the `Authorization` header. – ixe013 Dec 20 '12 at 16:45
  • 3
    _Windows Integrated Authentication_ nowadays means Kerberos. NTLM is deprecated. Also the OP asked for the client side. The answer is therefore off topic. – Wolfgang Kuehn Oct 23 '13 at 18:59
  • 3
    @amadeus: He asked about using node *as* the client of IIS, which is exactly what this answers. In regard to Kerberos vs NTLM, a `WWW-Authenticate` header of `Negotiate` means the server supports both (default in newer IIS). You certainly could pursue implementing Kerberos -- there are [a couple modules on npm](https://npmjs.org/search?q=kerberos), but they're very poorly documented. – josh3736 Oct 23 '13 at 19:26
  • I found that the easiest way to do this from the client side is to use node-libcurl. https://stackoverflow.com/a/48015144/75129 – zumalifeguard Jun 01 '18 at 04:06
  • In 2020, there is node-expose-sspi, which works well with Kerberos. Note: I am the author of node-expose-sspi. – jlguenego Mar 05 '20 at 19:07
4

For Kerberos:

  • node-sspi

    Just on windows
    No client side node
    Supports NTLM too
    
  • passport-negotiate

    Needs python on the server
    it's a passportJs strategy
    

For NTLM

  • node-sspi

    Just on windows
    No client side node
    Supports Kerberos too
    
  • httpntlm
  • express-ntlm
  • request-ntlm
  • ntlm

    experimental project!
    
  • ntlm-auth

    experimental!
    
  • passport-ntlm

    supports SMB protocol
    it's a passportJs strategy
    

I chose passport-negotiate for Kerberos and express-ntlm for NTLM

Dale K
  • 25,246
  • 15
  • 42
  • 71
DaNeSh
  • 1,022
  • 1
  • 14
  • 24
  • 3
    node-sspi doesn't work with Kerberos correctly per [Caveats](https://github.com/abbr/NodeSSPI#caveats) – TheCrazyProgrammer Apr 12 '17 at 17:26
  • node-expose-sspi works with both Kerberos and NTLM (Negotiate). Note: I am the author of node-expose-sspi. – jlguenego Mar 05 '20 at 19:05
  • Microsoft provides a number of SSPI packages. So far only NTLM and Negotiate have been tested working. Kerberos is not working. Contribution is encouraged. See caveats here https://www.npmjs.com/package/node-sspi – gllambi Nov 08 '22 at 16:28
-1

For client side, what works is to use node-libcurl to do REST / HTTP calls.

here's sample code:

var endpoint = urlString;
var url = require("url");
var endpointUrl = url.parse(endpoint);

var Curl = require( 'node-libcurl' ).Curl;
var curl = new Curl();

curl.setOpt( 'USERNAME', '' );
//curl.setOpt( 'VERBOSE', 1 );
curl.setOpt( 'URL', endpoint );
curl.setOpt( 'HTTPAUTH', Curl.auth.NEGOTIATE );
curl.setOpt( 'NOPROXY', endpointUrl.hostname );

curl.on( 'end', function( statusCode, body, headers ) {

    if (statusCode === 200) {
        console.log(body);
        cb(null, { statusCode, body, headers } ); 
    } else {
        cb(new Error(), { statusCode, body, headers } ); 
    }

    this.close();
});

curl.on( 'error', curl.close.bind( curl ) );
curl.perform();
zumalifeguard
  • 8,648
  • 5
  • 43
  • 56