【问题标题】:IdentityServer4 as WSFederation-client with .Net Core WSFederation preview2IdentityServer4 作为带有 .Net Core WSFederation preview2 的 WSFederation 客户端
【发布时间】:2017-12-14 00:45:30
【问题描述】:

我正在尝试将 WSFederation 身份验证提供程序添加到 IdentityServer4。 最近Microsoft.AspNetCore.Authentication.WsFederation Preview 2 发布了,我可以将它添加到普通的 Asp.NetCore-Application 中。

但我很难将其添加到IdentityServer4 EntityFramework-Quickstart-Example

这就是我在 Startup.cs/ConfigureServices-method 中添加 AuthenticationProvider 的方式:

services.AddAuthentication()
                .AddWsFederation("WsFederation", options =>
                {
                    options.Wtrealm = realm;
                    options.MetadataAddress = metadata;
                })

我在前端得到了 WSFederation 的按钮,我也可以登录。但是在回调之后我得到了这个错误:

InvalidOperationException:缺少子声明 IdentityServer4.Hosting.IdentityServerAuthenticationService.AssertRequiredClaims(ClaimsPrincipal 校长)

我可以理解这是从哪里来的,它是 IdentityServer4 的 IdentityServerAuthenticationService.cs 中的 this line,它需要一个“子”声明 - WSFed 不会返回这样的声明:

if (principal.FindFirst(JwtClaimTypes.Subject) == null) throw new InvalidOperationException("sub claim is missing");

据我所知,我无法配置此声明,尽管 quickstart-project 中有一些表似乎可以用于此,尤其是那些 2:

我已经尝试将我想要使用的声明而不是主题声明添加到表中,但它似乎没有任何影响,我也不知道数据库如何映射到我添加的身份提供者在代码中。我很乐意提供有关后续步骤的任何提示,或者如果您知道任何示例,那就更好了。

P.S.:关于这个主题已经有一些问题,但它们要么来自 WSFederation 的 .Net Core 实现可用之前,要么参考 WSFederation 服务器的示例,而不是客户端。

【问题讨论】:

  • 我只是想实现类似自定义 Authenticationprovider 的想法,它扩展 WSFederation-authentication 以将 WSFed 声明(如 upn)转换为 IdentityProvider 兼容声明(如“sub”) - 但我我不确定这是否是最优雅的方式。尝试通过逐步浏览源代码和阅读文档来了解更多信息。

标签: c# asp.net-core .net-core identityserver4 ws-federation


【解决方案1】:

感谢@leastprivilege,我实施了以下解决方法来提供子声明:

services.AddAuthentication()
                .AddWsFederation("WsFederation", options =>
                {
                    options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme;
                    options.Wtrealm = realm;
                    options.MetadataAddress = metadata;
                    options.Events.OnTicketReceived += OnTicketReceived;
                })

/* some more code inbetween */

    /// <summary>
    /// Transform the UPN-claim to the sub-claim to be compatible with IdentityServer4
    /// </summary>
    private async Task OnTicketReceived(TicketReceivedContext ticketReceivedContext)
    {
        var identity = ticketReceivedContext.Principal.Identities.First();
        identity.AddClaim(new Claim("sub", ticketReceivedContext.Principal.FindFirstValue("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier")));

    }

【讨论】:

    【解决方案2】:

    您需要对从 WS-Fed 提供者返回的声明进行声明转换。通过处理 WS-Fed 处理程序本身上的事件 - 或使用快速入门 UI 中使用的“ExternalLoginCallback”模式:

    https://github.com/IdentityServer/IdentityServer4.Quickstart.UI/blob/release/Quickstart/Account/AccountController.cs#L203

    【讨论】:

    • 谢谢 - 因为子声明的检查是在 ExternalLoginCallback 被击中之前完成的,所以似乎没有分叉 IdentityServer 的唯一选择是在 AuthenticationHandler 本身进行转换,因为它应该在外部登录回调。我会试一试并报告。
    • 我实现了一个 OnTicketReceived-Eventhandler 添加一个带有子声明的新身份。我在问题底部添加了代码 - 如果您认为这是一个合适的解决方案,请随时将代码添加到您的答案中,以便我将其标记为已解决。
    • ExternalLoginCallback 不是 IdentityServer 代码库的一部分。它在用户界面中。所以无论你喜欢什么。
    • UI 代码被命中的时间太晚了,因为来自 IdentityServer 的验证代码在 UI 代码执行之前运行。这就是为什么我不能把转换放在那里。我现在遇到了另一个问题,每个主体只允许一个身份 - 因此添加另一个身份与子声明也不起作用。我找不到用于操作现有委托人声明的设置器:/ /编辑:似乎我可以设置委托人本身 - 我现在试试看。
    • 抱歉,你是对的 - 它在 ExternalLoginCallback 的“HttpContext.AuthenticateAsync”调用中输入 IdentityServer-Code。谢谢你的耐心:)
    猜你喜欢
    • 1970-01-01
    • 2018-05-27
    • 1970-01-01
    • 2016-07-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-04
    • 2017-06-08
    相关资源
    最近更新 更多