【问题标题】:Prompt user for additional information during an Open Id Connect event?在 Open Id Connect 事件期间提示用户提供其他信息?
【发布时间】:2020-03-19 00:15:03
【问题描述】:

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

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

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

从那里,我希望应用程序获取我选择的用户 ID,询问与所选用户 ID 相关的角色的数据库,并将这些角色加载为我的身份声明。

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

这可能吗?

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

下面的示例使用 OnTicketReceived 事件,但该选择是任意的,我愿意在任何情况下都这样做。

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

            }); 

【问题讨论】:

  • 对我来说,这看起来好像您应该使用 2 种完全不同的方法。 OIDC 验证用户,你想要的模拟基本上是一种授权的形式。

标签: c# asp.net-mvc asp.net-core owin openid-connect


【解决方案1】:

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

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

然后您需要您的 UI 调用后端并告诉它更新身份验证 cookie 中的声明。不知道你是否能让这个工作 - 模拟用户可能需要单独的存储 - 例如第二个 cookie。

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

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

【讨论】:

    【解决方案2】:

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

    我决定改为编写一个在身份验证中间件之后触发的自定义中间件,如以下 SO 问题中所述:In asp.net core, why is await context.ChallengeAsync() not working as expected?

    【讨论】:

      猜你喜欢
      • 2017-01-08
      • 1970-01-01
      • 1970-01-01
      • 2014-09-21
      • 2014-01-27
      • 2020-04-24
      • 2017-08-22
      • 1970-01-01
      • 2019-03-30
      相关资源
      最近更新 更多