I am currently working on a project that consists of sub-projects such as WebApp, API, and Client class library. (The project structure is shown below). Project Solution Structure
Although the project is a web-based project, it uses windows Identity as authentication identity since it is an internal application. I implemented the authorization policy of the WebApp project without any problems by following the steps in the implementation_link. Now I can control access using DataAnnotation in WebApp (ex. [Authorize(Roles = "Admin"]). If I add Authorization control on the API side, WebApp cannot access this API. This is because of HttpContext.User is null. I found the solution to this problem solution_link. I adapted this solution to the project as below:
ServiceCollectionExtensions.cs in WebApp project:
public static IServiceCollection AddAuraServices(this IServiceCollection serviceCollection, IConfiguration configuration)
{
serviceCollection.AddTransient<IModelDatabaseNamesProvider, StandardCasingModelDatabasesNamesProvider>();
serviceCollection.Configure<RouteOptions>(routeOptions =>
{
routeOptions.ConstraintMap.Add(ModelDatabasesNameConstraint.Name, typeof(ModelDatabasesNameConstraint));
});
serviceCollection.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
serviceCollection.AddScoped<IModelMetadataProvider>(serviceProvider =>
{
var httpContext = serviceProvider.GetRequiredService<IHttpContextAccessor>().HttpContext;
var modelName = httpContext.Request.RouteValues["model-name"].ToString();
return new ModelMetadataProvider(modelName);
});
DateOnlyTypeConverter.AddAttributeToType();
serviceCollection.AddHttpClient<UploadRulesClient>("ServerAPI", (httpClient) =>
{
httpClient.BaseAddress = new Uri(configuration["AuraApiClient:BaseAddress"]);
}).AddHttpMessageHandler<BaseAddressAuthorizationMessageHandler>();
serviceCollection.AddHttpClient<ScenarioZipFilesClient>("ServerAPI",(httpClient) =>
{
httpClient.BaseAddress = new Uri(configuration["AuraApiClient:BaseAddress"]);
}).AddHttpMessageHandler<BaseAddressAuthorizationMessageHandler>();
serviceCollection.AddScoped(sp => sp.GetRequiredService<IHttpClientFactory>()
.CreateClient("ServerAPI"));
var jsonSerializerOptions = new JsonSerializerOptions
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase
};
ClientJsonResponse.Configure(jsonSerializerOptions);
serviceCollection.AddSingleton(jsonSerializerOptions);
serviceCollection.AddAuraDropzoneConfig(configuration);
return serviceCollection;
}
Startup.cs of WebApp:
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication(NegotiateDefaults.AuthenticationScheme).AddNegotiate();
services.AddAuthorization();
services.AddControllersWithViews();
//services.AddRazorPages();
services.AddAuraServices(Configuration);
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
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.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(name: "model-database", pattern: "{model-name:modeldatabasename}/{controller=ZipFiles}/{action=Index}/{id?}");
endpoints.MapControllerRoute(name: "default", pattern: "", new { controller = "Home", action = "Index" });
//endpoints.MapRazorPages();
});
}
}
But this time I am getting No service for Type Error. How can I solve this problem? Where do you think I am going wrong? Thanks
CodePudding user response:
You have to register BaseAddressAuthorizationMessageHandler
:
serviceCollection.AddTransient<BaseAddressAuthorizationMessageHandler>();
CodePudding user response:
Thank you for your comment but it didn't work. I tried this code line into either ServiceCollectionExtension.cs file and Startup.cs but the result is the same. I got this error:
System.AggregateException HResult=0x80131500 Message=Some services are not able to be constructed (Error while validating the service descriptor 'ServiceType: Microsoft.AspNetCore.Components.WebAssembly.Authentication.BaseAddressAuthorizationMessageHandler Lifetime: Transient ImplementationType: Microsoft.AspNetCore.Components.WebAssembly.Authentication.BaseAddressAuthorizationMessageHandler': Unable to resolve service for type 'Microsoft.AspNetCore.Components.WebAssembly.Authentication.IAccessTokenProvider' while attempting to activate 'Microsoft.AspNetCore.Components.WebAssembly.Authentication.BaseAddressAuthorizationMessageHandler'.) Source=Microsoft.Extensions.DependencyInjection StackTrace: at Microsoft.Extensions.DependencyInjection.ServiceProvider..ctor(ICollection
1 serviceDescriptors, ServiceProviderOptions options) at Microsoft.Extensions.DependencyInjection.ServiceCollectionContainerBuilderExtensions.BuildServiceProvider(IServiceCollection services, ServiceProviderOptions options) at Microsoft.Extensions.DependencyInjection.DefaultServiceProviderFactory.CreateServiceProvider(IServiceCollection containerBuilder) at Microsoft.Extensions.Hosting.Internal.ServiceFactoryAdapter
1.CreateServiceProvider(Object containerBuilder) at Microsoft.Extensions.Hosting.HostBuilder.CreateServiceProvider() at Microsoft.Extensions.Hosting.HostBuilder.Build() at Aura.App.Program.Main(String[] args) in C:\Users\DRA11KS\source\repos\AuRA\Aura.App\Program.cs:line 16
This exception was originally thrown at this call stack: Inner Exception 1: InvalidOperationException: Error while validating the service descriptor 'ServiceType: Microsoft.AspNetCore.Components.WebAssembly.Authentication.BaseAddressAuthorizationMessageHandler Lifetime: Transient ImplementationType: Microsoft.AspNetCore.Components.WebAssembly.Authentication.BaseAddressAuthorizationMessageHandler': Unable to resolve service for type 'Microsoft.AspNetCore.Components.WebAssembly.Authentication.IAccessTokenProvider' while attempting to activate 'Microsoft.AspNetCore.Components.WebAssembly.Authentication.BaseAddressAuthorizationMessageHandler'. Inner Exception 2: InvalidOperationException: Unable to resolve service for type 'Microsoft.AspNetCore.Components.WebAssembly.Authentication.IAccessTokenProvider' while attempting to activate 'Microsoft.AspNetCore.Components.WebAssembly.Authentication.BaseAddressAuthorizationMessageHandler'.
How can I solve it? Thanks.