I am calling a Web API from a Blazor Server application published on IIS as a IIS Application under the main site with Windows Authentication only on both. This means the the Same Origin rule is applied.
Although I'm sending a Network Credential with the request, Same Origin policy prevents the Credential from reaching the API and always get a
"Error: System.Net.Http.HttpRequestException: Response status code does not indicate success: 401 (Unauthorized)."
without any meaningful extra information.
The only workaround I found was to enable Anonymous Authentication on the main site which is Ok for the Staging environment but cannot be done on the Production environment.
On the API I need to know where the request is coming from and for that I need to know which user made the request.
How can I bypass the Same Origin rule and force the credential to go through to the API endpoint?
Here's what I've done:
On Startup.cs created an instance of HttpClient for Dependency Injection.
public void ConfigureServices(IServiceCollection services)
{
[...]
if (services.All(x => x.ServiceType != typeof(HttpClient)))
{
services.AddScoped(
s =>
{
HttpClientHandler handler = new HttpClientHandler
{
UseDefaultCredentials = false,
Credentials = Config.CredentialsCache,
PreAuthenticate = true,
AllowAutoRedirect = true,
};
HttpClient httpClient = new HttpClient(handler, false)
{
BaseAddress = new Uri(Config.BaseUrl),
};
httpClient.DefaultRequestHeaders.Add("User-Agent", "MEC2SIGRE Dashboard");
httpClient.DefaultRequestHeaders.Referrer = new Uri("http://mec2sigreqa.telecom.pt/Dashboard");
httpClient.DefaultRequestHeaders.ConnectionClose = false;
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
return httpClient;
});
}
services.AddScoped<MECDashBoardDataService>();
[...]
}
(Based on Antti K. Koskela's Personal Professional Blog proposal.)
And the class:
public class MECDashBoardDataService
{
private readonly HttpClient httpClient;
public MECDashBoardDataService(HttpClient _httpClient)
{
httpClient = _httpClient;
}
public async Task<TaskersRow> MECTaskersDataAsync()
{
//******** The error is raised here **********//
return await httpClient.GetFromJsonAsync<TaskersRow>(string.Concat(Config.BaseUrl, "/api/mec_api/gettaskersdata"));
}
}
I guess it's a relative simple approach.
On the API:
[ApiController]
[Route("api/[controller]")]
public class MEC_APIController : ControllerBase
{
[HttpGet]
[ActionName("gettaskersdata")]
[Route("gettaskersdata")]
public async ValueTask<ActionResult<MECTaskersRow>> GetTaskersData()
{
await taskingScoped.InicializeTasking();
MECTaskersRow MecTR = PushingDashboard.TaskersData;
MecTR.Message = httpContextAccessor.HttpContext.User.Identity.Name; //Only for testing and prove that the credential doesn't reach this point
return MecTR;
}
[HttpGet]
public string Get()
{
return "Connecting OK.";
}
}
On IIS:

I've tried:
BrowserHttpMessageHandler.DefaultCredentials = FetchCredentialsOption.Include;
but couldn't find how to use it. I think it doesn't apply to Blazor Server.
Also tried:
System.Threading.ExecutionContext.SuppressFlow()
but it messes up Blazor!
Also tried with CORS but no luck here either.
Thanks in advance for any help I can get! :-)