TechTurtle
TechTurtle

Reputation: 3187

Unable to consume TFS 2015 API. Getting 401 unauthrozed error

I tried TFS 2015 REST API Authentication However, it mentions request object (as I can't use javascript), not sure where is the request object or what type of it.

I am trying to pass query id and the code should execute the query and get result via API. The solution works from my local, however, after publishing to server it does not seems working. I also checked that the TFS is accessible from server using the credentials.

My code below:

    private HttpClientHandler GetTfsCredentials()
    {
        HttpClientHandler handler2 = new HttpClientHandler { UseDefaultCredentials = true };
        handler2.Credentials = new NetworkCredential("username", "password", "domain");
        return handler2;
    }
        private async Task<object> GetQueryResults(string queryId)
    {
        string tfsApiUrl = ConfigurationManager.AppSettings["TfsApiUrl"];
        string tfsProjectName = ConfigurationManager.AppSettings["TfsProjectName"];
        string TfsProjectGuid = ConfigurationManager.AppSettings["TfsProjectGuid"];

        //I tried both credentials and credentials2, but none of them working

        string credentials = Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes($"{""}:{"password"}"));

        string credentials2 = Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes("domain\\username:password") );

        if (!string.IsNullOrEmpty(tfsApiUrl) && !string.IsNullOrEmpty(tfsProjectName)
            && !string.IsNullOrEmpty(Id))
        {
            log.Info("GetQueryResults:: Config values found");
            using (var client = new HttpClient(GetTfsCredentials()) { BaseAddress = new Uri(tfsApiUrl) })
            {
                client.DefaultRequestHeaders.Accept.Clear();
                client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));

                client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", credentials2);

                HttpResponseMessage response = client.GetAsync($"{tfsProjectName}/_apis/wit/wiql/{Id}").Result;

                log.Info("GetQueryResults:: response.ReasonPhrase" + response.ReasonPhrase.ToString());
                log.Info("GetQueryResults:: response" + response.ToString());
                log.Info("GetQueryResults:: response.IsSuccessStatusCode" + response.IsSuccessStatusCode.ToString());
                string workItemList = null;

                if (response.IsSuccessStatusCode)
                {
                    //do something
                }
            }
        }

        return null;

    }

The error I received is:

2020-03-20 16:17:35,382 INFO GetQueryResults:: response.ReasonPhrase Unauthorized
2020-03-20 16:17:35,382 INFO GetQueryResults:: responseStatus Code: 401, ReasonPhrase: 'Unauthorized', Version: 1.1, Content: System.Net.Http.StreamContent, Headers:
{
  X-TFS-ProcessId: 115b5bba-0bf4-45e2-a3b2-2913ccc93f09
  ActivityId: bb21d947-99a3-44dc-bdb7-317d7af34934
  X-TFS-Session: bb21d947-99a3-44dc-bdb7-317d7af34934
  X-VSS-E2EID: bb21d947-99a3-44dc-bdb7-317d7af34934
  X-FRAME-OPTIONS: SAMEORIGIN
  X-TFS-SoapException: %3c%3fxml+version%3d%221.0%22+encoding%3d%22utf-8%22%3f%3e%3csoap%3aEnvelope+xmlns%3asoap%3d%22http%3a%2f%2fwww.w3.org%2f2003%2f05%2fsoap-envelope%22%3e%3csoap%3aBody%3e%3csoap%3aFault%3e%3csoap%3aCode%3e%3csoap%3aValue%3esoap%3aReceiver%3c%2fsoap%3aValue%3e%3csoap%3aSubcode%3e%3csoap%3aValue%3eUnauthorizedRequestException%3c%2fsoap%3aValue%3e%3c%2fsoap%3aSubcode%3e%3c%2fsoap%3aCode%3e%3csoap%3aReason%3e%3csoap%3aText+xml%3alang%3d%22en%22%3eTF400813%3a+The+user+%27CWOPA%5cSTCTCAPD006%24%27+is+not+authorized+to+access+this+resource.%3c%2fsoap%3aText%3e%3c%2fsoap%3aReason%3e%3c%2fsoap%3aFault%3e%3c%2fsoap%3aBody%3e%3c%2fsoap%3aEnvelope%3e
  X-TFS-ServiceError: TF400813%3a+The+user+%27CWOPA%5cSTCTCAPD006%24%27+is+not+authorized+to+access+this+resource.
  Server: Microsoft-IIS/8.5
  WWW-Authenticate: Bearer
  WWW-Authenticate: Negotiate
  WWW-Authenticate: NTLM
  X-Powered-By: ASP.NET
  P3P: CP="CAO DSP COR ADMa DEV CONo TELo CUR PSA PSD TAI IVDo OUR SAMi BUS DEM NAV STA UNI COM INT PHY ONL FIN PUR LOC CNT"
  Lfs-Authenticate: NTLM
  X-Content-Type-Options: nosniff
  Date: Fri, 20 Mar 2020 20:17:35 GMT
  Content-Length: 82
  Content-Type: text/plain; charset=utf-8
}
2020-03-20 16:17:35,382 INFO GetQueryResults:: response.IsSuccessStatusCode False

Upvotes: 0

Views: 234

Answers (1)

Sebastian Segerer
Sebastian Segerer

Reputation: 370

It looks like you are doing authentication in two different ways at once:

  • In the GetTfsCredentials-Method you set up Windows Authentication (NTLM or Kerberos)
  • By adding client.DefaultRequestHeaders.Authorization your try to set up Basic Authentication

Your TFS indicates (see WWW-Authenticate Header) that it supports Bearer, Negotiate and NTLM; but not Basic.

I would try:

  1. Remove client.DefaultRequestHeaders.Authorization, credentials and credentials2. This should remove Basic-Authentication
  2. Remove UseDefaultCredentials = true since you set explicit credentials the next line. UseDefaultCredentials tells HttpClientHandler to access TFS with the credentials of the running process, which is probably your account when executing locally and a service account when executing on the server.
    Whithout this line, the specified NetworkCredential should be used to access TFS.

Upvotes: 1

Related Questions