IdentityServer4登出

8

我遇到了一个问题,就是似乎无法让我的 Identity Server 注销显示确认提示。我从 Github 上下载了 IdentityServer4 的源代码,并在 Models 文件夹中找到了 LogoutRequest.cs 这个参数:ShowSignOutPrompt。在注销期间,IdentityServer 没有参考它。

在调试时,我发现它的值为 false。我不知道这个参数应该在哪里设置,我已经检查了服务器和客户端配置的选项,以及服务器启动时的选项。

我在客户端代码中找不到任何关于“ShowSignoutPrompt”的实例(我目前使用的是 IdentityServer3 Owin Hybrid 客户端示例)。

以下是代码流程: 我们在默认布局中有一个按钮,触发客户端的 AccountController.Signout():

public void Signout()
{
    Request.GetOwinContext().Authentication.SignOut();
}

从那里开始,我不确定接下来是怎么做的,但接下来它会触发IdentityServer的AccountController.Logout(string logoutId)方法。该方法使用AccountServices.BuildLogoutViewModelAsync中的检查构建了注销提示视图,并将其返回给用户的浏览器。只有当PostLogoutRedirectUri设置为“/signout-callback-oidc”时,才能使ShowSignoutPrompt不被设置为false。我不知道为什么。

当用户在上面生成的视图上单击“yes”时,它会转到IdSrvr的AccountController.Logout(LogoutInputModel model)。我正在尝试更改该方法的最后一行,从:

return View("LoggedOut", vm);

to:

return Redirect(vm.PostLogoutRedirectUri);

这里还有一个问题,即使我在客户端配置中设置了PostRedirectUri(实际上,身份服务器的客户端配置也有它),但这里仍然是null。

如果我将PostLogoutRedirectUri设置为“/signout-callback-oidc”,那么它成功显示注销提示,但是在IdentityServer AccountController中会抛出一个错误,因为AccountService.BuildLoggedOutViewModelAsync返回了一个空的视图模型。 - JakeJ
我还在IdentityServer主机控制器文件夹中看到了AccountOptions.cs。我目前的值为: ShowLogoutPrompt = true; AutomaticRedirectAfterSignOut = false;我很快就会尝试自动重定向,我想我之前对此也有些不稳定的行为。 - JakeJ
应该注意的是,如果您正在使用外部身份提供程序,则AccountController的Logout(string logoutId)方法实际上会被调用多次(3次):
  1. 第一次从客户端的Signout()方法触发它。
  2. 在用户单击确认注销视图上的“是”后。
  3. 在外部身份提供程序在那一端签出用户后返回控件后触发(从Logout(LoggedOutViewModel model)方法触发)。
这可能会导致很多混乱。 我还没有到达那里。
- JakeJ
我在尝试让注销提示并返回客户端注销页面时提出了两个单独的问题,一个是这个:https://dev59.com/clUM5IYBdhLWcg3wQOXw 我将以下内容标记为答案,因为它澄清了很多问题,如果这不足够,请查看我回答的另一个问题。 - JakeJ
2个回答

6

没有客户端属性来控制这个。

当客户端应用程序注销时,会调用IdentityServer4的End Session Endpoint

当客户端发送原始id_token时,可以绕过登出提示。这是通过id_token_hint参数传递的。

此外,它表明是否已经验证了登出请求,因此安全地不提示用户进行登出。参考

ShowSignoutPrompt根据传递到结束会话端点的参数指示是否应提示用户进行登出。来源PDF

注意: 如果您正在使用JavaScript OIDC-Client-JS库,'signoutRedirect'方法将在内部检查,参见_signoutStart方法第354行,id_token_hint参数或用户的id_token。因此,如果您正在使用此库注销用户并想要强制注销屏幕,则必须清除user.id_token。

_signoutStart()的示例部分:

_signoutStart(args = {}, navigator, navigatorParams = {}) {
    ...
    var id_token = args.id_token_hint || user && user.id_token;
    if (id_token) {
        Log.debug("Setting id_token into signout request");
        args.id_token_hint = id_token;
    }
    ...
}

更新:

如果您正在使用 IdentityServer4 版本 2.x,您可以使用新的 ClientProperty 类来存储键值对。在这里,您可以创建一个键为 "LogoffPromptRequired",值为 "true" 的键值对,用于在客户端或 IdentityServer 实现中确定是否需要显示注销屏幕。


所以,如果我想强制注销提示,我应该修改客户端,不发送id_token,我猜是这样。 - JakeJ
你有哪种类型的客户端?C# API,带有JavaScript的Web客户端? - aaronR
1
客户端的原始来源是来自IdentityServer示例,MVC Owin Hybrid。必须使用它才能使.NET标准项目与.NET Core IdentityServer4一起工作。该客户端来自IdentityServer3,但仍可与IdentityServer4一起使用。 - JakeJ
你能分享一下你的问题细节中客户端的注销代码吗? - aaronR
@aaronR,当使用oidc-client-js库时,是否有选项可以绕过身份验证服务器的注销屏幕?我正在编写一个注销功能来踢出空闲用户。我使用了createSignoutRequest(id_token_hint: user.id_token)并执行了GET请求到此端点,但它没有起作用。 - Narshe

0
我建议在客户端应用程序中实现提示,然后在完成后重定向到endsession。

你是说让用户决定是否显示注销提示框? - aaronR
我已经弄清楚了如何让IdentityServer接受PostLogoutRedirectUri,将会提供一个带有相关细节和陷阱/兔子洞的答案,以解决在服务器端得到空值的问题。感谢大家的帮助。 - JakeJ

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接