3

I am trying to consume an API which requires NTLM authentication. This curl command works fine:

curl -X POST --header 'Content-Type: application/json' --header 'Accept: application/json'  --ntlm -u user:password -d '{ "key1": "100",     "key2": "1"}' http://some/api/v/12

Now I am trying to do the same from a Go program:

package main

import (
    "bytes"
    "fmt"
    "net/url"
    "net/http"
    "io/ioutil"
    "log"
    "github.com/Azure/go-ntlmssp"



)

func main() {
    url_ := "http://some/api/v/12"

     client := &http.Client{
        Transport: ntlmssp.Negotiator{
            RoundTripper:&http.Transport{},
        },
    }



    data := url.Values{}
    data.Set("key1", "100")
    data.Set("key2", "1")
    b := bytes.NewBufferString(data.Encode())
    req, err := http.NewRequest("POST", url_,  b)
    req.Header.Set("Content-Type", "application/json")
    req.Header.Set("Accept", "application/json")
    req.SetBasicAuth("user", "password")


    resp, err := client.Do(req)
    if err != nil {
        fmt.Printf("Error : %s", err)
    } else {

        responseData, err := ioutil.ReadAll(resp.Body)
        if err != nil {
            log.Fatal(err)
        }


        responseString := string(responseData)



        fmt.Println(responseString)
        resp.Body.Close()
    }

}

When I execute this program I receive an "invalid credentials" error which I normally receive when I don't include "--ntlm" flag in the curl command.

Can you please me give me a hint how can I accomplish this task with Go?


Update

printing the request from the curl command:

* About to connect() to www.xxx.xxx.com port xx (#0)
*   Trying xxx.xxx.x.xxx...
* Connected to www.xxx.xxx.com (xxx.xxx.x.xx) port xx (#0)
* Initializing NSS with certpath: sql:/etc/pki/nssdb
* Server auth using NTLM with user 'user'


> POST /some/api/v2 HTTP/1.1
> Authorization: NTLM xxxxx (44 cahracters)
> User-Agent: curl/7.29.0
> Host: www.xxx.xxx.com
> Content-Type: application/json
> Accept: application/json
> Content-Length: 0
>

< HTTP/1.1 401 Unauthorized
< Content-Type: text/html; charset=us-ascii
< Server: Microsoft-HTTPAPI/2.0
< WWW-Authenticate: NTLM xxxxx (312 characters) 
< Date: Thu, xx Aug xxxx xx:xx:xx xxx
< Content-Length: 341
<

* Ignoring the response-body
* Connection
* Issue another request to this URL: 'http://some/api/v2'
* Found bundle for host www.xxx.xxx.com: 0x0000
* Re-using existing connection! 
* Connected to www.xxx.xxx.com (xxx.xxx.x.xx) port xx (#0)
* Server auth using NTLM with user 'user'
> POST /api/v2 HTTP/1.1
> Authorization: NTLM xxx (176 characters)
> User-Agent: curl/7.29.0
> Host: www.xxx.xxx.com
> Content-Type: application/json
> Accept: application/json
> Content-Length: 39
>


* upload completely sent off: 39 out of 39 bytes


< HTTP/1.1 200 OK
< Cache-Control: no-cache
< Pragma: no-cache
< Content-Type: application/json; charset=utf-8
< Expires: -1
< Server: Microsoft-IIS/7.5
< X-AspNet-Version: 4.0.30319
< Persistent-Auth: true
< X-Powered-By: ASP.NET
< Date: Thu, 08 Aug 2019 06:49:41 GMT
< Content-Length: 1235
roAl
  • 173
  • 1
  • 1
  • 16
  • Can you add the request and response headers to your question? Basically what should happen is the client makes a request to the server, the server responds with 2 `WWW-Authenticate` headers: `WWW-Authenticate: Negotiate` and (usually, but not always) `WWW-Authenticate: NTLM`. The client should then make another request with the `Authorization` header that includes the NTLM creds hash: `Authorization: Negotiate TIRM.....` – stringy05 Aug 08 '19 at 00:38
  • @stringy05 I added the request and response headers. – roAl Aug 08 '19 at 07:29
  • cool, now we need the request and response headers from the go version. My guess is that it's not responding to the NTLM challenge in the initial 401 correctly, or else the azure go library isn't able to create the NTLM hash for some reason (often group policy related) – stringy05 Aug 09 '19 at 00:38
  • is `req.SetBasicAuth` necessary when authenticating on NTLM ? – Eugène Adell Aug 20 '19 at 08:24
  • @Eugène Adell I don’t think it is necessary, however, removing this line doesn’t change anything. – roAl Aug 21 '19 at 16:34
  • 1
    You aren't using Basic auth any way. Why are you posting the curl trace (which works) instead of the go one (which you want to debug) ? – Eugène Adell Aug 21 '19 at 17:14
  • Issue 9 on GitHub mentions avoiding authentication in POST, but curl appears to do just that. I agree it would help to show at least the error stack trace. – eel ghEEz May 16 '21 at 14:27

1 Answers1

1

NTLM needs a fully qualified Domain\Username login. Email or simple username does not work. So for the username part, it has to look like this:

MYDOMAIN\[username]

where [username] is the actual windows user.

Mario Maus
  • 11
  • 3