How to authenticate the .NET core API using JWT access token with SSL enabled OpenID connect? - api

I've two separate .NET core API projects (OpenIDConnect and Features API) and deployed into IIS. OpenIDConnect is to authenticate the users with their credentials and it will issue accessToken if authentication succeeded. Features API will authenticate using the OpenIDConnect API with that accessToken.
services.AddAuthentication(options =>
{
options.DefaultChallengeScheme = OpenIddictValidationAspNetCoreDefaults.AuthenticationScheme;
options.DefaultAuthenticateScheme = OpenIddictValidationAspNetCoreDefaults.AuthenticationScheme;
options.DefaultForbidScheme = OpenIddictValidationAspNetCoreDefaults.AuthenticationScheme;
});
Everything works fine until enable mTLS in OpenIdConnect. That is, enabled SSL in OpenIdConnect API from IIS and so it requires client to include the certificate on their request.
OpenIdConnect API:
services
.AddAuthentication(o =>
{
o.DefaultScheme = CertificateAuthenticationDefaults.AuthenticationScheme;
})
.AddCertificate(options =>
{
options.AllowedCertificateTypes = CertificateTypes.All;
options.Events = new CertificateAuthenticationEvents
{
OnCertificateValidated = context =>
{
var claims = new[]
{
new Claim(
ClaimTypes.NameIdentifier,
context.ClientCertificate.Subject,
ClaimValueTypes.String, context.Options.ClaimsIssuer),
new Claim(
ClaimTypes.Name,
context.ClientCertificate.Subject,
ClaimValueTypes.String, context.Options.ClaimsIssuer)
};
context.Principal = new ClaimsPrincipal(new ClaimsIdentity(claims, context.Scheme.Name));
context.Success();
return Task.CompletedTask;
}
};
})
Once enabled it, I'm able to get accessToken from OpenIdConnect API by adding certificate in Postman.
But unable to access OpenIdConnect API from Features API even though added the client certificate into Features API project like below.
services.AddOpenIddict()
.AddServer(options =>
{
options.SetIssuer(new Uri(tokenServiceBaseUrl));
options.AddSigningCertificate(signingCertificate);
})
.AddValidation(options =>
{
options.SetIssuer(tokenServiceBaseUrl);
options.UseAspNetCore();
options.UseSystemNetHttp();
options.AddEncryptionCertificate(signingCertificate);
});
Getting below exception when trying to request from Postman:
System.InvalidOperationException: IDX20803: Unable to obtain
configuration from: 'System.String'. --->
System.Text.Json.JsonException: '<' is an invalid start of a value.
Path: $ | LineNumber: 0 | BytePositionInLine: 0. --->
System.Text.Json.JsonReaderException: '<' is an invalid start of a
value. LineNumber: 0 | BytePositionInLine: 0. at
System.Text.Json.ThrowHelper.ThrowJsonReaderException(Utf8JsonReader&
json, ExceptionResource resource, Byte nextByte, ReadOnlySpan1 bytes) at System.Text.Json.Utf8JsonReader.ConsumeValue(Byte marker) at System.Text.Json.Utf8JsonReader.ReadFirstToken(Byte first) at System.Text.Json.Utf8JsonReader.ReadSingleSegment() at System.Text.Json.Utf8JsonReader.Read() at System.Text.Json.Serialization.JsonConverter1.ReadCore(Utf8JsonReader&
reader, JsonSerializerOptions options, ReadStack& state) --- End of
inner exception stack trace --- at
System.Text.Json.ThrowHelper.ReThrowWithPath(ReadStack& state,
JsonReaderException ex) at
System.Text.Json.Serialization.JsonConverter1.ReadCore(Utf8JsonReader& reader, JsonSerializerOptions options, ReadStack& state) at System.Text.Json.Serialization.JsonConverter1.ReadCoreAsObject(Utf8JsonReader&
reader, JsonSerializerOptions options, ReadStack& state) at
System.Text.Json.JsonSerializer.ReadCore[TValue](JsonConverter
jsonConverter, Utf8JsonReader& reader, JsonSerializerOptions options,
ReadStack& state) at
System.Text.Json.JsonSerializer.ReadCore[TValue](JsonReaderState&
readerState, Boolean isFinalBlock, ReadOnlySpan1 buffer, JsonSerializerOptions options, ReadStack& state, JsonConverter converterBase) at System.Text.Json.JsonSerializer.ReadAsync[TValue](Stream utf8Json, Type returnType, JsonSerializerOptions options, CancellationToken cancellationToken) at System.Net.Http.Json.HttpContentJsonExtensions.ReadFromJsonAsyncCore[T](HttpContent content, Encoding sourceEncoding, JsonSerializerOptions options, CancellationToken cancellationToken) at OpenIddict.Validation.SystemNetHttp.OpenIddictValidationSystemNetHttpHandlers.ExtractJsonHttpResponse1.HandleAsync(TContext
context) at
OpenIddict.Validation.OpenIddictValidationDispatcher.DispatchAsync[TContext](TContext
context) at
OpenIddict.Validation.OpenIddictValidationDispatcher.DispatchAsync[TContext](TContext
context) at
OpenIddict.Validation.OpenIddictValidationService.<>c__DisplayClass2_0.<g__ExtractConfigurationResponseAsync|2>d.MoveNext()
--- End of stack trace from previous location --- at OpenIddict.Validation.OpenIddictValidationService.GetConfigurationAsync(Uri
address, CancellationToken cancellationToken) at
OpenIddict.Validation.OpenIddictValidationService.GetConfigurationAsync(Uri
address, CancellationToken cancellationToken) at
OpenIddict.Validation.OpenIddictValidationRetriever.Microsoft.IdentityModel.Protocols.IConfigurationRetriever<Microsoft.IdentityModel.Protocols.OpenIdConnect.OpenIdConnectConfiguration>.GetConfigurationAsync(String
address, IDocumentRetriever retriever, CancellationToken cancel) at
Microsoft.IdentityModel.Protocols.ConfigurationManager1.GetConfigurationAsync(CancellationToken cancel) --- End of inner exception stack trace --- at Microsoft.IdentityModel.Protocols.ConfigurationManager1.GetConfigurationAsync(CancellationToken
cancel) at
OpenIddict.Validation.OpenIddictValidationHandlers.ValidateIdentityModelToken.HandleAsync(ProcessAuthenticationContext
context) at
OpenIddict.Validation.OpenIddictValidationDispatcher.DispatchAsync[TContext](TContext
context) at
OpenIddict.Validation.OpenIddictValidationDispatcher.DispatchAsync[TContext](TContext
context) at
OpenIddict.Validation.AspNetCore.OpenIddictValidationAspNetCoreHandler.HandleAuthenticateAsync()
at
Microsoft.AspNetCore.Authentication.AuthenticationHandler`1.AuthenticateAsync()
at
Microsoft.AspNetCore.Authentication.AuthenticationService.AuthenticateAsync(HttpContext
context, String scheme) at
Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext
context) at
Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext
context)

Related

UriFormatException getting caught in exception handler for ASP .Net Core

I've added exception handling to my Asp .Net Core application to log any unhandled exceptions. I am getting unhandled UriFormatExceptions within the middleware due to what appears to be traffic from various web crawlers targeting non-existent endpoints. I am not sure how to fix this, or at least elegantly silence it so it does not show up in my telemetry. In general, I'd like to ignore traffic hitting endpoints not defined by my application.
Exception logged
[Unhandled exception][UriString][https:///favicon.ico][Exception]
[System.UriFormatException: Invalid URI: The hostname could not be parsed.]
Stacktrace:
at System.Uri.CreateThis(String uri, Boolean dontEscape, UriKind uriKind, UriCreationOptions& creationOptions)
at System.Uri..ctor(String uriString)
at Microsoft.AspNet.OData.Routing.ODataPathRouteConstraint.Match(HttpContext httpContext, IRouter route, String routeKey, RouteValueDictionary values, RouteDirection routeDirection)
at Microsoft.AspNetCore.Routing.RouteConstraintMatcher.Match(IDictionary`2 constraints, RouteValueDictionary routeValues, HttpContext httpContext, IRouter route, RouteDirection routeDirection, ILogger logger)
at Microsoft.AspNetCore.Routing.RouteBase.RouteAsync(RouteContext context)
at Microsoft.AspNetCore.Routing.RouteCollection.RouteAsync(RouteContext context)
at Microsoft.AspNetCore.Builder.RouterMiddleware.Invoke(HttpContext httpContext)
at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.<Invoke>g__Awaited|6_0(ExceptionHandlerMiddleware middleware, HttpContext context, Task task)]
Exception Handler
app.UseExceptionHandler(exceptionHandlerApp =>
{
exceptionHandlerApp.Run(async context =>
{
context.Response.StatusCode = StatusCodes.Status500InternalServerError;
IExceptionHandlerPathFeature exceptionHandlerPathFeature =
context.Features.Get<IExceptionHandlerPathFeature>();
string uriString = null;
uriString = context.Request.GetEncodedUrl();
Logger.EmitLog(
"Unhandled exception",
"UriString",
uriString,
"Exception",
exceptionHandlerPathFeature?.Error);
});
});

