Reputation: 794
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();
}
Upvotes: 2
Views: 8941
Reputation: 40918
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
});
Upvotes: 4