简体   繁体   English

.Net Core 2 OpenID Connect身份验证和多个身份

[英].Net Core 2 OpenID Connect Authentication and multiple Identities

I'm still learning the Identity Framework and am pretty lost in trying to setup authentication in my .Net Core 2 MVC application. 我仍在学习Identity Framework,并且在尝试在我的.Net Core 2 MVC应用程序中设置身份验证时非常迷失。 Any suggestions are appreciated since I'm not even sure what I'm doing is correct. 感谢我提供任何建议,因为我什至不确定自己在做什么。


I have a requirement to integrate an OpenID Connect identity provider for authentication and use a secondary data source for authorization . 我需要集成OpenID Connect身份提供程序进行身份验证,并使用辅助数据源进行授权 Inconveniently I cannot use any claim from the OIDC IdP except for the name claim. 除名称声明外,我不方便使用OIDC IdP的任何声明。 The rest of the user claims must come from the secondary data source (which is connected to the Identity Framework through a custom UserStore and User entity). 其余的用户声明必须来自辅助数据源(通过自定义UserStoreUser实体连接到Identity Framework)。

I am using the OpenId Connect provider to handle the authentication. 我正在使用OpenId Connect提供程序来处理身份验证。 This is working fine and gives me the first Identity (which I can only use one Claim from). 这工作正常,并为我提供了第一个身份(我只能使用一个索赔)。 My confusion starts when I need to fetch the second Identity of the user, add it to the principal, and set it as the default Identity . 当我需要获取用户的第二个Identity并将其添加到主体,并将其设置为默认Identity时,我的困惑就开始了。 This second Identity provides all of the user claims, including role. 此第二Identity提供了所有用户声明,包括角色。

My understanding of identity framework is that I should have a single ClaimsPrincipal with two identities so that I can plug into the rest of Identity Framework. 我对身份框架的理解是,我应该有一个具有两个身份的单个ClaimsPrincipal ,以便可以插入身份框架的其余部分。 However with two identities the default ClaimsPrincipal will automatically select the first Identity (which is the one I can't use), therefor it seems I should create a custom ClaimsPrincipal and set the PrimaryIdentitySelector so that my second Identity is the primary. 但是,对于两个身份,默认的ClaimsPrincipal将自动选择第一个Identity(这是我不能使用的身份),因此,似乎我应该创建一个自定义ClaimsPrincipal并设置PrimaryIdentitySelector以使我的第二个Identity为主要身份。

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
    }
}

Once I get the validated token from the OIDC IdP, I fetch the second identity, create a new MyClaimsPrincipal, add the two Identities to the new principal. 从OIDC IdP获得经过验证的令牌后,我将获取第二个身份,创建一个新的MyClaimsPrincipal,然后将两个身份添加到新的主体中。 After that I'm not sure what to do with this new principal. 之后,我不确定该如何处理新的校长。

I've tried to sign the user in via the SignInManager , setting the User on the HTTP context explicitly, and using middleware to convert ClaimsPrincipals to MyClaimsPrincipals but all of these seem to do nothing. 我试图通过SignInManager登录用户,在HTTP上下文中显式设置User,并使用中间件将ClaimsPrincipals转换为MyClaimsPrincipals但所有这些似乎都无济于事。 I think I am missing the point. 我想我没说清楚。

Some specific questions: 一些具体问题:

  • Is this the best way to do this? 这是最好的方法吗? Being generally confused about all of this makes it hard to tell if I'm even on the right track. 人们普遍对所有这些事情感到困惑,这使得很难判断我是否走上了正确的道路。
  • Once I've created a custom principal, how to I "set" it into the HTTP context so that it's persistent? 创建自定义主体后,如何将其“设置”到HTTP上下文中以使其持久化?
  • How does Cookie authentication work with OpenId Connect authentication? Cookie身份验证如何与OpenId Connect身份验证一起使用? It seems OIDC somehow passes the user into Cookie authentication, and that adding cookie authentication is required for OIDC authentication to work. 似乎OIDC以某种方式将用户传递到Cookie身份验证,并且需要添加cookie身份验证才能使OIDC身份验证正常工作。

An important thing to know when using the OpenID Connect scheme is that the scheme will never work on its own. 使用OpenID Connect方案时要了解的重要一点是,该方案永远不会独立运行。 In pretty much every example you can find you will see it combined with the cookie scheme. 在几乎每个示例中,您都可以找到它与cookie方案的结合。 The reason for this is very simple: OIDC is for authenticating the user with an external authentication provider. 原因很简单:OIDC用于通过外部身份验证提供程序对用户进行身份验证。 But that authentication is only temporary. 但是该身份验证只是暂时的。 In order to store it locally within your application, you need to sign in your user. 为了将其本地存储在应用程序中,您需要登录用户。 This is usually done with the cookie authentication scheme (although it could be done in other ways). 这通常是通过Cookie身份验证方案完成的(尽管它可以通过其他方式完成)。

The authentication flow for an application that uses OIDC and cookies usually works like this: 使用OIDC和Cookie的应用程序的身份验证流程通常如下所示:

  1. User accesses your application. 用户访问您的应用程序。
  2. Authentication : The cookie scheme, the default authentication scheme, will attempt to authenticate the user. 身份验证 :cookie方案(默认身份验证方案)将尝试对用户进行身份验证。 If there is no cookie, the handler will challenge the authentication. 如果没有cookie,则处理程序将挑战身份验证。
  3. Challenge : The OIDC scheme, the default challenge scheme, will challenge the user and redirect to the external authentication provider. 质询 :OIDC方案(默认质询方案)将质询用户并重定向到外部身份验证提供程序。
  4. The user will authenticate with the external authentication provider and will get redirected back to the application. 用户将通过外部身份验证提供程序进行身份验证,并将重定向到应用程序。
  5. Challenge callback : The OIDC scheme will take the response from the external authentication provider, complete the challenge and create a claims principal. 质询回调 :OIDC方案将从外部身份验证提供程序获得响应,完成质询并创建声明主体。
  6. Sign-in : The OIDC scheme will sign in that principal with its configured sign-in scheme (the cookie scheme). 登录 :OIDC方案将使用其配置的登录方案(cookie方案)登录该主体。
  7. The cookie scheme will sign in the user and create a cookie that is persisted in the user's browser. cookie方案将登录用户并创建一个持久保存在用户浏览器中的cookie。
  8. On a subsequent request to your application, the user will include a valid cookie, so the cookie schem can successfully authenticate the user, without having to challenge the OIDC scheme again. 在对您的应用程序的后续请求中,用户将包括有效的cookie,因此cookie方案可以成功验证用户身份,而无需再次挑战OIDC方案。

So assuming that everything worked properly, the OIDC scheme will not be involved again in the authentication. 因此,假设一切正常,OIDC方案将不再参与身份验证。 Instead, the identity from the cookie will be used every time. 而是每次都会使用cookie中的身份。

You can use this for your purpose to expand the principal that the OIDC scheme created with additional claims, before it is signed in and persisted by the cookie scheme. 您可以将其用于您的目的,以扩展OIDC方案使用其他声明创建的主体,然后再通过Cookie方案对其进行登录和持久化。 You could do this using a custom sign-in scheme that sits between the OIDC and cookie schemes, or you could simply attach to an authentication event of the OIDC scheme that is invoked after the challenge is completed but before the sign-in occurs. 你可以做到这一点使用自定义签入方案的OIDC和饼干方案之间坐镇,或者你可以简单地连接到挑战完成出现登录之前被调用,但OIDC方案的认证活动。

You can use the TicketReceived event for this purpose: 您可以将TicketReceived事件用于此目的:

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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM