【问题标题】:How can I redirect after OAUTH2 with SameSite=Strict and still get my cookies?如何在 OAUTH2 之后使用 SameSite=Strict 重定向并仍然获取我的 cookie?
【发布时间】:2017-07-02 04:26:18
【问题描述】:

祝你好运!除了40781534,接受的答案是设置SameSite=Lax

如何设置SameSite=Strict cookie 以重定向到我自己,以便我可以从Chrome 56.0.2924.87 取回cookie,即使用户的请求本身是来自我的OAUTH2 登录页面的重定向供应商?

完整的请求链是:

  • POST https://provider.com/callback302 FOUND 与:

    Location: https://me/login?code=xxx&state=yyy
    
  • GET https://example.com/login?code=xxx&state=yyy302 FOUND303 SEE OTHER(似乎无关紧要)与:

    Location: https://example.com/destination
    Set-Cookie: sid=zzzz; Secure; HttpOnly; SameSite=Strict; Path=/
    
  • GET https://example.com/destination401 GET OFF MY LAWN 因为浏览器没有提供sid cookie

  • GET https://example.com/destination200 OK 如果我刷新,因为那样网站是相同的,我的浏览器会显示sid cookie

对于用户上次加载的页面不在example.com 上的一般情况,我很欣赏将sid 呈现给/destination 的CSRF 潜力,但我只是从@987654341 设置它 @,我是现在重定向到/destination的人。

当然,我可以设置SameSite=Lax,但如果有人能找到某种方法,通过错误形成 URL 来触发他们从我的网站重定向他们的选择,那岂不是存在点击劫持的可能性?

【问题讨论】:

    标签: google-chrome cookies oauth-2.0


    【解决方案1】:

    HTTP OK 与 HTML 重定向确保重定向的请求实际发送 SameSite=Strict cookie。

    解决方案很简单。代替 302,发送带有以下正文的 200:

    <html>
    <head>
    <meta http-equiv="refresh" content="0;URL='https://example.com/destination'"/>
    </head>
    <body><p>Moved to <a href="https://example.com/destination">https://example.com/destination</a>.</p></body>
    </html>
    

    Using meta refresh to create an instant client-side redirect

    我的 OIDC 场景涉及:

    • GET 302 https://strict 重定向到不同的域
    • GET 302 https://oidc 重定向
    • GET 200 https://oidc/2 ok
    • POST 302 http://strict
    • GET 200 https://strict/redirect?returnUrl=target(新的 HTML 重定向
    • GET 200 https://strict/target

    通常我们会在 OIDC POST 上 302 重定向到目标,但是这不适用于 SameSite=Strict。浏览器拒绝发送 cookie,即使它存储了它。如果您关闭浏览器并重新打开,它将发送 cookie。通过添加额外的 HTML 重定向,浏览器在请求最终 URL 时发送 cookie。

    在 .NET Core 中,我可以通过将 Response.Redirect 替换为 HTML 重定向解决方案来使用 SameSite=Strict cookie:

    public sealed class OpenIdConnectHtmlRedirectHandler : OpenIdConnectHandler
    {
        public OpenIdConnectHtmlRedirectHandler(IOptionsMonitor<OpenIdConnectOptions> options,
                                                ILoggerFactory logger,
                                                HtmlEncoder htmlEncoder,
                                                UrlEncoder encoder,
                                                ISystemClock clock) : base(options, logger, htmlEncoder, encoder, clock) { }
    
        public override async Task<bool> HandleRequestAsync()
        {
            if (!await base.HandleRequestAsync())
                return false;
    
            var headers = Response.GetTypedHeaders();
            if (null == headers.Location)
                return true;
    
            Response.ContentType = "text/html";
            Response.StatusCode = 200;
            headers.Location = null;
            await Response.WriteAsync($"<html><head><meta http-equiv=\"refresh\" content=\"0; URL='{location}'\"/></head></html>",
                                      Encoding.UTF8, Context.RequestAborted);
            return true;
        }
    }
    

    【讨论】:

      【解决方案2】:

      出于安全原因,我认为不能这样做。 SameSite=Strict 表示如果用户被重定向或只是点击了指向您网站的链接(来自其他主机),则不应发送 cookie。重定向就像“链接”请求。因此,如果您的服务器重定向到另一个服务器并且该服务器立即使用 3xx 代码重定向回来,则会发送 cookie,因为您的服务器位于此链的“顶部”。

      但是,如果您重定向到 oauth 提供商并且用户必须允许您在那里访问他的帐户,这意味着此“链”已损坏,即使您的网站设置了 cookie 也将不再发送(已设置但未设置发送)。您的重定向只是单击“允许”链接的“扩展”。

      如果您想阻止其他人点击劫持您的网站,请在您认为必须阻止这种行为的情况下在链接中使用 nonce,否则可能会很危险。但请考虑到大多数提供商正在为您检查,如果您的应用先前已定义并允许重定向 url。

      这里有其他解决方案(只有在您知道自己在做什么并且可以对自己承担 100% 责任时才使用)。

      • 使用“继续访问网站”链接准备网站(当然,点击链接后会发送 cookie)
      • 使用 JavaScript 重新加载窗口
      • 使用将重定向用户的 JavaScript 准备网站
      • 结合第一种和第三种方法以获得更简洁的解决方案,并且在浏览器中不支持 JavaScript 的情况下工作。

      我在开发时使用了第二个,现在我使用的是同一个站点松懈(这在 Hapi 中是默认的,可能高达 15 个版本,所以还不错)。

      【讨论】:

        猜你喜欢
        • 2020-06-21
        • 2021-08-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-10-11
        • 1970-01-01
        • 2020-05-04
        相关资源
        最近更新 更多