Identity Serverを使用してSameSite Cookieの問題が発生しますか?

Identity Serverを使用してSameSite Cookieの問題が発生しますか?

Webアプリケーションと認証サーバーに別々のドメインを使用している場合、Chromeでのこの変更は一部のユーザーのセッションエクスペリエンスを損なう可能性があります。

最后更新 2022/04/28 6:47
Sebastian Gingter
预计阅读 14 分钟
分类
.NET
标签
.NET C# 認証済みの ホモフォロジー。

著者:セバスチャン·ギンター

原文へのリンク:https//www.example.com

翻訳:砂漠の果ての狼

翻訳リンクhttps//www.example.com

本文是作者 2019 年的一篇分享,里面的一些观点和使用的技术,对我们现在的开发依然有效,建议查看原文阅读,对本文翻译如有疑问,欢迎提 PR

まず、良いニュース:Googleは、2020年2月にChrome 80をリリースする際に、ウェブをより安全な場所にし、ユーザーのプライバシーを向上させる“インクリメンタル·ベター·クッキー”の実装を含むようになります(ウェブマスター注:2022年4月28日現在、Chromeは複数のアップデートをリリースしています)。

悪いニュースは、この新しい実装は、ブラウザがサーバーにクッキーを送信する方法を決定する大きな変更です。まず、Webアプリケーションと認証サーバーに別々のドメインを使用している場合、Chromeでのこの変更は一部のユーザーのセッションエクスペリエンスを損なう可能性があります。2つ目の問題は、一部のユーザーがシステムから正常にログアウトできなくなる可能性もあることです。

1. まず、このSameSiteは何ですか?

Web 是一个非常开放的平台:Cookie 是在大约 20 年前设计的,以及 2011 年在 RFC 6265中重新审视该设计时,跨站请求伪造 (CSRF) 攻击和过度用户跟踪还不是什么大事。

簡単に言えば、通常のクッキー仕様では、特定のドメインにクッキーが設定されている場合、ブラウザからのリクエストごとにクッキーとともにそのドメインに送信されると述べています。ドメインに直接移動するかどうかにかかわらず、ブラウザがドメインからリソース(画像)を読み込むだけの場合は、POSTリクエストを送信するか、その一部をiframeに埋め込みます。しかし、おそらく後者の可能性については、ブラウザが自動的にユーザーセッションCookieをサーバーに送信したくありません。これにより、任意のウェブサイトがそのユーザーのコンテキスト内でサーバーへのリクエストをJava Scriptで実行できるようになります。

为了防止这种情况发生, SameSite cookie 规范 是在 2016 年起草的。它让您可以更好地控制何时应该或不应该发送 cookie:当您设置 cookie 时,您现在可以为每个 cookie 明确指定浏览器何时应将其添加到请求。为此,当浏览器位于您自己的域中时,它引入了同站点 cookie 的概念,而当浏览器在不同域中导航但向您的域发送请求时,它引入了跨站点 cookie 的概念。

为了向后兼容,相同站点 cookie 的默认设置并没有改变以前的行为。您必须选择加入该新功能并明确设置您的 cookie SameSite=LaxSameSite=Strict 使其更安全。这已在 .NET Framework(包括.NET CORE) 和所有常见浏览器中实现。 Lax 意味着,cookie 将在初始导航时发送到服务器, Strict 意味着 cookie 只会在您已经在该域上时发送(即初始导航后的第二个请求)。

遗憾的是,这项新功能的采用速度很慢(根据 2019 年 3 月 Chrome 的遥测数据 【来源 】,全球范围内 Chrome 上处理的所有 cookie 中只有 0.1% 使用 SameSite 标志)。

谷歌决定推动采用该功能。为了强制执行,他们决定更改世界上最常用的浏览器的默认设置:Chrome 80 将 必须 指定一个新的设置 SameSite=None 来保留处理 cookie 的旧方式,如果您像旧规范建议的那样省略 SameSite 字段,它将 cookie 视为使用 SameSite=Lax.

请注意: 该设置 SameSite=None 仅在 cookie 也被标记为 Secure 并需要 HTTPS 连接时才有效。

更新: 如果您想了解有关 SameSite cookie 的更多背景信息,有一篇包含 所有细节的新文章

2. 影響はありますか?もしそうなら、どうするか。

如果您有一个单页面 Web 应用程序 (SPA),它针对托管在不同域上的身份提供者(IdP,例如 IdentityServer 4)进行身份验证,并且该应用程序使用所谓的静默令牌刷新,您就会受到影响。

IdPにログインすると、IdPドメインからのセッションクッキーがユーザーに設定されます。認証プロセスの最後に、異なるドメインのアプリケーションは何らかのアクセストークンを受け取りますが、通常はそれほど長くはありません。トークンの有効期限が切れると、アプリケーションはリソースサーバ(API)にアクセスできなくなります。このような状況が発生するたびにユーザーが再度ログインする必要がある場合、ユーザーエクスペリエンスは非常に悪くなります。

これを防ぐために、サイレントトークンリフレッシュを使用できます。この場合、アプリケーションはユーザーには見えないiframeを作成し、そのiframeで認証プロセスを再度開始します。IdPのウェブサイトはiframeにロードされ、ブラウザがIdPに沿ってセッションクッキーを送信すると、新しいトークンが同時にユーザーを認識します。

现在 iframe 存在于托管在应用程序域中的 SPA 中,其内容来自 IdP 域。如果 cookie 明确指出 SameSite=None,Chrome 80 只会将该 cookie 从 iframe 发送到 IdP,这被认为是跨站点请求。 如果不是这种情况,您的静默令牌刷新将在 2 月 Chrome 80 发布时中断。

問題を引き起こす可能性のある他の状況があります。まず、動画の自動再生設定など、他のドメインから派生した要素をウェブアプリケーションやウェブサイトに埋め込み、これらが適切に機能するためにクッキーを必要とする場合、これらもSameSiteポリシーを設定する必要があります。アプリケーションがクッキー認証に依存するブラウザからサードパーティAPIを要求する必要がある場合も同様です。

注意:________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________あなたが管理していない他のドメインの要素を使用している場合は、第三者に連絡し、問題が発生した場合にクッキーの変更を依頼する必要があります。

3. コードを変更して、SameSiteをNoneに設定します。今はできるよね?

不幸的是,Safari 有一个“错误”。此错误导致 Safari 无法将新引入的值 None 识别为 SameSite 设置的有效值。当 Safari 遇到无效值时,它会将 SameSite=Strict 当作已指定的设置,并且不会将会话 cookie 发送到 IdP。此错误已在 iOS 13 和 macOS 10.15 Catalina 上的 Safari 13 中修复,但不会向后移植到 macOS 10.14 Mojave 和 iOS 12,它们仍然拥有非常大的用户群。

所以,我们现在陷入了两难境地:要么我们忽略 SameSite 策略,我们的 Chrome 用户无法进行静默刷新,要么我们设置 SameSite=None 并锁定 iPhone、iPad 和 Mac 用户无法更新,或者旧设备无法更新到最新版本的 iOS 和 macOS。

4. 影響を受けていることを確認する方法は?

幸运的是,是的。如果您已经设置 SameSite=None,您可能已经注意到您的应用程序或网站在 iOS 12 和 macOS 10.4 上的 Safari 中无法正常工作。如果没有,请确保在这些版本的 Safari 中测试您的应用程序或网站。

SameSiteの値をまったく設定しない場合は、Chromeでアプリを開き、開発者ツールを開くだけです。次の警告が表示されます:

A cookie associated with a cross-site resource at {cookie domain} was set without the `SameSite` attribute.
A future release of Chrome will only deliver cookies with cross-site requests if they are set with `SameSite=None` and `Secure`.
You can review cookies in developer tools under Application>Storage>Cookies and see more details at
https://www.chromestatus.com/feature/5088147346030592 and
https://www.chromestatus.com/feature/5633521622188032.

如果您已经设置 SameSite=None 但忘了设置 Secure 标志,您将收到以下警告:

A cookie associated with a resource at {cookie domain} was set with `SameSite=None` but without `Secure`.
A future release of Chrome will only deliver cookies marked `SameSite=None` if they are also marked `Secure`.
You can review cookies in developer tools under Application>Storage>Cookies and
see more details at https://www.chromestatus.com/feature/5633521622188032.

5. どうすればこの問題を解決できるでしょう?ChromeとSafariは普通に使う必要がある。

我们,也就是我的同事 Boris Wilhelms 和我自己,对该主题进行了一些研究,并找到且验证了解决方案。微软的 Barry Dorrans 也有一篇 关于这个问题的好博文。该解决方案并不美观,遗憾的是需要在服务器端进行浏览器嗅探,但这是一个简单的解决方案,在过去的几周里,我们已经在我们的几个客户项目中成功实现了这一点。

要解决这个问题,我们首先需要确保需要通过跨站点请求传输的 cookie(例如我们的会话 cookie)设置为 SameSite=NoneSecure。我们需要在项目代码中找到该 cookie 的选项并进行相应调整。这解决了 Chrome 的问题并引入了 Safari 问题。

