Finbuckle.MultiTenant icon indicating copy to clipboard operation
Finbuckle.MultiTenant copied to clipboard

WithClaimsStrategy not working on IdentityServer with LocalApiAuthentication

Open boroneaionut opened this issue 2 years ago • 4 comments

I'm using IdentityServer for authenticating my services using OpenIdConnect. This works fine and the tenant is set correctly when I authenticate. For this, I have used a custom strategy that makes use of the IIdentityServerInteractionService to get the tenant from the ACR values.

I have also added IdentityServer's local API authentication by using AddLocalApiAuthentication. This also works correctly as I can access the protected endpoints and return data but not from the DB Context. The problem is that the WithClaimsStrategy doesn't set the tenant => ITenantInfo is null on the DB context.

The services are configured as follows:

services.AddIdentityServer(x =>
	{
		x.IssuerUri = "null";
		x.Authentication.CookieLifetime = TimeSpan.FromHours(2);
		x.UserInteraction = new UserInteractionOptions()
		{
			LogoutUrl = "/account/logout",
			LoginUrl = "/account/login",
			LoginReturnUrlParameter = "returnUrl"
		};
	})
	.AddSigningCredential(Certificate.Get())
	.AddAspNetIdentity<ApplicationUser>()
	.AddConfigurationStore(options => options.ConfigureDbContext = builder => builder.UseDatabase(dbProvider, rootConnectionString))
	.AddOperationalStore(options => options.ConfigureDbContext = builder => builder.UseDatabase(dbProvider, rootConnectionString))
	.Services.AddTransient<IProfileService, ProfileService>();

services.AddLocalApiAuthentication();

services
	.AddDbContext<TenantDbContext>((p, m) =>
	{
		var databaseSettings = p.GetRequiredService<IOptions<DatabaseSettings>>().Value;
		m.UseDatabase(databaseSettings.DBProvider!, databaseSettings.ConnectionString!);
	})
	.AddMultiTenant<CustomTenantInfo>()
	.WithStrategy<IdentityServerMultiTenantStrategy>(ServiceLifetime.Transient)
	.WithClaimStrategy(AppClaims.Tenant)
	//.WithPerTenantAuthentication()
	.WithEFCoreStore<TenantDbContext, CustomTenantInfo>()
	.Services
	.AddScoped<ITenantService, TenantService>();

The configuration of the app builder is as follows:

app.UseForwardedHeaders();
app.Use((context, next) => { context.Request.Scheme = "https"; return next(); });
app.UsePathBase(builder.Configuration);

app.UseStaticFiles();

app.UseCookiePolicy(new CookiePolicyOptions
{
  HttpOnly = HttpOnlyPolicy.None,
  MinimumSameSitePolicy = SameSiteMode.None,
  Secure = CookieSecurePolicy.Always
});
app.UseCorsPolicy();

app.UseRouting();
app.UseRequestLocalization();

app.UseAuthentication();
app.UseMultiTenancy();
app.UseAuthorization();
app.UseIdentityServer();
app.UseCurrentUser();

app.UseCustomHangfireDashboard(builder.Configuration);

app.MapDefaultControllerRoute();
app.MapControllers().RequireAuthorization(IdentityServerConstants.LocalApi.PolicyName);
app.MapHealthChecks("/hc", new HealthCheckOptions()
{
Predicate = _ => true,
ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse
});
app.MapHealthChecks("/liveness", new HealthCheckOptions
{
Predicate = r => r.Name.Contains("self")
});

I have also tried different orders for the app builder configuration but I can't seem to make it work.

I feel like I'm missing something or I'm doing something wrong. How can I correctly set the TenantInfo based on user claims?

Thanks!

boroneaionut avatar Feb 20 '23 16:02 boroneaionut

Hi, just to confirm, are you setting the claim value for '__tenant__' to the tenant identifier on the user?

AndrewTriesToCode avatar Feb 23 '23 21:02 AndrewTriesToCode

Hi, yes. I am using a custom claim name for the tenant but yes, I am setting its value in the user claims. I can see the claim when decoding the token.

boroneaionut avatar Feb 28 '23 10:02 boroneaionut

Any luck on this? I recommend when using ClaimsStrategy to usually call UseMultiTenant before UseAuthentication especially if you have per tenant authentication settings in place. I don't see anything obviously wrong. What is the value of AppClaims.Tenant and do you see that claim on the user?

AndrewTriesToCode avatar Mar 10 '23 07:03 AndrewTriesToCode

@boroneaionut

Can you please share your IdentityServerMultiTenantStrategy? I'm struggling with this as well and wanted to see if you figured it out.

natelaff avatar Apr 01 '24 21:04 natelaff