ASP.NET Core 6 how can I Use a .pem-chain file to set up https

I have an app I have written in asp.net core 6, and I think I have what I need to get https set up. I have a .pem-chain file and a .pem file I can use and I also have a .key file that was created when I generated a .csr file.
I looked through all the Documentation I could find regarding this.
This is the one that seemed the most relevant but there is no mention of any of those file types exactly, it mentions using .UseHttps(<pem filename>,<key filename>) but that throws
Unhandled exception. System.NotSupportedException: The server mode SSL must use a certificate with the associated private key.
at System.Net.Security.SslStreamCertificateContext.Create(X509Certificate2 target, X509Certificate2Collection additionalCertificates, Boolean offline, SslCertificateTrust trust)
at Microsoft.AspNetCore.Server.Kestrel.Https.Internal.HttpsConnectionMiddleware..ctor(ConnectionDelegate next, HttpsConnectionAdapterOptions options, ILoggerFactory loggerFactory)
at Microsoft.AspNetCore.Hosting.ListenOptionsHttpsExtensions.<>c__DisplayClass12_0.<UseHttps>b__0(ConnectionDelegate next)
at Microsoft.AspNetCore.Server.Kestrel.Core.ListenOptions.Build()
at Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServerImpl.<>c__DisplayClass30_0`1.<<StartAsync>g__OnBind|0>d.MoveNext()
--- End of stack trace from previous location ---
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.AddressBinder.BindEndpointAsync(ListenOptions endpoint, AddressBindContext context, CancellationToken cancellationToken)
at Microsoft.AspNetCore.Server.Kestrel.Core.ListenOptions.BindAsync(AddressBindContext context, CancellationToken cancellationToken)
at Microsoft.AspNetCore.Server.Kestrel.Core.AnyIPListenOptions.BindAsync(AddressBindContext context, CancellationToken cancellationToken)
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.AddressBinder.AddressesStrategy.BindAsync(AddressBindContext context, CancellationToken cancellationToken)
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.AddressBinder.BindAsync(IEnumerable`1 listenOptions, AddressBindContext context, CancellationToken cancellationToken)
at Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServerImpl.BindAsync(CancellationToken cancellationToken)
at Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServerImpl.StartAsync[TContext](IHttpApplication`1 application, CancellationToken cancellationToken)
at Microsoft.AspNetCore.Hosting.GenericWebHostService.StartAsync(CancellationToken cancellationToken)
at Microsoft.Extensions.Hosting.Internal.Host.StartAsync(CancellationToken cancellationToken)
at Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.RunAsync(IHost host, CancellationToken token)
at Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.RunAsync(IHost host, CancellationToken token)
at Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.Run(IHost host)
at Microsoft.AspNetCore.Builder.WebApplication.Run(String url)
at Program.<Main>$(String[] args) in C:\Users\Nicole\source\repos\TestWebAppRazor\TestWebAppRazor\Program.cs:line 43
Here is my Program.cs
using Microsoft.AspNetCore.Authentication.Certificate;
using Microsoft.AspNetCore.Server.Kestrel.Https;
using Microsoft.AspNetCore.Server.Kestrel.Core;
using Microsoft.AspNetCore.Hosting;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddRazorPages();
builder.WebHost.ConfigureKestrel(serverOptions =>
{
serverOptions.ConfigureEndpointDefaults(listenOptions =>
{
listenOptions.UseHttps("mywebsite_com.pem", "mywebsite.com.key");
});
});
builder.Services.Configure<KestrelServerOptions>(options =>
{
options.ConfigureHttpsDefaults(options =>
options.ClientCertificateMode = ClientCertificateMode.RequireCertificate);
});
builder.Services.AddAuthentication(CertificateAuthenticationDefaults.AuthenticationScheme).AddCertificate();
builder.Host.UseSystemd();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.UseAuthentication();
app.MapRazorPages();
app.Run();
I know I am doing things wrong but I am having a difficult time deciphering the documentation.
Any guidance or direction of where to look for documentation to work with what I have would be greatly appreciated.

How do correctly rollover to a new signing certificate with IdentityServer 4?

We have multiple applications that use a single sign on identity provider application. These are all Asp.NetCore 2.1 apps. The Idp app uses IdentityServer 4 and all are hosted on Windows Server in IIS. The signing certificate for the Idp is just a self-signed server authentication cert created in IIS.
After our old signing certificate expired and our app rolled over to the new certificate we no longer could reach the discovery document.
I have had both certificates added with the respective middleware about a week before the rollover. This is the relevant code from the Startup.cs:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
var identityServerConnectionString = Configuration.GetConnectionString("IdentityServerDataDbConnectionString");
services.AddIdentityServer()
.AddSigningCredential(LoadCertificateFromStore(Configuration["CurrentKeySubject"]))
.AddValidationKey(LoadCertificateFromStore(Configuration["NextKeySubject"]))
.AddUserStore()
.AddConfigurationStore(builder =>
{
builder.ConfigureDbContext = (context) => context.UseSqlServer(identityServerConnectionString);
})
.AddOperationalStore(builder =>
{
builder.ConfigureDbContext = (context) => context.UseSqlServer(identityServerConnectionString);
builder.EnableTokenCleanup = true;
builder.TokenCleanupInterval = 3600;
builder.TokenCleanupBatchSize = 100;
});
public X509Certificate2 LoadCertificateFromStore(string value)
{
using (var store = new X509Store(StoreName.My, StoreLocation.LocalMachine))
{
store.Open(OpenFlags.ReadOnly);
var certCollection = store.Certificates.Find(X509FindType.FindBySubjectName,
value, true);
if (certCollection.Count == 0)
{
throw new Exception("The specified certificate wasn't found. Check the specified identifier.");
}
return certCollection[0];
}
}
}
It wasn't until I deleted the records from the PersistentGrants table in the database that it started working again.
I have updated this certificate every year for about 4 years and this has not "seemed" to happen before. This is the first year that the app has had more than a couple users though so rollover and caching could have been a problem but never noticed.
Is this normal to have to remove the token references from the persistent grant store for this to work? If this is pure caching involved, how do I fix it? Should I have had a reference to both certs in the discovery document more than a week in advance?
IDX20803: Unable to obtain configuration from: 'https://oursite.com/ouridp/.well-known/openid-configuration'.
at Microsoft.IdentityModel.Protocols.ConfigurationManager1.GetConfigurationAsync(CancellationToken cancel) at Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectHandler.HandleChallengeAsync(AuthenticationProperties properties) at Microsoft.AspNetCore.Authentication.AuthenticationHandler1.ChallengeAsync(AuthenticationProperties properties)
at Microsoft.AspNetCore.Authentication.AuthenticationService.ChallengeAsync(HttpContext context, String scheme, AuthenticationProperties properties)
at Microsoft.AspNetCore.Mvc.ChallengeResult.ExecuteResultAsync(ActionContext context)
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeResultAsync(IActionResult result)
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeAlwaysRunResultFilters()
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeFilterPipelineAsync()
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeAsync()
at Microsoft.AspNetCore.Builder.RouterMiddleware.Invoke(HttpContext httpContext)
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.ResponseCompression.ResponseCompressionMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Diagnostics.StatusCodePagesMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.Invoke(HttpContext context)

How to resolve "TypeError: Failed to fetch" error on Blazor?

I am trying to send an HTTP request from my Blazor app to my ASP.NET Core API. I have breakpoints everywhere. The application gives an exception right after the action method on the API controller returns. I am familiar with .NET overall, however, I could not decipher the error message.
Blazor http call:
var response = await _httpClient.GetStreamAsync($"Customer/GetAllCustomers");
ASP.NET Core API Controller action:
[HttpGet]
[Route("GetAllCustomers")]
public async Task<IEnumerable<Customer>> GetAllCustomersAsync()
{
return await _service.GetAllCustomersAsync();
}
Error stack:
Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100]
Unhandled exception rendering component: TypeError: Failed to fetch
WebAssembly.JSException: TypeError: Failed to fetch
at System.Net.Http.WebAssemblyHttpHandler.doFetch (System.Threading.Tasks.TaskCompletionSource`1[TResult] tcs, System.Net.Http.HttpRequestMessage request, System.Threading.CancellationToken cancellationToken) <0x301ab40 + 0x00a30> in <filename unknown>:0
at System.Net.Http.WebAssemblyHttpHandler.SendAsync (System.Net.Http.HttpRequestMessage request, System.Threading.CancellationToken cancellationToken) <0x2ff3590 + 0x00174> in <filename unknown>:0
at Microsoft.Extensions.Http.Logging.LoggingHttpMessageHandler.SendAsync (System.Net.Http.HttpRequestMessage request, System.Threading.CancellationToken cancellationToken) <0x2ff1e98 + 0x00160> in <filename unknown>:0
at Microsoft.Extensions.Http.Logging.LoggingScopeHttpMessageHandler.SendAsync (System.Net.Http.HttpRequestMessage request, System.Threading.CancellationToken cancellationToken) <0x2fc8a98 + 0x00182> in <filename unknown>:0
at System.Net.Http.HttpClient.FinishSendAsyncUnbuffered (System.Threading.Tasks.Task`1[TResult] sendTask, System.Net.Http.HttpRequestMessage request, System.Threading.CancellationTokenSource cts, System.Boolean disposeCts) <0x301ff08 + 0x00134> in <filename unknown>:0
at System.Net.Http.HttpClient.FinishGetStreamAsync (System.Threading.Tasks.Task`1[TResult] getTask) <0x2ffa720 + 0x000cc> in <filename unknown>:0
at WebClient.Services.LectureVideoService.GetAllLectureVideos (Content.Data.Enums.LessonType lessonType) [0x00040] in D:\AlbidersSoftware\CSharp\Albiders Content MS\Albiders\WebClient\Services\LectureVideoService.cs:21
at WebClient.Pages.MathAccList.OnInitializedAsync () [0x00026] in D:\AlbidersSoftware\CSharp\Albiders Content MS\Albiders\WebClient\Pages\MathAccList.razor:18
at Microsoft.AspNetCore.Components.ComponentBase.RunInitAndSetParametersAsync () <0x2bed718 + 0x0013a> in <filename unknown>:0
at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask (System.Threading.Tasks.Task taskToHandle) <0x2e3a0b0 + 0x000b6> in <filename unknown>:0
Unhandled exception rendering component: TypeError: Failed to fetch
WebAssembly.JSException: TypeError: Failed to fetch
I did a test to make request(s) from my Blazor WebAssembly app to action method with testing data, which works well on my side.
[Route("[controller]")]
[ApiController]
public class CustomerController : ControllerBase
{
[HttpGet]
[Route("GetAllCustomers")]
public async Task<IEnumerable<Customer>> GetAllCustomersAsync()
{
//for testing purpose
return new List<Customer> { new Customer { Id = 1, Name = "Test1" }, new Customer { Id = 2, Name = "Test2" } };
//return await _service.GetAllCustomersAsync();
}
}
GetAllCustomers.razor
#page "/getallcustomers"
#using BlazorWasmApp1.Shared
#inject HttpClient _httpClient
<h3>Customer List</h3>
#if (customers == null)
{
<p><em>Loading...</em></p>
}
else
{
<table class="table">
<thead>
<tr>
<th>Id</th>
<th>Name</th>
</tr>
</thead>
<tbody>
#foreach (var customer in customers)
{
<tr>
<td>#customer.Id</td>
<td>#customer.Name</td>
</tr>
}
</tbody>
</table>
}
#code {
private Customer[] customers;
protected override async Task OnInitializedAsync()
{
//call external API
//_httpClient.BaseAddress = new Uri("https://localhost:44312/");
//your API action would return a collection of Customer
//you can try to call .GetFromJsonAsync<Customer[]>() to get the expected data
//rather than get stream
customers = await _httpClient.GetFromJsonAsync<Customer[]>($"Customer/GetAllCustomers");
}
}
Test Result
To troubleshoot the issue, please try:
check the URL of your request in browser developer tool Network tab, and make sure you are making request to correct endpoint
if your ASP.NET Core Web API project is hosting on separate site, please make sure you configured and enabled CORS to allow request(s) from your Blazor WebAssembly app, and make sure that API is running
Also check if your api is requesting from HTTP, change it to https: it will work
EDIT NOTE: I just realised that my original answer was a red-herring, so I have deleted it and replaced it. The actual cause of my error is quite different to your question, but I'll provide a summary of resolution here because it was the first post that came up with this error message and it might help someone else troubleshoot it.
I am building a Web Assembly Hosted project, but with multiple clients and have been trialing combining AddMicrosoftIdentityWebApi and AddMicrosoftIdentityWebApp in my Server project as per following.
Program.cs (Server Project)
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApi(builder.Configuration.GetSection("AzureAd"));
builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(builder.Configuration.GetSection("AzureAd"))
Everything worked fine with just AddMicrosoftIdentityWebApi. However, when I added AddMicrosoftIdentityWebApp and tried to call my api from the client, I got the error that you identified.
Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100]
Unhandled exception rendering component: TypeError: Failed to fetch
System.Net.Http.HttpRequestException: TypeError: Failed to fetch
---> System.Runtime.InteropServices.JavaScript.JSException: TypeError: Failed to fetch
at System.Net.Http.BrowserHttpHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
--- End of inner exception stack trace ---
at System.Net.Http.BrowserHttpHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
at Microsoft.Extensions.Http.Logging.LoggingHttpMessageHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
at Microsoft.AspNetCore.Components.WebAssembly.Authentication.AuthorizationMessageHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
at Microsoft.Extensions.Http.Logging.LoggingScopeHttpMessageHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
at System.Net.Http.HttpClient.<SendAsync>g__Core|83_0(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationTokenSource cts, Boolean disposeCts, CancellationTokenSource pendingRequestsCts, CancellationToken originalCancellationToken)
at System.Net.Http.Json.HttpClientJsonExtensions.<GetFromJsonAsyncCore>d__13`1[[BlazorApp14.Shared.WeatherForecast[], BlazorApp14.Shared, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].MoveNext()
at BlazorApp14.Client.Pages.FetchData.OnInitializedAsync() in C:\Temp\BlazorApp14\BlazorApp14\Client\Pages\FetchData.razor:line 50
at Microsoft.AspNetCore.Components.ComponentBase.RunInitAndSetParametersAsync()
at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask(Task taskToHandle, ComponentState owningComponentState)
If I had looked more closely, I would have seen that my error is not quite the same as yours, but anyway.....
I then noticed that there was an additional error showing in Dev Tools on the browser.
Access to fetch at 'https://login.microsoftonline.com/common/oauth2/v2.0/authorize?client_id=0e5f2876-c...................
redirected from 'https://localhost:5001/WeatherForecast') from origin 'https://localhost:5001' has been blocked by CORS policy:
Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
This sent me down another rabbit-hole and I setup Cors etc. on my WebApi project, which did not help.
I then thought that perhaps using the same registered AzureAD application in the AddMicrosoftIdentityWebApi and AddMicrosoftIdentityWebApp calls. However, this was not the problem either.
It turns out that the [Authorize] attribute on my controller couldn't choose which Authentication scheme to use and chose the "wrong" one. The simple fix to my error was to explicitly call out the Authentication Scheme in the Authorize attribute as shown following.
[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
private static readonly string[] Summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
private readonly ILogger<WeatherForecastController> _logger;
public WeatherForecastController(ILogger<WeatherForecastController> logger)
{
_logger = logger;
}
[HttpGet]
public IEnumerable<WeatherForecast> Get()
{
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = DateTime.Now.AddDays(index),
TemperatureC = Random.Shared.Next(-20, 55),
Summary = Summaries[Random.Shared.Next(Summaries.Length)]
})
.ToArray();
}
}

Kestrel error when sending a request from an emulator

When making a request to Kestrel via Fiddler, the following request succeeds.
GET http://192.168.1.148:5000/ HTTP/1.1
Host: 192.168.1.148:5000
Connection: keep-alive
When making the request thru the NETMF Emulator, the following request fails.
GET http://192.168.1.148:5000 HTTP/1.1
Host: 192.168.1.148:5000
Connection: keep-alive
This is the ASP.NET Core error message. The error appears to be about logging!
Request finished in 24788.6203ms 500
fail: Microsoft.AspNet.Server.Kestrel[13]
An unhandled exception was thrown by the application.
System.AggregateException: An error occurred while writing to logger(s).
---> System.ArgumentException: Parameter name: value
at Microsoft.AspNet.Http.PathString..ctor(String value)
at Microsoft.AspNet.Http.Internal.DefaultHttpRequest.get_Path()
at Microsoft.AspNet.Hosting.Internal.HostingLoggerExtensions
.HostingRequestStarting.ToString()
at Microsoft.Extensions.Logging.Console.ConsoleLogger.Log(
LogLevel logLevel, Int32 eventId, Object state,
Exception exception, Func`3 formatter)
at Microsoft.Extensions.Logging.Logger.Log(
LogLevel logLevel, Int32 eventId, Object state,
Exception exception, Func`3 formatter)
--- End of inner exception stack trace ---
at Microsoft.Extensions.Logging.Logger.Log(
LogLevel logLevel, Int32 eventId, Object state,
Exception exception, Func`3 formatter)
at Microsoft.AspNet.Hosting.Internal.HostingLoggerExtensions
.RequestStarting(ILogger logger, HttpContext httpContext)
at Microsoft.AspNet.Hosting.Internal.HostingEngine
.<>c__DisplayClass32_0.<<Start>b__0>d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter
.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNet.Server.Kestrel.Http.Frame
.<RequestProcessingAsync>d__79.MoveNext()
---> (Inner Exception #0) System.ArgumentException: Parameter name: value
at Microsoft.AspNet.Http.PathString..ctor(String value)
at Microsoft.AspNet.Http.Internal.DefaultHttpRequest.get_Path()
at Microsoft.AspNet.Hosting.Internal.HostingLoggerExtensions
.HostingRequestStarting.ToString()
at Microsoft.Extensions.Logging.Console.ConsoleLogger.Log(
LogLevel logLevel, Int32 eventId, Object state,
Exception exception, Func`3 formatter)
at Microsoft.Extensions.Logging.Logger.Log(
LogLevel logLevel, Int32 eventId, Object state,
Exception exception, Func`3 formatter)<---
This is the entire ASP.NET Core program.
using System;
using Microsoft.AspNet.Builder;
using Microsoft.AspNet.Http;
using Microsoft.Extensions.Logging;
namespace EmptyApplication01
{
public class Startup
{
public void Configure(
IApplicationBuilder app,
ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole(minLevel: LogLevel.Verbose);
app.Run(async (context) =>
{
var logger = loggerFactory.CreateLogger("CatchAll");
logger.LogInformation(DateTime.Now.ToString());
await context.Response.WriteAsync("head, body");
});
}
}
}
I have figured out. Kestrel will break if the AbsoluteURL is in the path. in order to make it work this is the work around
app.Use(next => async context => {
// get the frame from kestrel and then but the path by removing the hostname
var Frame = (Microsoft.AspNet.Server.Kestrel.Http.Frame)context.Features;
var newpath = Frame.RequestUri.Replace("http://" + context.Request.Host.Value, "");
context.Request.Path = newpath;
// Invoke the rest of the pipeline.
await next(context);
});
Turning off logging fixed the problem. This is probably a bug in the ASP.NET logging implementation.
using Microsoft.AspNet.Builder;
using Microsoft.AspNet.Http;
using System;
namespace EmptyApplication01
{
public class Startup
{
public void Configure(IApplicationBuilder app)
{
app.Run(async (context) =>
{
// no more logging!
System.Console.WriteLine(DateTime.Now.ToString());
await context.Response.WriteAsync("head, body");
});
}
}
}