如何在OAUTH2之后使用SameSite = Strict重定向并仍然获取我的cookie?

时间:2017-02-14 02:10:55

标签: google-chrome cookies oauth-2.0

天儿真好!继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

我很欣赏CSRF将sid提交给/destination的潜力,因为用户上次加载的网页不在example.com上,但我只是设置了< / em>来自/login,我现在正在重定向到/destination

当然,我可以设置SameSite=Lax,但是如果有人能找到某种方法通过错误形成网址来触发从我的网站重定向他们的选择,那么就不会有点击率的潜力吗? / p>

2 个答案:

答案 0 :(得分:3)

通过HTML重定向的

HTTP OK 可以确保重定向的请求实际上发送了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场景涉及:

  • 获取302 https://严格重定向到其他域
  • 获取302 https:// oidc重定向
  • 获取200 https:// oidc / 2好的
  • POST 302 http:// strict
  • 获取200 https:// strict / redirect?returnUrl = target(新的HTML重定向
  • 获取200 https:// strict / target

通常,我们将302重定向到OIDC POST上的目标,但这不适用于SameSite=Strict。即使它存储了浏览器,浏览器也拒绝发送它。如果关闭浏览器并重新打开,它将发送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;
    }
}

答案 1 :(得分:2)

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

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

如果您想阻止他人点击您的网站,只要您认为必须在链接中使用nonce,您必须阻止这种行为,如果您不这样做则可能会有危险。但请考虑大多数提供商 正在检查 ,如果您的应用先前已定义并允许重定向网址。

以下是其他解决方案(仅在您知道自己正在做什么并且可以自行承担责任时使用)。

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

我在开发时使用了第二个,现在我使用相同的网站松弛(这在Hapi中默认为15 ver,所以它不是那么糟糕)。