使用Sustainsys Saml2的ASP.NET身份-如何持久保存ExternalLoginInfo声明?

问题描述

我有一个针对netcoreapp3.1的ASP.NET Core应用,该应用使用ASP.NET Identity和Sustainsys.Saml2.AspNetCore2软件包进行设置。

由IDP发起的SAML身份验证工作正常,但是在身份验证重定向后,我无法从已登录用户检索自定义属性/声明。

在我的ExternalLogin.cshtml.cs类中,自定义声明出现在ExternalLoginInfo.Principal上(如下面的代码中的var info所示),但是在Context.User.Claims之后重定向

也就是说,_logger.Loginformation($"PatientId: {info.Principal.FindFirst("PatientId")}");打印在自定义PatientId SAML属性中传递的值,但是@Context.User.FindFirst("PatientId");重定向后为空。

public async Task<IActionResult> OnGetCallbackAsync(string returnUrl = null,string remoteError = null)
        {
            returnUrl = returnUrl ?? Url.Content("~/");
            if (remoteError != null)
            {
                ErrorMessage = $"Error from external provider: {remoteError}";
                return RedirectToPage("./Login",new { ReturnUrl = returnUrl });
            }
            var info = await _CustomSignInManager.GetExternalLoginInfoAsync();
            if (info == null)
            {
                ErrorMessage = "Error loading external login information.";
                return RedirectToPage("./Login",new { ReturnUrl = returnUrl });
            }

            // Sign in the user with this external login provider if the user already has a login.
            var result = await _CustomSignInManager.ExternalLoginSignInAsync(info.LoginProvider,info.ProviderKey,isPersistent: false,bypasstwoFactor: true);
            if (result.Succeeded)
            {
                _logger.Loginformation($"{info.Principal.Identity.Name} logged in with {info.LoginProvider} provider.");
                _logger.Loginformation($"PatientId: {info.Principal.FindFirst("PatientId")}");
                return LocalRedirect(returnUrl);
            }

    ...
}

我从this answer得出的结论是,这些声明仍然应该可用。我是否需要以某种方式将ExternalLoginInfo.Principal(而只是LoginProviderProviderKey)传递给ExternalLoginSignInAsync方法

我要说的是,我只想保留会话期间的声明,而不是将它们添加AspNetUserClaims数据库。每次登录时它们都会不同。

解决方法

我发现了一些可行的方法。在结尾处的我的问题是:“ 是否需要以某种方式将ExternalLoginInfo.Principal(而不只是LoginProvider和ProviderKey)传递给ExternalLoginSignInAsync方法?”。

如上所述,ExternalLoginSignInAsync方法位于CustomSignInManager类中(出于与该问题无关的原因,这是一个自定义实现,但该方法与默认的ASP.NET Identity相同。 SignInManager)。

将请求路径跟踪到“底部”,ExternalLoginSignInAsync调用SignInOrTwoFactorAsync,后者调用SignInAsync。在SignInAsync中,创建并返回一个新的ClaimsIdentity。因此,我只需要通过所有这些方法从ExternalLoginInfo.Principal实例传递它们,以便可以将它们设置为新的主体。

可能有用的细节:我选择创建一个CustomClaimSet类来存储自定义属性,然后必须更新所有方法签名以接受一个CustomClaimSet作为参数。