Identity Server 4 GetSchemeSupportsSignOutAsync返回错误的响应

时间:2019-06-12 15:44:45

标签: identityserver4

我使用dotnet核心中的AddOpenIdConnect扩展方法设置了一个开放ID连接提供程序(在这种情况下为Google)。在发现文档中:

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

由于没有end_session端点,因此Google似乎不支持联合注销。但是,在Identity Server 4中,调用:

var providerSupportsSignout = await HttpContext.GetSchemeSupportsSignOutAsync(idp);

返回true。因此,在注销过程中,它尝试使用以下方法登出google:

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提供程序时需要设置配置属性,以便此扩展方法能够识别提供程序不支持注销?

2 个答案:

答案 0 :(得分:2)

在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,因此,如果您使用{,则无论发现文档中有什么内容(是否支持结束会话端点),这都是为什么{1}},它将始终注册一个看似支持注销的处理程序,但是正如您所指出的那样,它实际上并未为这种功能支持(link to handler source)实施实际的idp验证。

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

因此,我想您只是不能使用通用的IAuthenticationSignOutHandler,而是应该使用未实现AddOpenIdConnect(...)的{​​{1}},因此可以与Identity Server 4一起使用( link to source)。

答案 1 :(得分:0)

如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)。