然后我们将以下类和代码片段添加到项目中。这会在 ASP.NET Core Web 应用程序中添加和配置 cookie 策略。此策略将检查是否设置了 cookie 为 SameSite=None 。如果是这种情况,它将检查浏览器的用户代理,并确定这是否是一个浏览器的设置有问题,比如我们受影响的 Safari 版本。如果也是这种情况,它会将 cookies SameSite 值设置为unspecified(未指定),这反过来将完全阻止设置 SameSite,从而为这些浏览器重新创建当前默认行为。

请注意: 此处提供的解决方案适用于 .NET Core。对于完整的基于 .NET Framework 的项目,您需要查看Barry Dorran 的帖子中指定的版本之一 。

5.1プロジェクトに追加するクラス

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;

namespace Microsoft.Extensions.DependencyInjection
{
   public static class SameSiteCookiesServiceCollectionExtensions
   {
      /// <summary>
      /// -1 defines the unspecified value, which tells ASPNET Core to NOT
      /// send the SameSite attribute. With ASPNET Core 3.1 the
      /// <seealso cref="SameSiteMode" /> enum will have a definition for
      /// Unspecified.
      /// </summary>
      private const SameSiteMode Unspecified = (SameSiteMode) (-1);

      /// <summary>
      /// Configures a cookie policy to properly set the SameSite attribute
      /// for Browsers that handle unknown values as Strict. Ensure that you
      /// add the <seealso cref="Microsoft.AspNetCore.CookiePolicy.CookiePolicyMiddleware" />
      /// into the pipeline before sending any cookies!
      /// </summary>
      /// <remarks>
      /// Minimum ASPNET Core Version required for this code:
      ///   - 2.1.14
      ///   - 2.2.8
      ///   - 3.0.1
      ///   - 3.1.0-preview1
      /// Starting with version 80 of Chrome (to be released in February 2020)
      /// cookies with NO SameSite attribute are treated as SameSite=Lax.
      /// In order to always get the cookies send they need to be set to
      /// SameSite=None. But since the current standard only defines Lax and
      /// Strict as valid values there are some browsers that treat invalid
      /// values as SameSite=Strict. We therefore need to check the browser
      /// and either send SameSite=None or prevent the sending of SameSite=None.
      /// Relevant links:
      /// - https://tools.ietf.org/html/draft-west-first-party-cookies-07#section-4.1
      /// - https://tools.ietf.org/html/draft-west-cookie-incrementalism-00
      /// - https://www.chromium.org/updates/same-site
      /// - https://devblogs.microsoft.com/aspnet/upcoming-samesite-cookie-changes-in-asp-net-and-asp-net-core/
      /// - https://bugs.webkit.org/show_bug.cgi?id=198181
      /// </remarks>
      /// <param name="services">The service collection to register <see cref="CookiePolicyOptions" /> into.</param>
      /// <returns>The modified <see cref="IServiceCollection" />.</returns>
      public static IServiceCollection ConfigureNonBreakingSameSiteCookies(this IServiceCollection services)
      {
         services.Configure<CookiePolicyOptions>(options =>
         {
            options.MinimumSameSitePolicy = Unspecified;
            options.OnAppendCookie = cookieContext =>
               CheckSameSite(cookieContext.Context, cookieContext.CookieOptions);
            options.OnDeleteCookie = cookieContext =>
               CheckSameSite(cookieContext.Context, cookieContext.CookieOptions);
         });

         return services;
      }

      private static void CheckSameSite(HttpContext httpContext, CookieOptions options)
      {
         if (options.SameSite == SameSiteMode.None)
         {
            var userAgent = httpContext.Request.Headers["User-Agent"].ToString();

            if (DisallowsSameSiteNone(userAgent))
            {
               options.SameSite = Unspecified;
            }
         }
      }

