【问题标题】:Identity Server 4 - Logout - Passing Additional DataIdentity Server 4 - 注销 - 传递附加数据
【发布时间】:2018-03-06 18:25:53
【问题描述】:

当用户在某些情况下注销时,我想在已注销的页面上向他们显示一条消息。要启用此功能,我希望能够在注销时将可选参数从客户端发送到身份服务器/授权站点。

虽然我的标准注销流程正常工作,但我在处理这种情况时遇到了困难,因为信​​息似乎很少,建议的解决方案不起作用。

根据我的阅读,“状态”参数是传递此信息的正确方法,但目前还没有通过。 AcrValues 仅用于以其他方式发送信息。

我下面的简单实现只是将状态查询字符串项添加到结束会话端点。但是,当我检查我的客户端用于访问身份服务器实例的查询字符串时,它丢失了。

重定向(discoveryResponse.EndSessionEndpoint+"&state=foo")

很高兴收到任何帮助!

MVC 客户端的当前流程:

请注意;为简洁起见,一些代码已被删除。

从带有 state=foo 的客户端控制器发起的注销:

public class LogoutController : Controller
{
    public ActionResult Index()
    {
        Request.GetOwinContext().Authentication.SignOut();

        var discoveryClient = new DiscoveryClient(clientConfig.Authority) { Policy = {RequireHttps = false} };

        var discoveryResponse = discoveryClient.GetAsync().Result;

        var tokenClaim = ((ClaimsIdentity)User.Identity).FindFirst("id_token");

        return Redirect(discoveryResponse.EndSessionEndpoint+ "?id_token_hint="+ tokenClaim + "&state=foo");
    }
}

为请求调用 RedirectToIdentityProvider:

IdTokenHint 和 PostLogoutRedirectUri 已正确设置和传递。

    app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
      {
         Notifications = new OpenIdConnectAuthenticationNotifications
         {
            RedirectToIdentityProvider = n =>
            {
              if (n.ProtocolMessage.RequestType != OpenIdConnectRequestType.LogoutRequest)
              return Task.FromResult(0);

              var idTokenHint = n.OwinContext.Authentication.User.FindFirst(OpenIdConnectClaimType.IdToken);

          if (idTokenHint == null) return Task.FromResult(0);

          n.ProtocolMessage.IdTokenHint = idTokenHint.Value;

  n.OwinContext.Response.Cookies.Append("IdentityServerPostLogoutReturnUri", 
  n.ProtocolMessage.PostLogoutRedirectUri);
          n.ProtocolMessage.PostLogoutRedirectUri = 
  n.Options.PostLogoutRedirectUri;


        return Task.FromResult(0);
           }
        }

已生成 URL(不是缺少“状态”项):

http://localhost:44362/connect/endsession?post_logout_redirect_uri=http%3a%2f%2flocalhost%3a2577%2fpostloginredirect&id_token_hint=removed&x-client-SKU=ID_NET&x-client-ver=1.0.40306.1554

权威网站的登出页面:

这是我希望能够访问状态参数的地方。

public class LogoutController : Controller
{
  public async Task<ViewResult> Index(string logoutId)
  {
    if (logoutId == null) throw new Exception("Missing logoutId");

    var logoutRequest = await interactionService.GetLogoutContextAsync(logoutId);

    var vm = new LoggedOutViewModel(logoutRequest, logoutId);

    if (!string.IsNullOrWhiteSpace(httpContextService.GetCookieValue(PostLogoutReturnUriCookieKey)))
    {
      vm.PostLogoutRedirectUri = httpContextService.GetCookieValue(PostLogoutReturnUriCookieKey);
      httpContextService.ClearCookie(PostLogoutReturnUriCookieKey);
    }

    await httpContextService.SignOutAsync();
    return View("Index", vm);
  }
}

【问题讨论】:

  • 状态参数是为了客户的利益,应该对 IDP 不透明。我认为您需要在客户端应用程序的注销后处理程序中选择它。至于为什么没有在您的重定向中传递状态参数,我想这与该中间件处理程序有关。
  • 感谢 Mackie,您对中间件问题的看法是正确的。

标签: c# asp.net-mvc authentication openid-connect identityserver4


【解决方案1】:

我进行了更深入的研究,发现问题是由 Microsoft.Owin.Security.OpenIdConnect 中间件中的以下几行引起的。

protected override async Task ApplyResponseGrantAsync()
{
    AuthenticationResponseRevoke signout = Helper.LookupSignOut(Options.AuthenticationType, Options.AuthenticationMode);

    if (signout != null)
    {
        // snip
        var notification = new RedirectToIdentityProviderNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions>(Context, Options)
        {
            ProtocolMessage = openIdConnectMessage
        };

        await Options.Notifications.RedirectToIdentityProvider(notification);
        // This was causing the issue
        if (!notification.HandledResponse)
        {
            string redirectUri = notification.ProtocolMessage.CreateLogoutRequestUrl();
            if (!Uri.IsWellFormedUriString(redirectUri, UriKind.Absolute))
            {
                _logger.WriteWarning("The logout redirect URI is malformed: " + redirectUri);
            }
            Response.Redirect(redirectUri);
        }
    }
}

为了防止中间件在检测到注销消息时覆盖重定向,需要在 RedirectToIdentityProvider 事件中调用“HandleResponse”方法中的以下行。

这允许将原始“状态”查询字符串项传递给 Identity Server,并使用交互服务提取。

app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
{
    // Snip
    Notifications = new OpenIdConnectAuthenticationNotifications
    {
        AuthorizationCodeReceived = async n =>
        {
            // Snip
        },
        RedirectToIdentityProvider = n =>
        {
            // Snip
            n.HandleResponse(); // The magic happens here
        }
}

【讨论】:

    猜你喜欢
    • 2019-12-26
    • 2020-10-06
    • 1970-01-01
    • 2020-04-10
    • 2019-07-02
    • 2019-01-03
    • 1970-01-01
    • 1970-01-01
    • 2021-03-14
    相关资源
    最近更新 更多