UseAuthorization does not work with WebHostBuilder on .NET 8
Is there an existing issue for this?
- [X] I have searched the existing issues
Describe the bug
When using WebHostBuilder to run web applications or tests in .NET 8, and app.UseAuthorization() is called, when starting the web app, an exception is thrown stating the following:
Unable to resolve service for type 'Microsoft.AspNetCore.Routing.EndpointDataSource' while attempting to activate 'Microsoft.AspNetCore.Authorization.Policy.AuthorizationPolicyCache'.
This issue does not occur with any prior version of .NET.
Expected Behavior
Using WebHostBuilder to create a web application should work as it did in .NET 7 and prior versions.
Steps To Reproduce
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework><!-- change to 7.0 and it works -->
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>
var hostBuilder = new WebHostBuilder();
hostBuilder.UseIIS(); // fails with UseKestrel() also
hostBuilder.ConfigureServices(services =>
{
services.AddAuthentication();
services.AddAuthorization();
});
hostBuilder.Configure(app =>
{
app.UseAuthentication();
app.UseAuthorization();
app.Run(async context =>
{
context.Response.StatusCode = 200;
context.Response.ContentType = "text/plain";
await context.Response.WriteAsync("OK");
});
});
await hostBuilder.Build().RunAsync(); // <-- crashes here
Exceptions (if any)
System.InvalidOperationException
HResult=0x80131509
Message=Unable to resolve service for type 'Microsoft.AspNetCore.Routing.EndpointDataSource' while attempting to activate 'Microsoft.AspNetCore.Authorization.Policy.AuthorizationPolicyCache'.
Source=Microsoft.Extensions.DependencyInjection
StackTrace:
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateArgumentCallSites(ServiceIdentifier serviceIdentifier, Type implementationType, CallSiteChain callSiteChain, ParameterInfo[] parameters, Boolean throwIfCallSiteNotFound)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateConstructorCallSite(ResultCache lifetime, ServiceIdentifier serviceIdentifier, Type implementationType, CallSiteChain callSiteChain)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateExact(ServiceDescriptor descriptor, ServiceIdentifier serviceIdentifier, CallSiteChain callSiteChain, Int32 slot)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateExact(ServiceIdentifier serviceIdentifier, CallSiteChain callSiteChain)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateCallSite(ServiceIdentifier serviceIdentifier, CallSiteChain callSiteChain)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.GetCallSite(ServiceIdentifier serviceIdentifier, CallSiteChain callSiteChain)
at Microsoft.Extensions.DependencyInjection.ServiceProvider.CreateServiceAccessor(ServiceIdentifier serviceIdentifier)
at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory)
at Microsoft.Extensions.DependencyInjection.ServiceProvider.GetService(ServiceIdentifier serviceIdentifier, ServiceProviderEngineScope serviceProviderEngineScope)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope.GetService(Type serviceType)
at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetService[T](IServiceProvider provider)
at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware..ctor(RequestDelegate next, IAuthorizationPolicyProvider policyProvider, IServiceProvider services)
at Microsoft.AspNetCore.Authorization.AuthorizationMiddlewareInternal..ctor(RequestDelegate next, IServiceProvider services, IAuthorizationPolicyProvider policyProvider, ILogger`1 logger)
at System.RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor)
at System.Reflection.MethodBaseInvoker.InvokeDirectByRefWithFewArgs(Object obj, Span`1 copyOfArgs, BindingFlags invokeAttr) in /_/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodBaseInvoker.cs:line 178
at System.Reflection.MethodBaseInvoker.InvokeWithFewArgs(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) in /_/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodBaseInvoker.cs:line 145
at System.Reflection.RuntimeConstructorInfo.Invoke(BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) in /_/src/libraries/System.Private.CoreLib/src/System/Reflection/RuntimeConstructorInfo.cs:line 162
at Microsoft.Extensions.Internal.ActivatorUtilities.ConstructorMatcher.CreateInstance(IServiceProvider provider)
at Microsoft.Extensions.Internal.ActivatorUtilities.CreateInstance(IServiceProvider provider, Type instanceType, Object[] parameters)
at Microsoft.AspNetCore.Builder.UseMiddlewareExtensions.ReflectionMiddlewareBinder.CreateMiddleware(RequestDelegate next)
at Microsoft.AspNetCore.Builder.ApplicationBuilder.Build()
at Microsoft.AspNetCore.Hosting.WebHost.BuildApplication() in /_/src/Hosting/Hosting/src/Internal/WebHost.cs:line 225
at Microsoft.AspNetCore.Hosting.WebHost.<StartAsync>d__27.MoveNext() in /_/src/Hosting/Hosting/src/Internal/WebHost.cs:line 132
at Microsoft.AspNetCore.Hosting.WebHostExtensions.<RunAsync>d__5.MoveNext() in /_/src/Hosting/Hosting/src/WebHostExtensions.cs:line 112
at Microsoft.AspNetCore.Hosting.WebHostExtensions.<RunAsync>d__5.MoveNext() in /_/src/Hosting/Hosting/src/WebHostExtensions.cs:line 147
at Microsoft.AspNetCore.Hosting.WebHostExtensions.<RunAsync>d__4.MoveNext() in /_/src/Hosting/Hosting/src/WebHostExtensions.cs:line 97
at Program.<<Main>$>d__0.MoveNext() in C:\......\Program.cs:line 24
at Program.<Main>(String[] args)
.NET Version
8.0.101
Anything else?
- Workaround: add
services.AddRouting(); - Workaround is not required when using
WebApplication.CreateBuilder
Hi @Shane32, I was having the same issue.
I got my tests working by adding services.AddRouting() before services.AddAuthorization().
services.AddRouting(); // <-- Order matters
services.AddAuthorization();
Background:
That idea was motivated by a comment in the source code of app.UseAuthorization().
https://github.com/dotnet/aspnetcore/blob/0bae45ebe88ad07f69e13a142c93a05b496dc9b4/src/Security/Authorization/Policy/src/AuthorizationAppBuilderExtensions.cs#L20-L21
I added the "using" (and not the service.AddRouting) and received this error:
System.InvalidOperationException: Unable to find the required services. Please add all the required services by calling 'IServiceCollection.AddRouting' inside the call to 'ConfigureServices(...)' in the application startup code.
To mitigate, I then added services.AddRouting(); before services.AddAuthorization(); and my code worked!
Just out of curiosity because my tests didn't explicitly need "app.UseRouting()", I checked whether removing the "using" would render the same results. My code ran without issue.
Mitigation -> more contextual setup code.
webBuilder
.UseTestServer()
.ConfigureServices(services =>
{
services.AddAuthentication(defaultScheme: <scheme>);
services.AddRouting();
services.AddAuthorization();
})
.Configure(app =>
{
//app.UseRouting(); // <- didn't need this. Whether it is correct to leave out is TBD.
app.UseAuthentication();
app.UseAuthorization();
// app.Run acts as terminating middleware to return 200 if we reach it. Without this,
// the Middleware pipeline will return 404 by default.
app.Run(async (context) =>
{
context.Response.StatusCode = (int)HttpStatusCode.OK;
await context.Response.WriteAsync("Successful Request");
await context.Response.StartAsync();
});
});
Original exception
I observed (and found this issue) because my stack trace matched yours.
System.InvalidOperationException: Unable to resolve service for type 'Microsoft.AspNetCore.Routing.EndpointDataSource' while attempting to activate 'Microsoft.AspNetCore.Authorization.Policy.AuthorizationPolicyCache'.
notes
I'm sure there must be a more elegant way of doing this, but I didn't have more time to look into this because I was trying to unblock myself from finishing a deliverable.
I'm having this same exception, but in a console app...
I added .UseRouting() and it works... but this is not a webhost?
after upgrading to NET 8
What warmfire said. Routing does not make sense in a Console app.
We should optionally resolve endpoint datasource.
Experiencing the same thing on a .NET 8 worker application (Microsoft.NET.Sdk.Worker) that I bootstrap with Host.CreateApplicationBuilder(). It started happening as soon as I depended on a library that has optional extension methods on WebApplicationBuilder to set up auth policies based on some incoming config.
However, I don't call that particular method. In fact, at no point is AddAuthorization() or UseAuthorization() called. Adding .AddRouting() early in my DI setup "fixed" the problem for now.