Finbuckle / Finbuckle.MultiTenant

Finbuckle.MultiTenant is an open-source multitenancy middleware library for .NET. It enables tenant resolution, per-tenant app behavior, and per-tenant data isolation.
https://www.finbuckle.com/multitenant
Apache License 2.0
1.26k stars 261 forks source link

TenantInfo is null after login with Identity ! Important #784

Open AHComp opened 6 months ago

AHComp commented 6 months ago

I create a demo to show the big problem !

We want to migrate to a hybrid Blazor app with MVC Support !

After login the TenantInfo is null !

Also in the path of the mvc controller /bim !

I try to call the middleware also at first ! Then the Blazor page work but not the mvc controller !

I hope the sample helps to fix !

Regards Alex

https://screenrec.com/share/ovIpdMm3L2

Sample.zip

I try to call the middleware also at first !

` using Esi.Web.Client.Pages; using Esi.Web.Components; using Esi.Web.Components.Account; using Esi.Web.Data; using Finbuckle.MultiTenant; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Components.Authorization; using Microsoft.AspNetCore.Identity; using Microsoft.EntityFrameworkCore;

var builder = WebApplication.CreateBuilder(args);

var connectionString = builder.Configuration.GetConnectionString("DefaultConnection") ?? throw new InvalidOperationException("Connection string 'DefaultConnection' not found.");

builder.Services.AddMultiTenant() .WithInMemoryStore(options => { options.IsCaseSensitive = true; options.Tenants.Add(new TenantInfo { Id = "localhost", Identifier = "localhost", ConnectionString = connectionString }); }) .WithHostStrategy(); // Add services to the container. builder.Services.AddRazorComponents() .AddInteractiveServerComponents() .AddInteractiveWebAssemblyComponents(); builder.Services.AddCascadingAuthenticationState(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped<AuthenticationStateProvider, PersistingRevalidatingAuthenticationStateProvider>(); var x = builder.Services.AddAuthentication(options => { options.DefaultScheme = IdentityConstants.ApplicationScheme; options.DefaultSignInScheme = IdentityConstants.ExternalScheme; }); x.AddIdentityCookies(); builder.Services.AddDbContext(); builder.Services.AddDatabaseDeveloperPageExceptionFilter(); builder.Services.AddIdentityCore(options => options.SignIn.RequireConfirmedAccount = true) .AddEntityFrameworkStores()
//.AddSignInManager<IdentitySignInManager>() .AddSignInManager() .AddDefaultTokenProviders(); builder.Services.AddSingleton<IEmailSender, IdentityNoOpEmailSender>(); builder.Services.AddControllersWithViews(options => { var policy = new AuthorizationPolicyBuilder() .RequireAuthenticatedUser() .Build(); //options.Filters.Add(new AuthorizeFilter(policy)); }); builder.Services.AddRazorPages();

var app = builder.Build(); app.UseMultiTenant();

// Configure the HTTP request pipeline. if (app.Environment.IsDevelopment()) { app.UseWebAssemblyDebugging(); app.UseMigrationsEndPoint(); } else { app.UseExceptionHandler("/Error", createScopeForErrors: true); // 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.UseAntiforgery(); app.UseAuthorization(); app.MapRazorComponents() .AddInteractiveServerRenderMode() .AddInteractiveWebAssemblyRenderMode() .AddAdditionalAssemblies(typeof(Counter).Assembly); // Add additional endpoints required by the Identity /Account Razor components. app.MapAdditionalIdentityEndpoints(); app.MapControllerRoute( name: "default", pattern: "{area=Bim}/{controller=Home}/{action=Index}/{id?}"); app.MapRazorPages(); app.Run();

`

The the Blazor page work but not the mvc controller !

I load the source an debug !

image

image

So something goes wrong with the delegate or ref to tenantinfo in efcore context !

Where and how the tenantinfo is injected to the efcore context ?

AndrewTriesToCode commented 5 months ago

Hi, if you enable debug log level for the Finbuckle logging namespace you’ll get some more detail for the request and what it tried to find the tenant.

In theory the mvc request should be using the hostname to get your tenant which is then provided via DI to the db context when the context is injected it or your controller. What is the full url of the request to the MVC pipeline that is causing the error?

AHComp commented 5 months ago

You can reproduce i add a sample project. The URL is the wheater page or a mvc conroller /bim.