El estándar de Google afecta a las cookies y a ASPNET

A principio de Octubre de 2019, en el sitio Chrome Platform Status, subieron un articulo explicando una nueva feature de un nuevo estándar que afectara a las cookies. En este articulo veremos cómo afecta el nuevo estándar de Google a las cookies y a ASPNET Core.

El nuevo comportamiento de las cookies

El flag SameSite de las cookies es un estándar del 2016 con el fin de prevenir ataques CSRF. Este flag tiene 3 posibles valores: el primero es None, este es el valor por defecto donde la cookie puede ser utilizado por cualquier sitio; en segundo lugar esta Lax, que evita que sitios de dominios externos puedan acceder a la cookie, excepto cuando el método de la petición HTTP sea GET; y por último, Strict, que evita completamente que un servidor de un dominio externo pueda acceder a la cookie.

Cookies en la DevTools de Google Chrome
Cookies en la DevTools de Google Chrome

El 7 de Mayo de este año, Google creo un nuevo estándar para las versiones futuras de los navegadores web. Lo que este nuevo estándar dice es que cuando no se especifique el valor de SameSite, el valor por defecto será Lax. Además, no estará permitido el uso de cookies cuyo valor de SameSite sea None y no este marcada como Secure, un flag que permite que solo sitios HTTPS puedan acceder a la cookie. Entonces para seguir utilizando cookies SameSite en None habrá que marcarlas si o si como Secure.

Estas nuevas características ya están disponibles para habilitar en las versiones beta de Chrome, y el 4 de Febrero de 2020 estará disponible en la versión estable 80 de Chromium. Pero estas nuevas modificaciones no serán compatibles con las versiones antiguas de los navegadores.

Funcionalidades como OpenIdConnect, WS-Federation, u otras que utilicen cookies con SameSite None no funcionarán correctamente en los navegadores con el nuevo estándar.

Cambios de ASPNET Core

El mayor cambio es sobre el enumerado SameSiteMode, donde se agregara un campo Unspecified con el valor -1. Esta modificación estará disponible a partir de Net Core 3.1.

Las clases CookieOptions, CookiePolicyOptions y CookieBuilder tienen una propiedad del tipo del enumerado mencionado, donde por defecto el valor era None. Ahora tendrán una nueva propiedad interna booleana llamada SuppressSameSiteNone. Esta propiedad se usara para indicar el comportamiento de la cookie. Si el comportamiento es del viejo estándar, el valor por defecto seguiría siendo None, pero si es del nuevo, entonces será Unspecified.

Para cambiar el valor de SuppressSameSiteNone hay que agregar un archivo en la raíz del proyecto llamado runtimeconfig.template.json con el siguiente contenido:


{ 
  "configProperties": { 
    "Microsoft.AspNetCore.SuppressSameSiteNone": "true" 
  } 
} 

Donde si el valor de la propiedad es True entonces se usara el viejo estándar.

Compatibilidad de cookies con versiones antiguas

Para poder utilizar cookies en versiones anteriores habrá que identificar la versión del navegador. Para esto podemos usar el encabezado User-Agent. La clase CookiePolicyOptions posee 2 delegados que se ejecutan cuando se crea una cookie o cuando se elimina. En esas funciones tenemos que validar que versión de navegador se esta utilizando. En caso de que la versión del navegador no soporte el nuevo comportamiento entonces se le asignara a la cookie SameSite como Unspecified. De esta manera el navegador le asignara el valor por defecto que tenga la versión. Todo lo mencionado anteriormente se puede realizar con el siguiente código que debería estar en el archivo Startup.cs.


private void CheckSameSite(HttpContext httpContext, CookieOptions options) 
{ 
    if (options.SameSite == SameSiteMode.None) 
    { 
        var userAgent = httpContext.Request.Headers["User-Agent"].ToString(); 
        // TODO: Use your User Agent library of choice here. 
        if (/* UserAgent doesn’t support new behavior */) 
        { 
               options.SameSite = SameSiteMode.Unspecified; 
        } 
    } 
}

public void ConfigureServices(IServiceCollection services) 
{ 
    services.Configure(options => 
    { 
        options.MinimumSameSitePolicy = SameSiteMode.Unspecified; 
        options.OnAppendCookie = cookieContext =>  
            CheckSameSite(cookieContext.Context, cookieContext.CookieOptions); 
        options.OnDeleteCookie = cookieContext =>  
            CheckSameSite(cookieContext.Context, cookieContext.CookieOptions); 
    }); 
} 
 
public void Configure(IApplicationBuilder app) 
{ 
    app.UseCookiePolicy(); // Before UseAuthentication or anything else that writes cookies. 
    app.UseAuthentication(); 
    // … 
}

Cuando se publique Net Core 3.1 en Noviembre podremos preparar nuestros sitios web para que se adapten al nuevo estándar y tener todo listo antes del lanzamiento de la versión 80 de Chrome.

Referencias

https://github.com/aspnet/AspNetCore/issues/14996

https://tools.ietf.org/html/draft-west-cookie-incrementalism-00

https://www.chromium.org/updates/same-site