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