【发布时间】:2018-08-07 15:50:30
【问题描述】:
继this 问题之后,我最终在用户选择租户后使用HttpContext.SignInAsync(string subject, Claim[] claims) 重载将所选租户ID 作为声明(定义为“TenantId”类型)传递。
然后,我在 this 问题的自定义 AccountChooserResponseGenerator 类中检查此声明,以确定是否需要将用户定向到租户选择器页面,如下所示:
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;
if (!request.Subject.HasClaim(c=> c.Type == "TenantId" && c.Value != "0"))
return new InteractionResponse
{
RedirectUrl = "/Tenant"
};
return new InteractionResponse();
}
交互正常,用户在选择租户后被正确重定向回客户端应用程序。
但是,在我的客户端上,我有简单的:
<dl>
@foreach (var claim in User.Claims)
{
<dt>@claim.Type</dt>
<dd>@claim.Value</dd>
}
</dl>
IdentityServer4 快速入门中的 sn-p 以显示声明,遗憾的是,我的 TenantId 声明不存在。
我已在 IdentityServer 设置中的客户端定义中允许它,如下所示:
var client = new Client
{
... other settings here
AllowedScopes = new List<string>
{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
IdentityServerConstants.StandardScopes.Email,
IdentityServerConstants.StandardScopes.Phone,
"TenantId"
}
};
为了让这个 TenantId 声明在我的客户端应用程序中可见,我缺少什么?
编辑:
基于@d_f的cmets,我现在已经将TentantId添加到我服务器的GetIdentityResources()中,如下:
public static IEnumerable<IdentityResource> GetIdentityResources()
{
return new List<IdentityResource>
{
new IdentityResources.OpenId(),
new IdentityResources.Profile(),
new IdentityResources.Email(),
new IdentityResources.Phone(),
new IdentityResource("TenantId", new[] {"TenantId"})
};
}
我已经编辑了客户的startup.ConfigureServices(IServiceCollection services) 来请求这个额外的范围,如下:
services.AddAuthentication(options =>
{
options.DefaultScheme = "Cookies";
options.DefaultChallengeScheme = "oidc";
})
.AddCookie("Cookies")
.AddOpenIdConnect("oidc", options =>
{
//other settings not shown
options.Scope.Add("TenantId");
});
编辑 2:已修复!
最后@RichardGowan 的回答奏效了。那是因为(正如@AdemCaglin 出色地观察到的那样)我使用的是 IdentityServer 的 AspNetIdentity,它有自己的 IProfileService 实现,尽管有所有这些其他设置,但它一直放弃我的自定义 TenantId 声明)。
所以最后,我可以撤消所有其他设置...我没有在 GetIdentityResources 中提及 TenantId 声明,在我的 IdSrv 中的客户端定义中的 AllowedScopes 中没有提及它,并且在我的客户端services.AddAuthentication的配置中没有提到它。
【问题讨论】:
-
您已为您的客户添加了“TenantId”作为 AllowedScope,但您尚未描述该范围。类似于: services.AddIdentityServer() .AddInMemoryIdentityResources(new List
{ new IdentityResources.OpenId(), new IdentityResources.Profile(), new IdentityResources.Email(), new IdentityResource("TenantId", new[] {"租户 ID"}) }) -
并且您必须在客户端配置中请求额外的范围
-
或简单的
.AddInMemoryIdentityResources(GetIdentityResources())及更高版本:public static List<IdentityResource> GetIdentityResources() { /*Claims automatically included in OpenId scope*/ var openIdScope = new IdentityResources.OpenId(); openIdScope.UserClaims.Add("TenantId"); /* Available scopes*/ return new List<IdentityResource>{openIdScope, new IdentityResources.Profile(), new IdentityResources.Email(), /*etc*/}; } -
@d_f 感谢您的反馈...请查看我的编辑说明对我的设置所做的更改...但客户端仍然没有 TenantId 声明?
-
将
AlwaysIncludeUserClaimsInIdToken设置添加到您在 IdSrv 中的客户端配置中。
标签: authentication identityserver4