Amostra Razor Páginas SameSite cookie do ASP.NET Core 3.1

O ASP.NET Core 3.0 tem suporte interno para o atributo SameSite, incluindo um valor de atributo SameSiteMode de Unspecified para suprimir a gravação do atributo.

O Identity do ASP.NET Core não é substancialmente afetado pelos cookies SameSite, exceto por cenários avançados, como integração de IFrames ou OpenIdConnect.

Ao usar Identity, não adicione nenhum cookie provedor ou chame services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme). O Identity cuida disso.

Gravando o atributo SameSite

Veja a seguir um exemplo de como escrever um atributo SameSite em um cookie;

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.Unspecified.
    SameSite = SameSiteMode.None
};

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

A autenticação Cookie, o estado de sessão e vários outros componentes definem suas opções do sameSite por meio de opções Cookie, por exemplo

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;
});

No código mostrado acima, a autenticação cookie e o estado de sessão definem seu atributo SameSite como None, emitindo o atributo com um valor None e também define o atributo Secure como true.

Execute o exemplo

Se você executar o projeto de exemplo, carregue o depurador do navegador na página inicial e use-o para exibir o conjunto cookie do site. Para fazer isso no Edge e no Chrome, pressione F12, selecione a guia Application e clique na URL do site na opção Cookies na seção Storage.

Lista de Cookie Depuradores do Navegador

Você pode ver na imagem acima que o cookie criado pelo exemplo quando você clica no botão "Criar SameSite Cookie" tem um valor de atributo SameSite igual ao valor de Lax definido no código de exemplo.

Interceptação de cookies

Para interceptar o cookies para ajustar o valor none de acordo com seu suporte no agente do navegador do usuário, você deve usar o middleware CookiePolicy. Isso deve ser colocado no pipeline da solicitação http antes de todos os componentes que gravam cookies e são configurados no ConfigureServices().

Para inseri-lo no pipeline, use app.UseCookiePolicy() no método Configure(IApplicationBuilder, IHostingEnvironment) em startup.cs. Por exemplo

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?}");
    });
}

Em seguida, no ConfigureServices(IServiceCollection services), configure a política cookie para chamar uma classe auxiliar quando os cookies são acrescentados ou excluídos, dessa forma:

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.Unspecified;
        }
    }
}

A função CheckSameSite(HttpContext, CookieOptions) auxiliar:

  • É chamada quando os cookies são acrescentados à solicitação ou excluídos da solicitação.
  • Verifica se a propriedade SameSite está definida como None.
  • Se SameSite for definido como None e o agente de usuário atual for conhecido por não dar suporte ao valor de atributo none. A marcar é feita usando a classe SameSiteSupport:
    • Define SameSite para não emitir o valor definindo a propriedade como (SameSiteMode)(-1)

Mais informações

Documentaçãode Atualizações do Chrome para SameSite do ASP.NET