ASP.NET Core での SameSite cookie の使用Work with SameSite cookies in ASP.NET Core

作成者: Rick AndersonBy Rick Anderson

SameSiteは、クロスサイトリクエスト偽造 (csrf) 攻撃に対して何らかの保護を提供するように設計されたIETFドラフトです。SameSite is an IETF draft designed to provide some protection against cross-site request forgery (CSRF) attacks. SameSite 2019 のドラフト:The SameSite 2019 draft:

  • クッキーを既定で SameSite=Lax として扱います。Treats cookies as SameSite=Lax by default.
  • クロスサイト配信を有効にするために SameSite=None を明示的にアサートする cookie の状態を Secureとしてマークする必要があります。States cookies that explicitly assert SameSite=None in order to enable cross-site delivery should be marked as Secure.

Lax は、ほとんどのアプリ cookie で機能します。Lax works for most app cookies. OpenID connect (oidc) やws-federationのような認証形式では、既定で POST ベースのリダイレクトが設定されます。Some forms of authentication like OpenID Connect (OIDC) and WS-Federation default to POST based redirects. POST ベースのリダイレクトによって SameSite ブラウザーの保護がトリガーされるため、これらのコンポーネントの SameSite は無効になります。The POST based redirects trigger the SameSite browser protections, so SameSite is disabled for these components. ほとんどのOAuthログインは、要求フローの違いによって影響を受けません。Most OAuth logins are not affected due to differences in how the request flows.

None パラメーターを指定すると、以前の2016ドラフト標準 (iOS 12 など) を実装したクライアントとの互換性の問題が発生します。The None parameter causes compatibility problems with clients that implemented the prior 2016 draft standard (for example, iOS 12). このドキュメントの「古いブラウザーのサポート」を参照してください。See Supporting older browsers in this document.

Cookie を生成する各 ASP.NET Core コンポーネントは、SameSite が適切かどうかを判断する必要があります。Each ASP.NET Core component that emits cookies needs to decide if SameSite is appropriate.

SameSite を使用した API の使用API usage with SameSite

SameSite は、既定では Unspecifiedに設定されます。つまり、cookie に追加された属性はありません。また、クライアントは既定の動作を使用します (新しいブラウザーではなく、古いブラウザーではありません)。HttpContext.Response.Cookies.Append defaults to Unspecified, meaning no SameSite attribute added to the cookie and the client will use its default behavior (Lax for new browsers, None for old ones). 次のコードは、cookie の SameSite 値を SameSiteMode.Laxに変更する方法を示しています。The following code shows how to change the cookie SameSite value to SameSiteMode.Lax:

HttpContext.Response.Cookies.Append(
                     "name", "value",
                     new CookieOptions() { SameSite = SameSiteMode.Lax });

Cookie を出力するすべての ASP.NET Core コンポーネントは、前述の既定値よりも、そのシナリオに適した設定を上書きします。All ASP.NET Core components that emit cookies override the preceding defaults with settings appropriate for their scenarios. オーバーライドされた前の既定値は変更されていません。The overridden preceding default values haven't changed.

コンポーネントComponent Cookiecookie [既定値]Default
CookieBuilder SameSite Unspecified
Session SessionOptions. CookieSessionOptions.Cookie Lax
CookieTempDataProvider CookieTempDataProviderOptionsCookieTempDataProviderOptions.Cookie Lax
IAntiforgery アンチ Forgeryoptions. CookieAntiforgeryOptions.Cookie Strict
Cookie 認証Cookie Authentication CookieAuthenticationOptions. CookieCookieAuthenticationOptions.Cookie Lax
AddTwitter TwitterOptions.StateCookieTwitterOptions.StateCookie Lax
RemoteAuthenticationHandler<TOptions> Remoteauthenticationoptions. CorrelationCookie NoneRemoteAuthenticationHandler<TOptions> RemoteAuthenticationOptions.CorrelationCookie None
AddOpenIdConnect OpenIdConnectOptions.NonceCookieOpenIdConnectOptions.NonceCookie None
HttpContext. Cookies. AppendHttpContext.Response.Cookies.Append CookieOptions Unspecified

ASP.NET Core 3.1 以降では、次の SameSite サポートが提供されます。ASP.NET Core 3.1 and later provides the following SameSite support:

  • SameSiteMode.None が出力される動作を再定義し SameSite=NoneRedefines the behavior of SameSiteMode.None to emit SameSite=None
  • 新しい値 SameSiteMode.Unspecified を追加して、SameSite 属性を省略します。Adds a new value SameSiteMode.Unspecified to omit the SameSite attribute.
  • すべての cookie Api の既定値は Unspecifiedです。All cookies APIs default to Unspecified. Cookie を使用する一部のコンポーネントでは、そのシナリオにより具体的な値が設定されています。Some components that use cookies set values more specific to their scenarios. 例については、上の表を参照してください。See the table above for examples.

ASP.NET Core 3.0 以降では、一貫性のないクライアントの既定値と競合しないように、SameSite の既定値が変更されました。In ASP.NET Core 3.0 and later the SameSite defaults were changed to avoid conflicting with inconsistent client defaults. 次の Api が既定値を SameSiteMode.Lax から -1 に変更し、これらの cookie の SameSite 属性が出力されないようにしました。The following APIs have changed the default from SameSiteMode.Lax to -1 to avoid emitting a SameSite attribute for these cookies:

履歴と変更History and changes

SameSite サポートは、2.0 の ASP.NET Core で最初に2016 ドラフト標準を使用して実装されました。SameSite support was first implemented in ASP.NET Core in 2.0 using the 2016 draft standard. 2016標準はオプトインでした。The 2016 standard was opt-in. ASP.NET Core、いくつかの cookie を既定で Lax するように設定することによってオプトインできます。ASP.NET Core opted-in by setting several cookies to Lax by default. 認証でいくつかの問題が発生すると、ほとんどの SameSite の使用が無効になりました。After encountering several issues with authentication, most SameSite usage was disabled.

2016標準から2019標準に更新するために、2019年11月に修正プログラムが発行されました。Patches were issued in November 2019 to update from the 2016 standard to the 2019 standard. SameSite 仕様の2019ドラフト:The 2019 draft of the SameSite specification:

  • は、2016ドラフトとの下位互換性がありませんIs not backwards compatible with the 2016 draft. 詳細については、このドキュメントの「古いブラウザーのサポート」を参照してください。For more information, see Supporting older browsers in this document.
  • Cookie を既定で SameSite=Lax として扱うことを指定します。Specifies cookies are treated as SameSite=Lax by default.
  • クロスサイト配信を有効にするために SameSite=None を明示的にアサートする cookie を Secureとしてマークする必要があることを指定します。Specifies cookies that explicitly assert SameSite=None in order to enable cross-site delivery should be marked as Secure. None は、オプトアウトする新しいエントリです。None is a new entry to opt out.
  • は、ASP.NET Core 2.1、2.2、および3.0 に対して発行された修正プログラムによってサポートされています。Is supported by patches issued for ASP.NET Core 2.1, 2.2, and 3.0. ASP.NET Core 3.1 には、追加の SameSite サポートがあります。ASP.NET Core 3.1 has additional SameSite support.
  • 2 月 2020日に既定でChromeによって有効になるようにスケジュールされています。Is scheduled to be enabled by Chrome by default in Feb 2020. ブラウザーは2019でこの標準への移行を開始しました。Browsers started moving to this standard in 2019.

2016 SameSite draft standard から2019ドラフト標準への変更によって影響を受ける ApiAPIs impacted by the change from the 2016 SameSite draft standard to the 2019 draft standard

古いブラウザーのサポートSupporting older browsers

2016 SameSite 標準では、不明な値を SameSite=Strict 値として処理する必要があることが義務付けられています。The 2016 SameSite standard mandated that unknown values must be treated as SameSite=Strict values. 2016 SameSite 標準をサポートする古いブラウザーからアクセスされるアプリは、値が Noneの SameSite プロパティを取得すると壊れます。Apps accessed from older browsers which support the 2016 SameSite standard may break when they get a SameSite property with a value of None. Web apps が古いブラウザーをサポートする予定の場合は、ブラウザーの検出を実装する必要があります。Web apps must implement browser detection if they intend to support older browsers. ユーザーエージェントの値が変動し、頻繁に変更されるため、ASP.NET Core はブラウザーの検出を実装しません。ASP.NET Core doesn't implement browser detection because User-Agents values are highly volatile and change frequently. Microsoft.AspNetCore.CookiePolicy の拡張ポイントを使用すると、ユーザーエージェント固有のロジックに接続できます。An extension point in Microsoft.AspNetCore.CookiePolicy allows plugging in User-Agent specific logic.

Startup.Configureで、UseAuthentication または cookie を書き込む任意のメソッドを呼び出す前に UseCookiePolicy を呼び出すコードを追加します。In Startup.Configure, add code that calls UseCookiePolicy before calling UseAuthentication or any method that writes cookies:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler("/Error");
        app.UseHsts();
    }

    app.UseHttpsRedirection();
    app.UseStaticFiles();

    app.UseRouting();

    app.UseCookiePolicy();
    app.UseAuthentication();
    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapRazorPages();
    });
}

Startup.ConfigureServicesで、次のようなコードを追加します。In Startup.ConfigureServices, add code similar to the following:

public void ConfigureServices(IServiceCollection services)
{
    services.Configure<CookiePolicyOptions>(options =>
    {
        options.MinimumSameSitePolicy = SameSiteMode.Unspecified;
        options.OnAppendCookie = cookieContext =>
            CheckSameSite(cookieContext.Context, cookieContext.CookieOptions);
        options.OnDeleteCookie = cookieContext =>
            CheckSameSite(cookieContext.Context, cookieContext.CookieOptions);
    });

    services.AddRazorPages();
}

private void CheckSameSite(HttpContext httpContext, CookieOptions options)
{
    if (options.SameSite == SameSiteMode.None)
    {
        var userAgent = httpContext.Request.Headers["User-Agent"].ToString();
        if (MyUserAgentDetectionLib.DisallowsSameSiteNone(userAgent))
        {
            options.SameSite = SameSiteMode.Unspecified;
        }
    }
}
public void ConfigureServices(IServiceCollection services)
{
    services.Configure<CookiePolicyOptions>(options =>
    {
        options.MinimumSameSitePolicy = (SameSiteMode)(-1);
        options.OnAppendCookie = cookieContext =>
            CheckSameSite(cookieContext.Context, cookieContext.CookieOptions);
        options.OnDeleteCookie = cookieContext =>
            CheckSameSite(cookieContext.Context, cookieContext.CookieOptions);
    });

    services.AddRazorPages();
}

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

    }
}

前のサンプルの MyUserAgentDetectionLib.DisallowsSameSiteNone は、ユーザーエージェントが SameSite Noneをサポートしていないかどうかを検出するユーザー指定のライブラリです。In the preceding sample, MyUserAgentDetectionLib.DisallowsSameSiteNone is a user supplied library that detects if the user agent doesn't support SameSite None:

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

次のコードは、DisallowsSameSiteNone メソッドの例を示しています。The following code shows a sample DisallowsSameSiteNone method:

警告

次のコードは、デモンストレーションのみを対象としています。The following code is for demonstration only:

  • 完全であるとは限りません。It should not be considered complete.
  • 管理されていないか、サポートされていません。It is not maintained or supported.
public 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.
    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.
    if (userAgent.Contains("Macintosh; Intel Mac OS X 10_14") &&
        userAgent.Contains("Version/") && userAgent.Contains("Safari"))
    {
        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.
    if (userAgent.Contains("Chrome/5") || userAgent.Contains("Chrome/6"))
    {
        return true;
    }

    return false;
}

SameSite 問題のアプリをテストするTest apps for SameSite problems

サードパーティのログインによってなどのリモートサイトと対話するアプリでは、次の操作を行う必要があります。Apps that interact with remote sites such as through third-party login need to:

新しい SameSite 動作にオプトインできるクライアントバージョンを使用して、web アプリをテストします。Test web apps using a client version that can opt-in to the new SameSite behavior. Chrome、Firefox、Chromium Edge には、テストに使用できる新しいオプトイン機能フラグがあります。Chrome, Firefox, and Chromium Edge all have new opt-in feature flags that can be used for testing. アプリが SameSite パッチを適用したら、古いクライアントバージョン (特に Safari) を使用してテストします。After your app applies the SameSite patches, test it with older client versions, especially Safari. 詳細については、このドキュメントの「古いブラウザーのサポート」を参照してください。For more information, see Supporting older browsers in this document.

Chrome を使用したテストTest with Chrome

Chrome 78 + には一時的な軽減策があるため、誤解を招く結果になります。Chrome 78+ gives misleading results because it has a temporary mitigation in place. Chrome 78 + 一時的な軽減策では、2分前よりも少ない cookie を使用できます。The Chrome 78+ temporary mitigation allows cookies less than two minutes old. 適切なテストフラグが有効になっている Chrome 76 または77では、より正確な結果が得られます。Chrome 76 or 77 with the appropriate test flags enabled provides more accurate results. 新しい SameSite の動作をテストするには、chrome://flags/#same-site-by-default-cookies有効に切り替えます。To test the new SameSite behavior toggle chrome://flags/#same-site-by-default-cookies to Enabled. 新しい None 設定で失敗するように、Chrome の旧バージョン (75 以降) が報告されます。Older versions of Chrome (75 and below) are reported to fail with the new None setting. このドキュメントの「古いブラウザーのサポート」を参照してください。See Supporting older browsers in this document.

Google では、以前のバージョンの chrome は使用できません。Google does not make older chrome versions available. Chromium のダウンロード」の手順に従って、Chrome の旧バージョンをテストします。Follow the instructions at Download Chromium to test older versions of Chrome. 以前のバージョンの chrome を検索することによって提供されるリンクから ChromeをダウンロードしないでくださいDo not download Chrome from links provided by searching for older versions of chrome.

Safari を使用したテストTest with Safari

Safari 12 では以前のドラフトが厳密に実装されており、新しい None 値が cookie に含まれていると失敗します。Safari 12 strictly implemented the prior draft and fails when the new None value is in a cookie. このドキュメントでは、古いブラウザーをサポートするブラウザーの検出コードを使用して None を回避します。None is avoided via the browser detection code Supporting older browsers in this document. MSAL、ADAL、使用している任意のライブラリを使用して、Safari 12、Safari 13、WebKit ベースの OS スタイルのログインをテストします。Test Safari 12, Safari 13, and WebKit based OS style logins using MSAL, ADAL or whatever library you are using. この問題は、基盤の OS バージョンによって変わります。The problem is dependent on the underlying OS version. OSX Mojave (10.14) と iOS 12 には、新しい SameSite の動作に互換性の問題があることがわかっています。OSX Mojave (10.14) and iOS 12 are known to have compatibility problems with the new SameSite behavior. OS を OSX Catalina.properties (10.15) または iOS 13 にアップグレードすると、問題が解決されます。Upgrading the OS to OSX Catalina (10.15) or iOS 13 fixes the problem. Safari には、現在、新しい仕様動作をテストするオプトインフラグがありません。Safari does not currently have an opt-in flag for testing the new spec behavior.

Firefox でのテストTest with Firefox

新しい標準の Firefox サポートは、バージョン68以降で、[about:config] ページで機能フラグ network.cookie.sameSite.laxByDefaultをオンにしてテストできます。Firefox support for the new standard can be tested on version 68+ by opting in on the about:config page with the feature flag network.cookie.sameSite.laxByDefault. 以前のバージョンの Firefox との互換性に関する問題は報告されていません。There haven't been reports of compatibility issues with older versions of Firefox.

Edge ブラウザーを使用したテストTest with Edge browser

Edge では、古い SameSite 標準がサポートされています。Edge supports the old SameSite standard. Edge バージョン44には、新しい標準との互換性に関する既知の問題はありません。Edge version 44 doesn't have any known compatibility problems with the new standard.

Edge でテストする (Chromium)Test with Edge (Chromium)

SameSite フラグは edge://flags/#same-site-by-default-cookies ページで設定されます。SameSite flags are set on the edge://flags/#same-site-by-default-cookies page. Edge Chromium で互換性の問題は検出されませんでした。No compatibility issues were discovered with Edge Chromium.

電子を使用したテストTest with Electron

Electron の複数のバージョンには、Chromium の古いバージョンが含まれています。Versions of Electron include older versions of Chromium. たとえば、チームによって使用されている電子 66 Chromium のバージョンは、以前の動作を示しています。For example, the version of Electron used by Teams is Chromium 66, which exhibits the older behavior. 製品で使用されている電子版を使用して、独自の互換性テストを実行する必要があります。You must perform your own compatibility testing with the version of Electron your product uses. 次のセクションの「古いブラウザーのサポート」を参照してください。See Supporting older browsers in the following section.

その他の技術情報Additional resources