遗憾的是,非常缺乏关于在 IdentityServer4 中实现自定义
AuthorizeInteractionResponseGenerator
的文档。
我正在尝试实现我自己的
AuthorizeInteractionResponseGenerator
,因为我需要进一步的用户交互步骤(在身份验证之后)。我的场景是单个身份(电子邮件)可以与多个租户相关联。所以在登录后,我需要向用户显示相关租户列表,以便他们可以选择一个。
我评估了源代码,并提出了以下自定义
AuthorizeInteractionResponseGenerator
:
public class AccountChooserResponseGenerator : AuthorizeInteractionResponseGenerator
{
public AccountChooserResponseGenerator(ISystemClock clock,
ILogger<AuthorizeInteractionResponseGenerator> logger,
IConsentService consent, IProfileService profile)
: base(clock, logger, consent, profile)
{
}
public override async Task<InteractionResponse> ProcessInteractionAsync(ValidatedAuthorizeRequest request, ConsentResponse consent = null)
{
var response = await base.ProcessInteractionAsync(request, consent);
if (response.IsConsent || response.IsLogin || response.IsError)
return response;
return new InteractionResponse
{
RedirectUrl = "/Organization"
};
}
}
它继承自IdentityServer4内置的基础AuthorizeInteractionResponseGenerator,因此可以显示标准的登录和同意页面。发生这种情况,然后用户被正确重定向到
/Organization
url 以选择一个组织(租户)。
然后呢?由于缺乏文档和示例,我真的很难弄清楚以下两个问题:
1) 我现在如何在选择租户后向我的自定义 AccountChooserResponseGenerator 指示我的交互已完成,并且现在可以将用户重定向回客户端?
编辑:
回答1:表示交互完成,你我要返回一个空的new InteractionResponse()。在我的例子中,检查 TenantId 声明是否存在就足够了,如下所示:
if (!request.Subject.HasClaim(c=> c.Type == "TenantId" && c.Value != "0"))
return new InteractionResponse
{
RedirectUrl = "/Organization"
};
return new InteractionResponse();
2) 我怎样才能获得有关所选租户的信息以添加到 IdentityServer4 传递回客户端的身份令牌中?
编辑:对 2 的回答:在选择租户后执行的控制器操作方法中,我调用了:
await HttpContext.SignInAsync(User.Claims.Single(r=> r.Type == "sub").Value,
new System.Security.Claims.Claim("TenantId", tenant.Id.ToString()));
return Redirect(ReturnUrl);
要在 IdentityServer4 中实现自定义交互响应生成器并将有关所选租户的信息添加到身份令牌,您可以从基础 AuthorizeInteractionResponseGenerator 继承并覆盖 ProcessInteractionAsync 方法。也可以使用IdentityServer4提供的IProfileService接口,在签发token前,将租户信息作为用户身份的声明添加
实现自定义交互响应生成器的步骤:
继承自基础 AuthorizeInteractionResponseGenerator 并覆盖 ProcessInteractionAsync 方法:
// Example implementation of ProcessInteractionAsync
public override async Task<InteractionResponse> ProcessInteractionAsync(ValidatedAuthorizeRequest request, ConsentResponse consent = null)
{
// Your custom logic here
// Indicate that the interaction is complete
return new InteractionResponse();
}
将有关所选租户的信息添加到身份令牌:
// Example implementation of IProfileService
public class CustomProfileService : IProfileService
{
private readonly UserManager<ApplicationUser> _userManager;
public CustomProfileService(UserManager<ApplicationUser> userManager)
{
_userManager = userManager;
}
public async Task GetProfileDataAsync(ProfileDataRequestContext context)
{
var user = await _userManager.GetUserAsync(context.Subject);
if (user != null)
{
var tenantIdClaim = user.Claims.FirstOrDefault(c => c.Type == "TenantId");
if (tenantIdClaim != null)
{
context.IssuedClaims.Add(new Claim("tenant_id", tenantIdClaim.Value));
}
}
}
public Task IsActiveAsync(IsActiveContext context)
{
return Task.CompletedTask;
}
}
在 Startup.cs 文件中使用 IdentityServer4 注册 CustomProfileService:
services.AddTransient<IProfileService, CustomProfileService>();
温馨提示: