【问题标题】:OWIN and Azure AD HTTPS to HTTP Redirect LoopOWIN 和 Azure AD HTTPS 到 HTTP 重定向循环
【发布时间】:2015-10-13 19:53:43
【问题描述】:

我对 OWIN 很陌生 :)。我正在尝试创建一个带有开放公共区域的页面,该页面将允许通过 HTTP 匿名,然后是一个需要身份验证的受限部分。我不想强迫整个网站对普通用户使用 HTTPS。

我遇到的问题是我收到以下循环:

  1. http://example.com/authenticatedPage -> 302 重定向到 AD 登录
  2. 登录到 AD 页面 HTTP 200。触发打开指向站点的 Azure AD 链接。
  3. 链接到站点标识这是一个 OWIN 重定向,并执行 302 重定向到 http://example.com/authenticatedPage
  4. 转到 1。

我尝试了 3 种在 OWIN 中拦截重定向的方法,但似乎没有任何效果。

如果我通过浏览到https://example.com/ 开始会话,然后单击到authenticatedPage 的链接,那么登录将按我的预期工作。即

  1. 加载https://example.com/authenticatedPage -> 302 重定向到 AD
  2. 登录到 AD -> 加载 https://example.com/
  3. 302 重定向到https://example.com/authenticatedPage

有没有办法在不将我的整个网站标记为需要 SSL 的情况下解决这个问题?

【问题讨论】:

    标签: azure redirect owin


    【解决方案1】:

    问题是 OIDC 中间件在您的应用程序中设置的引荐来源网址。会发生什么:

    1. http://foo.bar 上输入您的应用程序并重定向到身份提供商
    2. IDP/AD 按照配置的返回 URI 重定向到 https://foo.bar
    3. Cookie 由带有安全标志的 OIDC 中间件设置,因此仅适用于 HTTPS
    4. 中间件重定向到 HTTP 的引荐来源网址
    5. HTTP 上没有设置 Cookie,所以回到步骤 1。

    对此有多种解决方案,例如仅强制执行 SSL、重载 Authorize 属性以及将 CookieSecure 标志设置为 CookieSecureOption.Never(不要这样做)。

    我更喜欢的选项是在中间件本身中修复引用者:

    app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
    {
        Authority = ...
        ClientId = ...
        RedirectUri = "https://foo.bar"
        ResponseType = "id_token",
        Scope = "openid profile",      
        SignInAsAuthenticationType = "Cookies",
    
        // Deal with the returning tokens
        Notifications = new OpenIdConnectAuthenticationNotifications
        {
            AuthorizationCodeReceived = async n =>
            {
                // Enforce the reference/redirect to be HTTPS
                var builder = new UriBuilder(n.AuthenticationTicket.Properties.RedirectUri);
                builder.Scheme = "https";
                builder.Port = 443;
                n.AuthenticationTicket.Properties.RedirectUri = builder.ToString();
            }
        }
    });
    

    这样做是将引用 URL 上的 HTTP 重写为 HTTPS。这样,如果用户通过 HTTP 进入应用程序,他将在使用后自动重定向到 HTTPS 版本。

    【讨论】:

    • 所以您已经更新了 OWIN/您的中间件,以便在重定向之前执行此操作。开源的合理解决方案。我试图避免在开源上维护一个分支,但仍然是一个合理的解决方案。
    • @Spence 这不需要对任何开源软件或分叉进行任何更改。通知和 AuthorizationCodeReceived 处理程序已由 Microsoft 在其标准中间件中实现。
    • 在我的问题中并不明显,但我正在登录 Azure Active Directory,这没有使用 OpenID 身份验证。据我所知,该代码的可扩展性不如 open id 的东西。这个问题也有近一年的历史,所以所有的框架都向前推进了。重定向也来自 Azure,而不是我的代码。
    • AAD 支持 OIDC。这实际上是他们推荐的身份验证方式。它确实不像 AAD 目前不允许自定义范围那样可扩展(除非您是 AAD 管理员并为您的应用设置了权限)。框架确实向前发展了,使用中间件基本上是相同的。关于重定向,是的,它们确实来自 Azure 到您的主机,但是您的主机然后设置 cookie 并再次将其重定向到指定的引荐来源网址。重定向到自身是您原始问题中的问题所在。
    【解决方案2】:

    是否存在您不想将整个网站标记为需要 SSL 的特定原因?可能有解决上述问题的方法,但它们可能存在风险。如果您希望在某个时候为您的域创建一个会话 cookie,那么您要确保在没有适当的安全通道的情况下永远不会发送它......并且处理两者之间的切换很棘手。如果您可以分享您不愿意在整个应用程序中使用 SSL 的原因,那对我们来说非常有用……我们目前的假设是它是可行的,到目前为止它似乎成功了,但可能成为我们忽略的东西。

    【讨论】:

    • 托管在 azure 上。 SSL 的额外费用。我只是想在页面顶部有一个员工链接,该链接可以进行身份​​验证,以便团队使用
    • 感谢您提供额外的上下文。我最近没有使用 Azure 定价,但直到前一段时间,无论有多少路由使用 SSL,你都会支付相同的金额......换句话说,唯一的区别是使用 SSL 或根本不使用它。我会四处询问以了解情况是否发生了变化...
    【解决方案3】:

    假设我没有引入一个巨大的安全漏洞,这确实有效。覆盖授权属性并将其应用于您的控制器。如果您尝试从不安全的页面进行授权,它会先将您重定向到该页面的 HTTPS://,然后再尝试进行身份验证。这意味着来自 Azure 的重定向将重定向回 HTTPS,它就像一个魅力。 Cookie 保持安全,每个人都是赢家!

    using System.Web.Mvc;
    
    namespace Spenceee.Attributes
    {
        public class AuthorizeFromHTTPAttribute : AuthorizeAttribute
        {
            public override void OnAuthorization(AuthorizationContext filterContext)
            {
                if (!filterContext.HttpContext.Request.IsSecureConnection)
                {
                    UriBuilder redirectUrl = new UriBuilder(
                       filterContext.HttpContext.Request.Url);
                    redirectUrl.Scheme = "HTTPS";
                    redirectUrl.Port = 443;
                    filterContext.HttpContext.Response.Redirect(redirectUrl.ToString());
                    return;
                }
                else
                {
                    base.OnAuthorization(filterContext);
                }
            }
        }
    } 
    

    【讨论】:

      【解决方案4】:

      正如 Vittorio 建议的那样,强制整个网站使用 SSL 可以解决问题。假设这对您来说是一个可行的方案,只需在Global.asax.csApplication_Start 方法中添加一个全局过滤器:

      protected void Application_Start()
          {
              GlobalFilters.Filters.Add(new RequireHttpsAttribute());
              ...
      

      用户现在可以使用 HTTP 或 HTTPS 访问您的应用,并且在身份验证后将被正确地重新路由,而不会出现无限重定向循环。

      【讨论】:

      • 明白你的意思。当我使用 Azure 托管时,我的公共页面不需要 SSL,因为我的公共页面上没有任何需要安全性的内容可以节省资金,我想避免这种情况。我确实找到了一个合理的解决方案,但我很惊讶它竟然这么难。
      • 很高兴你能找到一个合理的解决方案,不幸的是这很难。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-01-18
      • 2015-10-09
      • 2019-08-13
      • 2018-12-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多