我仍在学习Identity Framework,并且在尝试在.Net Core 2 MVC应用程序中设置身份验证时非常迷失。感谢您提供任何建议,因为我什至不确定自己在做什么。
我需要集成一个OpenID Connect身份提供程序进行身份验证,并使用辅助数据源进行授权。除名称声明外,我不方便使用OIDC IdP的任何声明。其余的用户声明必须来自辅助数据源(通过自定义UserStore
和User
实体连接到Identity Framework)。
我正在使用OpenId Connect provider来处理身份验证。这工作正常,并为我提供了第一个身份(我只能使用一个索赔)。当我需要获取用户的第二个Identity并将其添加到主体,并将其设置为默认Identity
时,我的困惑就开始了。第二Identity
提供了所有用户声明,包括角色。
我对身份框架的理解是,我应该有一个带有两个身份的ClaimsPrincipal
,以便可以插入身份框架的其余部分。但是,对于两个身份,默认的ClaimsPrincipal
将自动选择第一个身份(这是我不能使用的身份),因此,似乎应该创建自定义ClaimsPrincipal
并设置PrimaryIdentitySelector
这样我的第二个身份就是主要身份。
public class MyClaimsPrincipal : ClaimsPrincipal
{
private static readonly Func<IEnumerable<ClaimsIdentity>, ClaimsIdentity> IdentitySelector = SelectPrimaryIdentity;
/// <summary>
/// This method iterates through the collection of ClaimsIdentities and chooses an identity as the primary.
/// </summary>
private static ClaimsIdentity SelectPrimaryIdentity(IEnumerable<ClaimsIdentity> identities)
{
// Find and return the second identity
}
}
一旦我从OIDC IdP获得经过验证的令牌,就获取第二个身份,创建一个新的MyClaimsPrincipal,然后将两个身份添加到新的主体中。之后,我不确定该新校长该怎么办。
我尝试通过SignInManager
登录用户,在HTTP上下文中显式设置User,并使用中间件将ClaimsPrincipals
转换为MyClaimsPrincipals
,但所有这些似乎什么都不做。我想我错过了重点。
一些特定问题:
答案 0 :(得分:4)
使用OpenID Connect方案时要了解的重要一点是,该方案永远不会独立运行。在几乎每个示例中,您都可以找到它与cookie方案的结合。原因很简单:OIDC用于通过外部身份验证提供程序对用户进行身份验证。但是该身份验证只是暂时的。为了将其本地存储在您的应用程序中,您需要登录您的用户。通常,这是通过Cookie身份验证方案完成的(尽管可以通过其他方式完成)。
使用OIDC和cookie的应用程序的身份验证流程通常是这样的:
因此,假设一切正常,OIDC方案将不再涉及身份验证。而是每次都会使用Cookie中的身份。
您可以使用它来扩展OIDC方案使用其他声明创建的主体,然后再通过Cookie方案对其进行登录和持久化。您可以使用位于OIDC和cookie方案之间的自定义登录方案来执行此操作,或者可以简单地附加到在挑战完成后 调用的OIDC方案的身份验证事件。 em>之前进行登录。
您可以为此使用TicketReceived
event:
public void ConfigureServices(IServiceCollection services)
{
// …
services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie()
.AddOpenIdConnect(options =>
{
// …
options.Events.OnTicketReceived = OnOpenIdConnectTicketReceived;
});
}
public static Task OnOpenIdConnectTicketReceived(TicketReceivedContext context)
{
if (context.Principal.Identity is ClaimsIdentity identity)
{
identity.AddClaim(new Claim("foo", "bar"));
}
return Task.CompletedTask;
}