Search code examples
c#azureasp.net-web-apiazure-devopswindows-authentication

Authentication in Azure DevOps Server using Windows Auth


I don't understand how authenticate to Azure DevOps Server using Windows Auth.

I create a ASP.NET Web API project that identifies users using Windows Auth (https://learn.microsoft.com/en-us/aspnet/core/security/authentication/windowsauth#kestrel).

But how can I get data from Azure DevOps Server use identified user? The documentation says that you can use "Windows Auth" for authentication (https://learn.microsoft.com/en-us/azure/devops/integrate/get-started/authentication/oauth).

[HttpGet]
public string Get()
{
    var userName = User.FindFirstValue(ClaimTypes.Name);
    // It's work and contained windows username
    // User - HttpContext.User (ClaimsPrincipal)

    // But what to do next?! How can I send a request using this user?
    // https://{azure}/{org}/_apis/projects?api-version=6.0
}

Should I take some data from the ClaimsPrincipal class and add it to my request header?


Solution

  • UPDATED

    Based on the old sample of Client Library (Interactive and Windows authentication) in the Guide to authenication, I have managed to update the sample, which generates interactive sign in prompts for Azure DevOps Services users and leverages seemless Windows credential authentication for Azure DevOps Server users.

    If you are a TFS user authentication should happen in the background.

    Here is the updated code in my .NET Framework console app. For Azure DevOps Services users,

    Since the .NET Core version doesn't support interactive dialogs, this sample applies only to the .NET Framework version of the clients.

    using System;
    using Microsoft.TeamFoundation.Core.WebApi;
    using Microsoft.VisualStudio.Services.WebApi;
    using Microsoft.VisualStudio.Services.Client;
    using System.Collections.Generic;
    
    namespace TFSWindowsAuthAppClient
    {
        //After running the console will close so please add a breakpoint or sleep to see output.
        public class Program
        {
            //============= Config [Edit these with your settings] =====================
            internal const string azureDevOpsOrganizationUrl = "http://aztfs2022/DefaultCollection/"; //change to the URL of your Azure DevOps or TFS account; Azure DevOps: https://dev.azure.com/organization TFS: https://*:8080/tfs/defaultcollection" 
            //==========================================================================
    
            public static void Main(string[] args)
            {
                try
                {
                    //Based on collection URL will either start an interactive login session or use local Windows credential authentication
                    VssClientCredentials credentials = new VssClientCredentials();
                    VssConnection connection = new VssConnection(new Uri(azureDevOpsOrganizationUrl), new VssClientCredentials());
    
                    ProjectHttpClient projectClient = connection.GetClient<ProjectHttpClient>();
                    IEnumerable<TeamProjectReference> projects = projectClient.GetProjects().Result;
                    foreach (TeamProjectReference p in projects)
                    {
                        Console.WriteLine(p.Name);
                        Console.ReadLine();
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine("{0}: {1}", ex.GetType(), ex.Message);
                }
            }
        }
    }
    
    

    enter image description here SDK References:

    ProjectHttpClient Class (Microsoft.TeamFoundation.Core.WebApi) | Microsoft Learn

    VssClientCredentials Class (Microsoft.VisualStudio.Services.Client) | Microsoft Learn


    Here is my example to use the authentication with the local user account (username Alvin and its password) on the Windows machine hosting my Azure DevOps server, which calls this API; I succeed in listing the project in my collection.

    using System;
    using System.Net;
    using System.Net.Http;
    using System.Net.Http.Headers;
    
    namespace TFSWindowsAuthApp
    {
        class Program
        {
            static async Task Main()
            {
    
                var baseAddress = new Uri("http://aztfs2022/DefaultCollection/");
    
                var networkCredential = new NetworkCredential("Alvin", "AzxxPasswordxx");
    
                var httpClientHandler = new HttpClientHandler { Credentials = networkCredential };
    
                var client = new HttpClient(httpClientHandler) { BaseAddress = baseAddress };
    
                client.DefaultRequestHeaders.Accept.Clear();
                client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
    
                HttpResponseMessage response = client.GetAsync("_apis/projects?api-version=7.0").Result;
    
                response.EnsureSuccessStatusCode();
                Console.WriteLine(await response.Content.ReadAsStringAsync());
    
            }
        }
    }
    
    

    enter image description here

    Hope the sample could help.