【问题标题】:Identity Server 4 GetSchemeSupportsSignOutAsync returns incorrect responseIdentity Server 4 GetSchemeSupportsSignOutAsync 返回不正确的响应
【发布时间】:2019-06-13 22:21:00
【问题描述】:

我使用 dotnet 核心中的 AddOpenIdConnect 扩展方法设置了一个开放 id 连接提供程序,在本例中为 Google。来自发现文档:

https://accounts.google.com/.well-known/openid-configuration 

谷歌似乎不支持联合注销,因为没有 end_session 端点。但是,在 Identity Server 4 中,调用:

var providerSupportsSignout = await HttpContext.GetSchemeSupportsSignOutAsync(idp);

返回真。因此,在注销期间,它会尝试使用以下方式退出谷歌:

return SignOut(new AuthenticationProperties { RedirectUri = url }, vm.ExternalAuthenticationScheme);

抛出异常:

InvalidOperationException: Cannot redirect to the end session endpoint, the configuration may be missing or invalid.

这是 Identity Server 4 中的一个错误,还是在设置 Oidc 提供程序时需要设置一个配置属性,以便此扩展方法能够识别提供程序不支持注销?

【问题讨论】:

    标签: identityserver4


    【解决方案1】:

    似乎不是 Identity Server 4 中的错误。此扩展背后的 code 调用以获取底层身份验证方案处理程序。

        public static async Task<bool> GetSchemeSupportsSignOutAsync(this HttpContext context, string scheme)
        {
            var provider = context.RequestServices.GetRequiredService<IAuthenticationHandlerProvider>();
            var handler = await provider.GetHandlerAsync(context, scheme);
            return (handler != null && handler is IAuthenticationSignOutHandler);
        }
    

    在这种情况下,您的处理程序将是OpenIdConnectHandler,它似乎实现了IAuthenticationSignOutHandler,这就是为什么无论发现文档中的内容(是否支持结束会话端点),如果您使用AddOpenIdConnect(...),它将始终注册一个看似支持注销的处理程序,但正如您所指出的,实际上并没有为这种功能支持强制执行实际的 idp 验证 (link to handler source)。

    最后,值得一提的是,根据Microsoft docs,Identity Server 4 检查在这里是正确的,IAuthenticationSignOutHandler 实际上基本上是一个标记接口,用于确定处理程序是否支持 SignOut。

    所以我猜你只是不能使用通用的AddOpenIdConnect(...),相反,也许你应该使用没有实现IAuthenticationSignOutHandlerAddGoogle(...),这样就可以按预期使用Identity Server 4 (link to source)。

    【讨论】:

      【解决方案2】:

      正如 Vidmantas Blazevicius 提到的,使用 .AddOpenIdConnect 将使扩展方法默认为 true,因为该接口。我已将代码更改为明确检查 end_session_endpoint 的支持,方法是:

        var discoveryClient = new IdentityModel.Client.DiscoveryClient("https://accounts.google.com/.well-known/openid-configuration")
                          {
                              Policy = new IdentityModel.Client.DiscoveryPolicy
                              {
                                  ValidateEndpoints = false, //this is needed for google, if set to true then will result in error response
                                  ValidateIssuerName = false //this is needed for Microsoft, if set to true then will result in error response
                              }
                          };
      
                          var discoveryResult = await discoveryClient.GetAsync();
                          if (!discoveryResult.IsError)
                          {
                              if (!String.IsNullOrWhiteSpace(discoveryResult.EndSessionEndpoint))
                                  supportsFederatedSignOut = true;
      
                          }
      
      

      然后我在模型“SupportsFederatedSignOut”上保存一个附加属性,然后使用它来确定是否应该调用外部身份提供者注销 (SignOut)。

      【讨论】:

        猜你喜欢
        • 2021-01-22
        • 1970-01-01
        • 2020-03-24
        • 2020-03-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-12-18
        • 2016-10-13
        相关资源
        最近更新 更多