在 Open Id Connect 事件期间提示用户提供额外信息?

Prompt user for additional information during an Open Id Connect event?

使用 asp.net Core、Mvc 和 OpenIdConnect,是否可以在 ODIC 身份验证过程中提示经过身份验证的用户提供其他信息,然后重定向回最初需要的页面?

举一个具体的例子:在我们的系统中,一个人,由一个电子邮件地址代表,可以有多个用户 ID,他们可能希望在这些用户 ID 下进行操作。假设我的电子邮件地址是 tregan@domain.com,并且我有 3 个用户 ID 可供选择:treganCat、treganDog、treganMouse。当我点击一个用 [Authorize] 属性修饰的 Controller 操作时,我首先通过 OpenIdConnect 身份验证,返回的声明之一是电子邮件地址。

使用该电子邮件地址,我希望应用程序提示我 select 我想要 运行 在(treganDog、treganCat 或 treganMouse)下的身份。

从那里,我希望应用程序获取我 selected 的用户 ID,查询数据库以查找与 selected 用户 id 一起使用的角色,然后加载这些角色作为对我身份的声明。

最后,我希望应用程序将我转到我想要的页面(这是我最初尝试访问的受保护的控制器方法)。

这可能吗?

我正在使用 Owin Startup class;下面的代码 "works" 除了虚构的行 "var identityGuid = [return value from the prompt];" ("fictional" 因为它代表了我想要发生的事情,但实际上需要一系列重定向)。

我下面的示例使用了 OnTicketReceived 事件,但是 selection 是任意的,无论如何我都愿意这样做。

        services.AddAuthentication(authenticationOptions =>
            {
                authenticationOptions.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                authenticationOptions.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
            })
            .AddCookie()
            .AddOpenIdConnect(openIdConnectOptions =>
            {
                openIdConnectOptions.Authority = Configuration["PingOne:Authority"];
                openIdConnectOptions.CallbackPath = "/Callback";
                openIdConnectOptions.ClientId = Configuration["PingOne:ClientId"];
                openIdConnectOptions.ClientSecret = Configuration["PingOne:ClientSecret"];
                openIdConnectOptions.ResponseType = "code";

                openIdConnectOptions.Events.OnTicketReceived = (ticketReceivedContext) =>
                {                   
                    var emailClaim =
                        ticketReceivedContext.Principal.Claims.FirstOrDefault(o =>
                            o.Type == ClaimTypes.Email);
                    string emailAddress = emailClaim.Value;

                    //here is where I would like to prompt the user to select an identity based on the email address
                    //the selected identity is represented by a guid
                    var identityGuid = [return value from the prompt];

                   var roles = new MyRepository(myContext).GetRolesForUserId(identityGuid);

                    var claims = new List<Claim>();
                    foreach (string role in roles)
                    {
                        claims.Add(new Claim(ClaimTypes.Role, role));
                    }

                    ticketReceivedContext.Principal.AddIdentity(new ClaimsIdentity(claims));
                    return Task.CompletedTask;
                };

            }); 

这是模拟真实用户,您需要在登录后识别模拟用户。

您需要先完成登录,return 到应用程序并配置主体。然后渲染一个 UI 并接收选择的选项。

然后您需要 UI 调用后端并告诉它更新 auth cookie 中的声明。不确定您是否能让它正常工作 - 模拟用户可能需要单独存储 - 例如第二个 cookie。

这突出表明,将 UI 收到的令牌/凭据与后端使用的声明分开可能很有用。

对于直接为 UI 提供服务的 REST API,我经常使用以下设计 - 尽管这对您的解决方案来说可能有点矫枉过正: https://authguidance.com/2017/10/03/api-tokens-claims/

我认为如果不在 PingOne 中找到一种方法或者编写我自己的 IdentityServer 并在那里处理额外的步骤,我想做的事情是不可能的。

我决定改为编写一个在身份验证中间件之后触发的自定义中间件,如以下 SO 问题所述: