ASP.NET Core 2.1 Razor Pages の SameSite cookie のサンプル

このサンプルは、ターゲットされている .NET Framework をターゲットにしています

ASP.NET Core 2.1 には SameSite 属性のサポートが組み込まれていますが、元の標準に書き込まれていました。 パッチ適用後の動作では SameSite.None の意味が変更され、値を出力しない代わりに、None の値を持つ SameSite 属性が出力されるようになりました。 値を出力しない場合は、cookie の SameSite プロパティを -1 に設定できます。

ASP.NET Core Identity は、IFrames または OpenIdConnect 統合のような高度なシナリオを除き、SameSite cookies の影響をほとんど受けません。

Identity を使用する場合は、cookie プロバイダーの追加や services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme) の呼び出しを "行わないでください"。これらは、Identity によって行われます。

SameSite 属性の書き込み

次のコードは、cookie に SameSite 属性を書き込む方法の例です。

var cookieOptions = new CookieOptions
{
    // Set the secure flag, which Chrome's changes will require for SameSite none.
    // Note this will also require you to be running on HTTPS
    Secure = true,

    // Set the cookie to HTTP only which is good practice unless you really do need
    // to access it client side in scripts.
    HttpOnly = true,

    // Add the SameSite attribute, this will emit the attribute with a value of none.
    // To not emit the attribute at all set the SameSite property to (SameSiteMode)(-1).
    SameSite = SameSiteMode.None
};

// Add the cookie to the response cookie collection
Response.Cookies.Append(CookieName, "cookieValue", cookieOptions);

Cookie 認証、セッション状態、およびその他のさまざまなコンポーネントでは、Cookie オプションを介して sameSite オプションを設定します。次に例を示します。

services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
    .AddCookie(options =>
    {
        options.Cookie.SameSite = SameSiteMode.None;
        options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
        options.Cookie.IsEssential = true;
    });

services.AddSession(options =>
{
    options.Cookie.SameSite = SameSiteMode.None;
    options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
    options.Cookie.IsEssential = true;
});

上記のコードでは、cookie 認証とセッション状態の両方で sameSite 属性を None に設定し、None 値を持つ属性を出力し、また Secure 属性を true に設定しています。

サンプルを実行する

サンプル プロジェクトを実行する場合は、最初のページでブラウザー デバッガーを読み込み、それを使ってサイトの cookie のコレクションを表示してください。 Edge と Chrome でこれを行うには、F12 キーを押してから Application タブを選び、Storage セクションの Cookies オプションの下にあるサイト URL をクリックします。

Browser Debugger Cookie List

上の画像から、"Create SameSite Cookie" ボタンをクリックしたときにサンプルによって作成された cookie の SameSite 属性値が Lax であり、サンプル コードで設定されている値と一致していることがわかります。

cookie のインターセプト

cookie をインターセプトするには、ユーザーのブラウザー エージェントでのサポート合わせて None 値を調整するために、CookiePolicy ミドルウェアを使う必要があります。 これは、cookie を書き込むすべてのコンポーネントの前に http 要求パイプラインに配置し、ConfigureServices() 内で構成する必要があります。

これをパイプラインに挿入するには、Startup.csConfigure(IApplicationBuilder, IHostingEnvironment) メソッドで app.UseCookiePolicy() を使います。 次に例を示します。

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

    app.UseHttpsRedirection();
    app.UseStaticFiles();
    app.UseCookiePolicy();
    app.UseAuthentication();
    app.UseSession();

    app.UseMvc(routes =>
    {
        routes.MapRoute(
            name: "default",
            template: "{controller=Home}/{action=Index}/{id?}");
    });
}

次に、ConfigureServices(IServiceCollection services) で、cookie が追加または削除された場合にヘルパー クラスを呼び出すように cookie ポリシーを構成します。例:

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

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

ヘルパー関数 CheckSameSite(HttpContext, CookieOptions) は:

  • cookie が要求に追加された場合、または要求から削除された場合に呼び出されます。
  • SameSite プロパティが None に設定されているかどうかをチェックします。
  • SameSiteNone に設定されていて、現在のユーザー エージェントで None 属性値がサポートされていないことがわかっている場合。 このチェックは、SameSiteSupport クラスを使って実行されます。
    • プロパティを (SameSiteMode)(-1) に設定して、値を出力しないように SameSite を設定します

.NET Framework をターゲットにする

ASP.NET Core と System.Web (ASP.NET 4.x) には、SameSite の独立した実装があります。 ASP.NET Core を使用する場合、.NET Framework 用の SameSite KB パッチは必要ありません。また、System.Web SameSite の最小フレームワーク バージョン要件 (.NET Framework 4.7.2) も ASP.NET Core に適用されません。

.NET 上の ASP.NET Core では、NuGet パッケージの依存関係を更新して適切な修正プログラムを取得する必要があります。

.NET Framework 用の ASP.NET Core の変更を取得するには、パッチが適用されたパッケージとバージョン (2.1.14 以降の 2.1 バージョン) への直接参照が必要です。

<PackageReference Include="Microsoft.Net.Http.Headers" Version="2.1.14" />
<PackageReference Include="Microsoft.AspNetCore.CookiePolicy" Version="2.1.14" />

詳細情報

Chrome の更新ASP.NET Core SameSite のドキュメントASP.NET Core 2.1 SameSite の変更に関するお知らせ