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

MultitenantConext from Auth is null in Controller #779

Open turkysha opened 6 months ago

turkysha commented 6 months ago

I don't know if this is MultiTenant issue or I just don't know that much about HttpContext and it's lifecycle.

So, basically, I have a case in which I don't initially know Tenant but I know some other entity that is multitenant. So that entity has username and password and that entity is real device. How auth works is that device provides username and password in header, I select divice by username from db, authenticate it, and than I know which tenant it belongs to based on TenantId.

Then I try to TrySetTenantInfo, which returns true and GetMultiTenantContext is not null.

But commands in my application crashes because TenantInfo is null in my DbContext. I also tried to get MultiTenantContex in my Controller and it is also null. So from AuthHandler where TenantInfo is set in context to Controller, MultiTenantContext is somewhere lost.

I found "hack" where I set TenantInfo in HttpContex.Items, than I get it again in Controller and initialize new MultiTenantContext and attach that Tenant to this new MultiTenantContext.

I don't understand why is properly set MultiTenantContext in AuthHendler simply lost in my Controller.

AndrewTriesToCode commented 6 months ago

hi @turkysha Anything that was already instantiated va DI would not know about the new tenant id from TrySetTenantInfo -- is it possible that something is injecting the DbContect for that scope earlier in the request pipeline? In that case the context wouldn't see the new tenant.

I think I your case a better approach would be to define a tenant strategy which does exactly what you described: check the username fro the db and determine then tenant then return the tenant identifier from the strategy. Then the regular Finbuckle MultiTenant middleware would get the correct tenant and everything else should work as expected. I recommend implementing IMultiTenantStrategy and registering it with UseStrategy or using the DelegateStrategy.

turkysha commented 6 months ago

hi @AndrewTriesToCode, I can't use WithTenantStrategy because I don't know Tenant Info before device is authenticated on my system. So, I first need to authenticate device that is connecting to my system, then I can get which Tenant it belongs to based on TenantId shadow property from db that I get.

Only way to set Tenant in my HttpContext is by first authenticating device that is connecting to my system and then selecting which tenant it belongs to. Device infos and tenant infos are preconfigured by admin in db. So whenever device is connecting to my system, it already is configured in db and has tenant id attached to it. Problem is device does not know which tenant it belongs on initial auth.

So, you are correct, I first DI Scoped DbContext, I get device info from DbContext, I authenticate device, then I try to explicitly set TenantInfo to my DbContext.