We have solution based on 3rd party ABP framework and its multi-layer architecture:
We are using Angular as a web face and IdentityServer4 for user authentication. So, we are running 2 hosts - HTTP API host and IdentityServer host and as to web face - it works in a standard way: login box, user enters credentials - voila.
Though, we have a custom setup allowing the same login name under different tenant. The tenants list is displayed as a dropdown on UI and we would like to re-login a user with the selected tenant instead of the user currently logged in. It needs to look like a simple page reload. The problem is I don't have clear understanding how to implement this. I've tried to use the following call from application layer, but it does not work (error is "No authentication handler is registered for the scheme 'Identity.Application'...", but I don't know how to set up authentication configuration on application layer to be able to work with our IdentityServer):
[HttpGet]
public async Task<TenantDto> SwitchTenantForCurrentUser(Guid? tenantId)
{
var abxUser = await _abxUserRepository.FirstOrDefaultAsync(x => x.Login == CurrentUser.UserName && x.Tenant.AbpId == tenantId);
if (abxUser == null)
return null;
using var _ = _abpCurrentTenant.Change(tenantId);
var currentTenant = await _abxTenantRepository.FirstOrDefaultAsync(x => x.AbpId == _abpCurrentTenant.Id.Value);
var identityUser = await _identityUserRepository.FindByNormalizedUserNameAsync(abxUser.Login.ToUpper());
if (await _signInManager.CanSignInAsync(identityUser))
{
await _signInManager.SignOutAsync();
await _signInManager.SignInAsync(identityUser, true);
}
return ObjectMapper.Map<Tenant, TenantDto>(currentTenant); // Not decided yet what to return, it depends on proper implementation
}
Configuration part from Http API host as to authentication:
private void ConfigureAuthentication(ServiceConfigurationContext context, IConfiguration configuration)
{
context.Services.AddAuthentication("Bearer")
.AddIdentityServerAuthentication(options =>
{
options.Authority = configuration["AuthServer:Authority"];
options.RequireHttpsMetadata = true;
options.ApiName = "CentralTools";
options.JwtBackChannelHandler = new HttpClientHandler
{
//TODO: use valid certificate in future and change the logic
ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator
};
});
context.Services.AddAbpIdentity().AddDefaultTokenProviders();