      /// <summary>
      /// Checks if the UserAgent is known to interpret an unknown value as Strict.
      /// For those the <see cref="CookieOptions.SameSite" /> property should be
      /// set to <see cref="Unspecified" />.
      /// </summary>
      /// <remarks>
      /// This code is taken from Microsoft:
      /// https://devblogs.microsoft.com/aspnet/upcoming-samesite-cookie-changes-in-asp-net-and-asp-net-core/
      /// </remarks>
      /// <param name="userAgent">The user agent string to check.</param>
      /// <returns>Whether the specified user agent (browser) accepts SameSite=None or not.</returns>
      private static bool DisallowsSameSiteNone(string userAgent)
      {
         // Cover all iOS based browsers here. This includes:
         //   - Safari on iOS 12 for iPhone, iPod Touch, iPad
         //   - WkWebview on iOS 12 for iPhone, iPod Touch, iPad
         //   - Chrome on iOS 12 for iPhone, iPod Touch, iPad
         // All of which are broken by SameSite=None, because they use the
         // iOS networking stack.
         // Notes from Thinktecture:
         // Regarding https://caniuse.com/#search=samesite iOS versions lower
         // than 12 are not supporting SameSite at all. Starting with version 13
         // unknown values are NOT treated as strict anymore. Therefore we only
         // need to check version 12.
         if (userAgent.Contains("CPU iPhone OS 12")
            || userAgent.Contains("iPad; CPU OS 12"))
         {
            return true;
         }

         // Cover Mac OS X based browsers that use the Mac OS networking stack.
         // This includes:
         //   - Safari on Mac OS X.
         // This does not include:
         //   - Chrome on Mac OS X
         // because they do not use the Mac OS networking stack.
         // Notes from Thinktecture:
         // Regarding https://caniuse.com/#search=samesite MacOS X versions lower
         // than 10.14 are not supporting SameSite at all. Starting with version
         // 10.15 unknown values are NOT treated as strict anymore. Therefore we
         // only need to check version 10.14.
         if (userAgent.Contains("Safari")
            && userAgent.Contains("Macintosh; Intel Mac OS X 10_14")
            && userAgent.Contains("Version/"))
         {
            return true;
         }

         // Cover Chrome 50-69, because some versions are broken by SameSite=None
         // and none in this range require it.
         // Note: this covers some pre-Chromium Edge versions,
         // but pre-Chromium Edge does not require SameSite=None.
         // Notes from Thinktecture:
         // We can not validate this assumption, but we trust Microsofts
         // evaluation. And overall not sending a SameSite value equals to the same
         // behavior as SameSite=None for these old versions anyways.
         if (userAgent.Contains("Chrome/5") || userAgent.Contains("Chrome/6"))
         {
            return true;
         }

         return false;
      }
   }
}

このクッキーポリシーを使用するには、以下を起動コードに追加する必要があります。

public void ConfigureServices(IServiceCollection services)
{
   // Add this
   services.ConfigureNonBreakingSameSiteCookies();
}

public void Configure(IApplicationBuilder app)
{
   // Add this before any other middleware that might write cookies
   app.UseCookiePolicy();

   // This will write cookies, so make sure it's after the cookie policy
   app.UseAuthentication();
}

6. いいですね。もう終わったのか?

除了彻底的测试,特别是在 Chrome 79 中激活了“默认 cookie 的 SameSite”标志以及 macOS 和 iOS 上受影响的 Safari 版本,是的,你现在应该没事了。要在 Chrome 79 中进行测试,请导航到 chrome://flags、搜索 samesite 并启用该 SameSite by default cookies 标志。重新启动浏览器,您可以立即测试即将发生的更改。

真剣に:サイレントリフレッシュ(または通常、クッキーを必要とするクロスサイトリクエスト)が、これらのデバイスやブラウザで動作することを確認してください。

7. 認証サーバベンダーがこの問題を解決するのを待つことはできませんか?

这是不太可能的。在我们这里的具体示例中,实际上管理 cookie 的不是 IdentityServer 本身。IdentityServer 依赖于 ASP.NET Core 框架的内置身份验证系统,这是管理会话 cookie 的地方。虽然 ASP.NET Core 框架已更新以支持新 SameSiteNone 和技术设置 Unspecified (不发送 SameSite ), 但微软表示 他们不能直接在 ASP.NET Core 中引入用户代理嗅探。所以这真的取决于你和你现有的项目。

8. まとめまとめまとめ

Chrome 将很快(2020 年 2 月)更改其处理 cookie 的默认行为。将来,它将默认 SameSite 被明确设置为None标志 和 Secure 标志设置,以允许将 cookie 添加到某些跨站点请求。如果你这样做,常见版本的 Safari 就会对此感到厌烦。

为确保所有浏览器都满意,您将所有受影响的 cookie 设置为 SecureSameSite=None,然后添加一个 cookie 策略(如上所示的代码),该策略可以覆盖这些设置并再次为无法对 None 正确解释该值的浏览器删除SameSite标志.

Keep Exploring

延伸阅读

更多文章
同分类 / 同标签 2026/04/22

バージョン別の. NETサポート状況(250 7 0 7更新)

仮想マシンとテストマシンを使用して、各バージョンのオペレーティングシステムの. NETサポートをテストします。オペレーティングシステムのインストール後、対応するランタイムを測定し、スターダストエージェントをパスとして実行できます。

继续阅读
同分类 / 同标签 2026/02/07

AOTの使用経験

プロジェクトの最初から、新しい機能が追加されたり、新しい構文が使用されたりするたびに、AOTリリーステストを行うという良い習慣を身につける必要があります。

继续阅读