简体   繁体   中英

How do I pass the windows authentication token on a web request to an api?

In ASP.NET Core 5, can I use Windows Authentication (which allows IIS to authenticate the user) and somehow grab that token and then use that to call a Web API application that also authenticates via Windows Authentication? In other words, we want the same security context in the API app as we have in the UI app. Is that even possible?

public void ConfigureServices(IServiceCollection services)
{
    services.AddAuthentication(IISDefaults.AuthenticationScheme);
    var commonApiSettings = Configuration.GetSection("CommonApiSettings").Get<CommonApiSettings>(); 
    services.AddHttpClient("CommonApi",
                    client =>
                    {
                        client.BaseAddress = new Uri(commonApiSettings.BaseAddress);
                        client.DefaultRequestHeaders.Add("Accept", "application/json");
                        client.DefaultRequestHeaders.Add("User-Agent", "AspNetCore-Demo");
                    });
    services.AddControllersWithViews();
}

THen in my controller I want to call a web api. Every time I get 401 Unauthorized.

public class HomeController : Controller
{
    private readonly ILogger<HomeController> _logger;
    private readonly IHttpClientFactory _clientFactory;

    public HomeController(ILogger<HomeController> logger, IHttpClientFactory httpClient)
    {
        _logger = logger;
        _clientFactory = httpClient;
    }

    public async Task<IActionResult> Index()
    {

        IEnumerable<Confection> inventory;

        try
        {
            var user = (WindowsIdentity)User.Identity!;

            await WindowsIdentity.RunImpersonatedAsync(user.AccessToken, async () =>
            {

                var impersonatedUser = WindowsIdentity.GetCurrent();
                var message =
                    $"User: {impersonatedUser.Name}\t" +
                    $"State: {impersonatedUser.ImpersonationLevel}";

                var bytes = Encoding.UTF8.GetBytes(message);
          
                var httpClient = _clientFactory.CreateClient("CommonApi");
                httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", impersonatedUser.AccessToken.ToString());
                var request = new HttpRequestMessage(HttpMethod.Get, "");

                var httpResponseMessage = await httpClient.SendAsync(request);

                if (httpResponseMessage.IsSuccessStatusCode)
                {
                    using var contentStream = await httpResponseMessage.Content.ReadAsStreamAsync();
                    inventory = await JsonSerializer.DeserializeAsync<IEnumerable<Confection>>(contentStream);
                }
            });
        }
        catch (Exception e)
        {
            //await context.Response.WriteAsync(e.ToString());
        }

        return View();
    }

To send Windows credentials, you need to set the UseDefaultCredentials property of the HttpClientHandler used by HttpClient . There is an example of how to do this with IHttpClientFactory in the documentation .

In your case, it should look something like this:

services.AddHttpClient("CommonApi",
                client =>
                {
                    client.BaseAddress = new Uri(commonApiSettings.BaseAddress);
                    client.DefaultRequestHeaders.Add("Accept", "application/json");
                    client.DefaultRequestHeaders.Add("User-Agent", "AspNetCore-Demo");
                })
            .ConfigurePrimaryHttpMessageHandler(() =>
                new HttpClientHandler
                {
                    UseDefaultCredentials = true
                });

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM