Compartir vía


Ejemplo de Razor Pages SameSite cookie de ASP.NET Core 3.1

ASP.NET Core 3.0 tiene compatibilidad integrada con el atributo SameSite, incluido un SameSiteMode valor de atributo de Unspecified para suprimir la escritura del atributo.

ASP.NET Core Identity no se ve afectado en gran medida por las cookies de SameSite excepto en escenarios avanzados como la integración de IFrames o OpenIdConnect.

Al usar Identity, no agregue ningún proveedor de cookie o llame a services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme), Identity se encarga de ello.

Escritura del atributo SameSite

A continuación se muestra un ejemplo de cómo escribir un atributo SameSite en una 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);

Cookie autenticación, estado de sesión y otros componentes establecen sus mismas opciones de sameSite a través de opciones de Cookie, por ejemplo

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

En el código mostrado anteriormente, tanto la autenticación de cookie como el estado de sesión establecen su mismo atributo de sameSite en None, emitiendo el atributo con un valor None y también establecen el atributo Secure en true.

Ejecución del ejemplo

Si ejecuta el proyecto de ejemplo, cargue el depurador del explorador en la página inicial y úselo para ver la colección de cookie del sitio. Para ello, en Edge y Chrome, presione F12, seleccione la pestaña Application y haga clic en la dirección URL del sitio en la opción Cookies de la sección Storage.

Depurador de explorador Cookie Lista

Puede ver en la imagen anterior que la cookie creada por el ejemplo al hacer clic en el botón "Crear Cookie de SameSite" tiene un valor de atributo SameSite de Lax, que coincide con el valor establecido en el código de ejemplo.

Interceptación de cookies

Para interceptar cookies, para ajustar el valor none según su compatibilidad con el agente del explorador del usuario, debes usar el middleware CookiePolicy. Debe colocarse en la canalización de solicitudes http antes de los componentes que escriben cookies y se configuran dentro de ConfigureServices().

Para insertarlas en la canalización, use app.UseCookiePolicy() en el método Configure(IApplicationBuilder, IHostingEnvironment) de Startup.cs. Por ejemplo,

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

A continuación, en ConfigureServices(IServiceCollection services) configura la directiva de cookie para llamar a una clase auxiliar cuando se anexan o eliminan cookies, de este modo;

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

La función auxiliar CheckSameSite(HttpContext, CookieOptions):

  • Se llama cuando se anexan cookies a la solicitud o se eliminan de la solicitud.
  • Comprueba si la propiedad SameSite está establecida en None.
  • Si SameSite se establece en None y se sabe que el agente de usuario actual no admite el valor de atributo none. La comprobación se realiza mediante la clase SameSiteSupport:
    • Establece SameSite para no emitir el valor estableciendo la propiedad en (SameSiteMode)(-1)

Más información

Chrome actualizala documentación de SameSite de ASP.NET Core