Trabajo con cookies de SameSite en ASP.NET Core
Por Rick Anderson
SameSite es un estándar de borrador de IETF diseñado para proporcionar cierta protección contra ataques de falsificación de solicitud entre sitios (CSRF). Redactado originalmente en 2016, el borrador del estándar se actualizó en 2019. El estándar actualizado no es compatible con el estándar anterior, siendo las diferencias más notables:
- Las cookies sin encabezado de SameSite se tratan como
SameSite=Lax
de manera predeterminada. SameSite=None
se debe usar para permitir el uso entre sitios cookie .- Las cookies que declaran
SameSite=None
también deben marcarse comoSecure
. - Las aplicaciones que usan
<iframe>
pueden experimentar problemas con las cookies desameSite=Lax
osameSite=Strict
porque<iframe>
se trata como escenario entre sitios. - El valor
SameSite=None
no está permitido por el estándar de 2016 y hace que algunas implementaciones traten esas cookies comoSameSite=Strict
. Consulte Compatibilidad con exploradores más antiguos en este documento.
La configuración de SameSite=Lax
funciona para la mayoría de las cookies de aplicaciones. Algunas formas de autenticación como OpenID Connect (OIDC) y WS-Federation usan de manera predeterminada redireccionamientos basados en POST. Las redirecciones basadas en POST desencadenan las protecciones del explorador de SameSite, por lo que SameSite está deshabilitado para estos componentes. La mayoría de los inicios de sesión de OAuth no se ven afectados debido a las diferencias en la forma en que fluye la solicitud.
Cada componente de ASP.NET Core que emite cookies debe decidir si SameSite es adecuado.
SameSite y Identity
ASP.NET Core Identity no se ve afectado en gran medida por las cookies 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.
Código de ejemplo de prueba de SameSite
El ejemplo siguiente se puede descargar y probar:
Muestra | Documento |
---|---|
Razor Pages de .NET Core | Ejemplo de SameSite de Razor Pages de ASP.NET Core 3.1 cookie |
Compatibilidad de .NET Core con el atributo sameSite
.NET Core admite el estándar de borrador de 2019 para SameSite. Los desarrolladores pueden controlar mediante programación el valor del mismo atributoSite mediante la propiedad HttpCookie.SameSite
. Si establece la propiedad SameSite
en Strict
, Lax
o None
, esos valores se escribirán en la red con el cookie. Establecerlo en SameSiteMode.Unspecified
indica que no debe enviarse ningñun sameSite con el 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.
SameSite = SameSiteMode.None
// The client should follow its default cookie policy.
// SameSite = SameSiteMode.Unspecified
};
// Add the cookie to the response cookie collection
Response.Cookies.Append("MyCookie", "cookieValue", cookieOptions);
}
Uso de API con SameSite
HttpContext.Response.Cookies.Append tiene Unspecified
como valor predeterminado, lo que significa que no se ha agregado ningún atributo SameSite al cookie y el cliente usará su comportamiento predeterminado (Lax para los nuevos exploradores, None para los antiguos). En el código siguiente se muestra cómo cambiar el valor de SameSite cookie a SameSiteMode.Lax
:
HttpContext.Response.Cookies.Append(
"name", "value",
new CookieOptions() { SameSite = SameSiteMode.Lax });
Todos los componentes de ASP.NET Core que emiten cookies sustituyen los valores predeterminados anteriores con la configuración adecuada para sus escenarios. Los valores predeterminados anteriores invalidados no han cambiado.
Componente | cookie | Valor predeterminado |
---|---|---|
CookieBuilder | SameSite | Unspecified |
Session | SessionOptions.Cookie | Lax |
CookieTempDataProvider | CookieTempDataProviderOptions.Cookie | Lax |
IAntiforgery | AntiforgeryOptions.Cookie | Strict |
Autenticación de Cookie | CookieAuthenticationOptions.Cookie | Lax |
AddTwitter | TwitterOptions.StateCookie | Lax |
RemoteAuthenticationHandler<TOptions> | RemoteAuthenticationOptions.CorrelationCookie | None |
AddOpenIdConnect | OpenIdConnectOptions.NonceCookie | None |
HttpContext.Response.Cookies.Append | CookieOptions | Unspecified |
ASP.NET Core 3.1 y versiones posteriores proporciona la siguiente compatibilidad con SameSite:
- Vuelve a definir el comportamiento de
SameSiteMode.None
para emitirSameSite=None
- Agrega un nuevo valor
SameSiteMode.Unspecified
para omitir el atributo SameSite. - Todas las API de cookies tienen como valor predeterminado
Unspecified
. Algunos componentes que usan cookies establecen valores más específicos para sus escenarios. Consulte la tabla anterior para obtener ejemplos.
En ASP.NET Core 3.0 y versiones posteriores se cambiaron los valores predeterminados de SameSite para evitar conflictos con valores predeterminados de cliente incoherentes. Las siguientes API han cambiado el valor predeterminado de SameSiteMode.Lax
a -1
para evitar la emisión de un atributo SameSite para estas cookies:
- CookieOptions usado con HttpContext.Response.Cookies.Append
- CookieBuilder usado como fábrica de
CookieOptions
- CookiePolicyOptions.MinimumSameSitePolicy
Historial y cambios
La compatibilidad con SameSite se implementó por primera vez en ASP.NET Core en la versión 2.0 con el estándar de borrador de 2016. El estándar de 2016 era opcional. ASP.NET Core optó por participar estableciendo varias cookies en Lax
de manera predeterminada. Después de encontrar varios problemas con la autenticación, se deshabilitó la mayoría del uso de SameSite.
Las revisiones se emitieron en noviembre de 2019 para actualizar del estándar de 2016 al estándar de 2019. El borrador de 2019 de la especificación SameSite:
- No es compatible con el borrador de 2016. Para más información, vea Compatibilidad con exploradores más antiguos en este documento.
- especifica que las cookies se tratan como
SameSite=Lax
de manera predeterminada; - especifica que las cookies que afirman explícitamente
SameSite=None
para habilitar la entrega entre sitios deben estar marcadas comoSecure
.None
es una nueva entrada para no participar. - Es compatible con las revisiones emitidas para ASP.NET Core 2.1, 2.2 y 3.0. ASP.NET Core 3.1 y versiones posteriores tiene compatibilidad adicional con SameSite.
- Está previsto que Chrome lo habilite de manera predeterminada en febrero de 2020. Los exploradores empezaron a pasar a este estándar en 2019.
API afectadas por el cambio del estándar de borrador de SameSite de 2016 al estándar de borrador de 2019
- Http.SameSiteMode
- CookieOptions.SameSite
- CookieBuilder.SameSite
- CookiePolicyOptions.MinimumSameSitePolicy
- Microsoft.Net.Http.Headers.SameSiteMode
- Microsoft.Net.Http.Headers.SetCookieHeaderValue.SameSite
Compatibilidad con exploradores más antiguos
El estándar de SameSite de 2016 obligaba a tratar los valores desconocidos como valores de SameSite=Strict
. Las aplicaciones a las que se accede desde exploradores antiguos que admiten el estándar de SameSite de 2016 pueden interrumpirse cuando obtienen una propiedad de SameSite con un valor de None
. Las aplicaciones web deben implementar la detección de navegadores si pretenden ser compatibles con navegadores antiguos. ASP.NET Core no implementa la detección del explorador porque los valores de User-Agents son muy volátiles y cambian con frecuencia. Un punto de extensión en Microsoft.AspNetCore.CookiePolicy permite conectar la lógica específica de User-Agent.
En Program.cs
, agrega código que llame a UseCookiePolicy antes de llamar a UseAuthentication o a cualquier método que escriba cookies:
var builder = WebApplication.CreateBuilder(args);
builder.Services.Configure<CookiePolicyOptions>(options =>
{
options.MinimumSameSitePolicy = SameSiteMode.Unspecified;
options.OnAppendCookie = cookieContext =>
CheckSameSite(cookieContext.Context, cookieContext.CookieOptions);
options.OnDeleteCookie = cookieContext =>
CheckSameSite(cookieContext.Context, cookieContext.CookieOptions);
});
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;
}
}
}
builder.Services.AddRazorPages();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseCookiePolicy();
app.UseAuthorization();
app.MapRazorPages();
app.Run();
En Program.cs
, agregue código similar al código resaltado siguiente:
var builder = WebApplication.CreateBuilder(args);
builder.Services.Configure<CookiePolicyOptions>(options =>
{
options.MinimumSameSitePolicy = SameSiteMode.Unspecified;
options.OnAppendCookie = cookieContext =>
CheckSameSite(cookieContext.Context, cookieContext.CookieOptions);
options.OnDeleteCookie = cookieContext =>
CheckSameSite(cookieContext.Context, cookieContext.CookieOptions);
});
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;
}
}
}
builder.Services.AddRazorPages();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseCookiePolicy();
app.UseAuthorization();
app.MapRazorPages();
app.Run();
En el ejemplo anterior, MyUserAgentDetectionLib.DisallowsSameSiteNone
es una biblioteca proporcionada por el usuario que detecta si el agente de usuario no admite None
de SameSite:
if (MyUserAgentDetectionLib.DisallowsSameSiteNone(userAgent))
{
options.SameSite = SameSiteMode.Unspecified;
}
El siguiente código muestra un método DisallowsSameSiteNone
de ejemplo:
Advertencia
El código siguiente es solo para demostración:
- No debería considerarse completo.
- No se mantiene ni tiene soporte.
public static bool DisallowsSameSiteNone(string userAgent)
{
// Check if a null or empty string has been passed in, since this
// will cause further interrogation of the useragent to fail.
if (String.IsNullOrWhiteSpace(userAgent))
return false;
// 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;
}
Probar aplicaciones para problemas de SameSite
Las aplicaciones que interactúan con sitios remotos, por ejemplo mediante inicio de sesión de terceros, necesitan:
- Probar la interacción en varios navegadores.
- Aplica la Detección y mitigación del navegador CookiePolicy tratada en este documento.
Probar las aplicaciones web usando una versión cliente que pueda incorporarse al nuevo comportamiento de SameSite. Chrome, Firefox y Chromium Edge tienen nuevas marcas de características de participación que se pueden usar para las pruebas. Una vez que la aplicación aplique las revisiones de SameSite, pruébela con versiones de cliente anteriores, especialmente Safari. Para más información, vea Compatibilidad con exploradores más antiguos en este documento.
Prueba con Chrome
Chrome 78+ proporciona resultados engañosos porque tiene una mitigación temporal en su lugar. La mitigación temporal de Chrome 78+ admite cookies de menos de dos minutos de antigüedad. Chrome 76 o 77 con las marcas de prueba adecuadas habilitadas proporciona resultados más precisos. Para probar el nuevo comportamiento, cambie chrome://flags/#same-site-by-default-cookies
a Habilitado. Se ha informado de que las versiones más antiguas de Chrome (75 e inferiores) fallan con la nueva configuración de None
. Consulte Compatibilidad con exploradores más antiguos en este documento.
Google no hace que las versiones de Chrome anteriores estén disponibles. Siga las instrucciones que aparecen en Descargar Chromium para probar versiones anteriores de Chrome. No descargue Chrome desde los vínculos proporcionados mediante la búsqueda de versiones anteriores de Chrome.
A partir de la versión de Canary 80.0.3975.0
, la mitigación temporal Lax+POST se puede deshabilitar con fines de prueba con la nueva marca --enable-features=SameSiteDefaultChecksMethodRigorously
para permitir la prueba de sitios y servicios en el estado final de la característica en la que se ha quitado la mitigación. Para más información, consulte las Actualizaciones de SameSite de The Chromium Projects
Prueba con Safari
Safari 12 aplica estrictamente el proyecto anterior y falla cuando el nuevo valor None
está en un cookie. None
se evita a través del código de detección del explorador Compatibilidad con exploradores más antiguos en este documento. Pruebe los inicios de sesión de estilo del sistema operativo basados en Safari 12, Safari 13 y WebKit mediante MSAL, ADAL o cualquier biblioteca que esté usando. El problema depende de la versión del sistema operativo subyacente. Se sabe que OSX Mojave (10.14) e iOS 12 tienen problemas de compatibilidad con el nuevo comportamiento de SameSite. Actualizar el sistema operativo a OSX Catalina (10.15) o iOS 13 soluciona el problema. Safari no tiene actualmente una marca de participación para probar el comportamiento de la nueva especificación.
Prueba con Firefox
La compatibilidad de Firefox con el nuevo estándar puede probarse en la versión 68+ accediendo a la página about:config
con la marca de características network.cookie.sameSite.laxByDefault
. No ha habido informes de problemas de compatibilidad con versiones anteriores de Firefox.
Prueba con el explorador Edge
Edge admite el antiguo estándar de SameSite. La versión 44 de Edge no tiene problemas de compatibilidad conocidos con el nuevo estándar.
Prueba con Edge (Chromium)
Las marcas de SameSite se establecen en la página de edge://flags/#same-site-by-default-cookies
. No se detectaron problemas de compatibilidad con Edge Chromium.
Prueba con Electron
Las versiones de Electron incluyen versiones anteriores de Chromium. Por ejemplo, la versión de Electron usada por Teams es Chromium 66, que exhibe el comportamiento anterior. Realice sus propias pruebas de compatibilidad con la versión de Electron que use el producto. Consulte Compatibilidad con exploradores más antiguos en la sección siguiente.
Recursos adicionales
- Blog de Cromo:Desarrolladores: Prepárese para el nuevo SameSite=None; Proteger configuración de Cookie
- Cookies de SameSite explicadas
- Revisiones de noviembre de 2019
Muestra | Documento |
---|---|
Razor Pages de .NET Core | Ejemplo de SameSite de Razor Pages de ASP.NET Core 3.1 cookie |
El ejemplo siguiente se puede descargar y probar:
Muestra | Documento |
---|---|
Razor Pages de .NET Core | Ejemplo de SameSite de Razor Pages de ASP.NET Core 3.1 cookie |
Compatibilidad de .NET Core con el atributo sameSite
.NET Core 3.1 y versiones posteriores admiten el estándar de borrador de 2019 para SameSite. Los desarrolladores pueden controlar mediante programación el valor del mismo atributoSite mediante la propiedad HttpCookie.SameSite
. Si establece la propiedad SameSite
en Strict (Estricto), Lax (Laxo) o None (Ninguno), esos valores se escribirán en la red con el cookie. Si se establece en igual a (SameSiteMode)(-1)
, se indica que no se debe incluir ningún atributo de sameSite en la red con 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
// SameSite = (SameSiteMode)(-1)
SameSite = SameSiteMode.None
};
// Add the cookie to the response cookie collection
Response.Cookies.Append("MyCookie", "cookieValue", cookieOptions);
.NET Core 3.1 y versiones posteriores admiten los valores actualizados de SameSite y agregan un valor de enumeración adicional, SameSiteMode.Unspecified
a la enumeración SameSiteMode
.
Este nuevo valor indica que no se debe enviar sameSite con cookie.
Uso de API con SameSite
HttpContext.Response.Cookies.Append tiene Unspecified
como valor predeterminado, lo que significa que no se ha agregado ningún atributo SameSite al cookie y el cliente usará su comportamiento predeterminado (Lax para los nuevos exploradores, None para los antiguos). En el código siguiente se muestra cómo cambiar el valor de SameSite cookie a SameSiteMode.Lax
:
HttpContext.Response.Cookies.Append(
"name", "value",
new CookieOptions() { SameSite = SameSiteMode.Lax });
Todos los componentes de ASP.NET Core que emiten cookies sustituyen los valores predeterminados anteriores con la configuración adecuada para sus escenarios. Los valores predeterminados anteriores invalidados no han cambiado.
Componente | cookie | Valor predeterminado |
---|---|---|
CookieBuilder | SameSite | Unspecified |
Session | SessionOptions.Cookie | Lax |
CookieTempDataProvider | CookieTempDataProviderOptions.Cookie | Lax |
IAntiforgery | AntiforgeryOptions.Cookie | Strict |
Autenticación de Cookie | CookieAuthenticationOptions.Cookie | Lax |
AddTwitter | TwitterOptions.StateCookie | Lax |
RemoteAuthenticationHandler<TOptions> | RemoteAuthenticationOptions.CorrelationCookie | None |
AddOpenIdConnect | OpenIdConnectOptions.NonceCookie | None |
HttpContext.Response.Cookies.Append | CookieOptions | Unspecified |
ASP.NET Core 3.1 y versiones posteriores proporciona la siguiente compatibilidad con SameSite:
- Vuelve a definir el comportamiento de
SameSiteMode.None
para emitirSameSite=None
- Agrega un nuevo valor
SameSiteMode.Unspecified
para omitir el atributo SameSite. - Todas las API de cookies tienen como valor predeterminado
Unspecified
. Algunos componentes que usan cookies establecen valores más específicos para sus escenarios. Consulte la tabla anterior para obtener ejemplos.
En ASP.NET Core 3.0 y versiones posteriores se cambiaron los valores predeterminados de SameSite para evitar conflictos con valores predeterminados de cliente incoherentes. Las siguientes API han cambiado el valor predeterminado de SameSiteMode.Lax
a -1
para evitar la emisión de un atributo SameSite para estas cookies:
- CookieOptions usado con HttpContext.Response.Cookies.Append
- CookieBuilder usado como fábrica de
CookieOptions
- CookiePolicyOptions.MinimumSameSitePolicy
Historial y cambios
La compatibilidad con SameSite se implementó por primera vez en ASP.NET Core en la versión 2.0 con el estándar de borrador de 2016. El estándar de 2016 era opcional. ASP.NET Core optó por participar estableciendo varias cookies en Lax
de manera predeterminada. Después de encontrar varios problemas con la autenticación, se deshabilitó la mayoría del uso de SameSite.
Las revisiones se emitieron en noviembre de 2019 para actualizar del estándar de 2016 al estándar de 2019. El borrador de 2019 de la especificación SameSite:
- No es compatible con el borrador de 2016. Para más información, vea Compatibilidad con exploradores más antiguos en este documento.
- especifica que las cookies se tratan como
SameSite=Lax
de manera predeterminada; - especifica que las cookies que afirman explícitamente
SameSite=None
para habilitar la entrega entre sitios deben estar marcadas comoSecure
.None
es una nueva entrada para no participar. - Es compatible con las revisiones emitidas para ASP.NET Core 2.1, 2.2 y 3.0. ASP.NET Core 3.1 tiene compatibilidad adicional con SameSite.
- Está previsto que Chrome lo habilite de manera predeterminada en febrero de 2020. Los exploradores empezaron a pasar a este estándar en 2019.
API afectadas por el cambio del estándar de borrador de SameSite de 2016 al estándar de borrador de 2019
- Http.SameSiteMode
- CookieOptions.SameSite
- CookieBuilder.SameSite
- CookiePolicyOptions.MinimumSameSitePolicy
- Microsoft.Net.Http.Headers.SameSiteMode
- Microsoft.Net.Http.Headers.SetCookieHeaderValue.SameSite
Compatibilidad con exploradores más antiguos
El estándar de SameSite de 2016 obligaba a tratar los valores desconocidos como valores de SameSite=Strict
. Las aplicaciones a las que se accede desde exploradores antiguos que admiten el estándar de SameSite de 2016 pueden interrumpirse cuando obtienen una propiedad de SameSite con un valor de None
. Las aplicaciones web deben implementar la detección de navegadores si pretenden ser compatibles con navegadores antiguos. ASP.NET Core no implementa la detección del explorador porque los valores de User-Agents son muy volátiles y cambian con frecuencia. Un punto de extensión en Microsoft.AspNetCore.CookiePolicy permite conectar la lógica específica de User-Agent.
En Startup.Configure
, agrega código que llame a UseCookiePolicy antes de llamar a UseAuthentication o cualquier método que escriba 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();
});
}
En Startup.ConfigureServices
, agregue código similar al siguiente:
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;
}
}
}
En el ejemplo anterior, MyUserAgentDetectionLib.DisallowsSameSiteNone
es una biblioteca proporcionada por el usuario que detecta si el agente de usuario no admite None
de SameSite:
if (MyUserAgentDetectionLib.DisallowsSameSiteNone(userAgent))
{
options.SameSite = SameSiteMode.Unspecified;
}
El siguiente código muestra un método DisallowsSameSiteNone
de ejemplo:
Advertencia
El código siguiente es solo para demostración:
- No debería considerarse completo.
- No se mantiene ni tiene soporte.
public static bool DisallowsSameSiteNone(string userAgent)
{
// Check if a null or empty string has been passed in, since this
// will cause further interrogation of the useragent to fail.
if (String.IsNullOrWhiteSpace(userAgent))
return false;
// 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;
}
Probar aplicaciones para problemas de SameSite
Las aplicaciones que interactúan con sitios remotos, por ejemplo mediante inicio de sesión de terceros, necesitan:
- Probar la interacción en varios navegadores.
- Aplica la Detección y mitigación del navegador CookiePolicy tratada en este documento.
Probar las aplicaciones web usando una versión cliente que pueda incorporarse al nuevo comportamiento de SameSite. Chrome, Firefox y Chromium Edge tienen nuevas marcas de características de participación que se pueden usar para las pruebas. Una vez que la aplicación aplique las revisiones de SameSite, pruébela con versiones de cliente anteriores, especialmente Safari. Para más información, vea Compatibilidad con exploradores más antiguos en este documento.
Prueba con Chrome
Chrome 78+ proporciona resultados engañosos porque tiene una mitigación temporal en su lugar. La mitigación temporal de Chrome 78+ admite cookies de menos de dos minutos de antigüedad. Chrome 76 o 77 con las marcas de prueba adecuadas habilitadas proporciona resultados más precisos. Para probar el nuevo comportamiento, cambie chrome://flags/#same-site-by-default-cookies
a Habilitado. Se ha informado de que las versiones más antiguas de Chrome (75 e inferiores) fallan con la nueva configuración de None
. Consulte Compatibilidad con exploradores más antiguos en este documento.
Google no hace que las versiones de Chrome anteriores estén disponibles. Siga las instrucciones que aparecen en Descargar Chromium para probar versiones anteriores de Chrome. No descargue Chrome desde los vínculos proporcionados mediante la búsqueda de versiones anteriores de Chrome.
A partir de la versión de Canary 80.0.3975.0
, la mitigación temporal Lax+POST se puede deshabilitar con fines de prueba con la nueva marca --enable-features=SameSiteDefaultChecksMethodRigorously
para permitir la prueba de sitios y servicios en el estado final de la característica en la que se ha quitado la mitigación. Para más información, consulte las Actualizaciones de SameSite de The Chromium Projects
Prueba con Safari
Safari 12 aplica estrictamente el proyecto anterior y falla cuando el nuevo valor None
está en un cookie. None
se evita a través del código de detección del explorador Compatibilidad con exploradores más antiguos en este documento. Pruebe los inicios de sesión de estilo del sistema operativo basados en Safari 12, Safari 13 y WebKit mediante MSAL, ADAL o cualquier biblioteca que esté usando. El problema depende de la versión del sistema operativo subyacente. Se sabe que OSX Mojave (10.14) e iOS 12 tienen problemas de compatibilidad con el nuevo comportamiento de SameSite. Actualizar el sistema operativo a OSX Catalina (10.15) o iOS 13 soluciona el problema. Safari no tiene actualmente una marca de participación para probar el comportamiento de la nueva especificación.
Prueba con Firefox
La compatibilidad de Firefox con el nuevo estándar puede probarse en la versión 68+ accediendo a la página about:config
con la marca de características network.cookie.sameSite.laxByDefault
. No ha habido informes de problemas de compatibilidad con versiones anteriores de Firefox.
Prueba con el explorador Edge
Edge admite el antiguo estándar de SameSite. La versión 44 de Edge no tiene problemas de compatibilidad conocidos con el nuevo estándar.
Prueba con Edge (Chromium)
Las marcas de SameSite se establecen en la página de edge://flags/#same-site-by-default-cookies
. No se detectaron problemas de compatibilidad con Edge Chromium.
Prueba con Electron
Las versiones de Electron incluyen versiones anteriores de Chromium. Por ejemplo, la versión de Electron usada por Teams es Chromium 66, que exhibe el comportamiento anterior. Realice sus propias pruebas de compatibilidad con la versión de Electron que use el producto. Consulte Compatibilidad con exploradores más antiguos en la sección siguiente.
Recursos adicionales
- Blog de Cromo:Desarrolladores: Prepárese para el nuevo SameSite=None; Proteger configuración de Cookie
- Cookies de SameSite explicadas
- Revisiones de noviembre de 2019
Muestra | Documento |
---|---|
Razor Pages de .NET Core | Ejemplo de SameSite de Razor Pages de ASP.NET Core 3.1 cookie |
Los ejemplos siguientes se pueden descargar y probar:
Muestra | Documento |
---|---|
.NET Core MVC | Ejemplo cookie de SameSite de MVC de ASP.NET Core 2.1 |
Razor Pages de .NET Core | Ejemplo de SameSite de Razor Pages de ASP.NET Core 2.1 cookie |
Cambios de comportamiento de revisión de diciembre
El cambio de comportamiento específico para .NET Framework y .NET Core 2.1 es cómo interpreta el valor None
la propiedad SameSite
. Antes de la revisión, un valor de None
significa "No emitir el atributo en absoluto", después de la revisión significa "Emitir el atributo con un valor de None
". Después de la revisión, un valor SameSite
de (SameSiteMode)(-1)
hace que el atributo no se emita.
El valor predeterminado de SameSite para la autenticación de formularios y las cookies de estado de sesión se cambiaron de None
a Lax
.
Uso de API con SameSite
HttpContext.Response.Cookies.Append tiene Unspecified
como valor predeterminado, lo que significa que no se ha agregado ningún atributo SameSite al cookie y el cliente usará su comportamiento predeterminado (Lax para los nuevos exploradores, None para los antiguos). En el código siguiente se muestra cómo cambiar el valor de SameSite cookie a SameSiteMode.Lax
:
HttpContext.Response.Cookies.Append(
"name", "value",
new CookieOptions() { SameSite = SameSiteMode.Lax });
Todos los componentes de ASP.NET Core que emiten cookies sustituyen los valores predeterminados anteriores con la configuración adecuada para sus escenarios. Los valores predeterminados anteriores invalidados no han cambiado.
Componente | cookie | Valor predeterminado |
---|---|---|
CookieBuilder | SameSite | Unspecified |
Session | SessionOptions.Cookie | Lax |
CookieTempDataProvider | CookieTempDataProviderOptions.Cookie | Lax |
IAntiforgery | AntiforgeryOptions.Cookie | Strict |
Autenticación de Cookie | CookieAuthenticationOptions.Cookie | Lax |
AddTwitter | TwitterOptions.StateCookie | Lax |
RemoteAuthenticationHandler<TOptions> | RemoteAuthenticationOptions.CorrelationCookie | None |
AddOpenIdConnect | OpenIdConnectOptions.NonceCookie | None |
HttpContext.Response.Cookies.Append | CookieOptions | Unspecified |
Historial y cambios
La compatibilidad con SameSite se implementó por primera vez en ASP.NET Core en la versión 2.0 con el estándar de borrador de 2016. El estándar de 2016 era opcional. ASP.NET Core optó por participar estableciendo varias cookies en Lax
de manera predeterminada. Después de encontrar varios problemas con la autenticación, se deshabilitó la mayoría del uso de SameSite.
Las revisiones se emitieron en noviembre de 2019 para actualizar del estándar de 2016 al estándar de 2019. El borrador de 2019 de la especificación SameSite:
- No es compatible con el borrador de 2016. Para más información, vea Compatibilidad con exploradores más antiguos en este documento.
- especifica que las cookies se tratan como
SameSite=Lax
de manera predeterminada; - especifica que las cookies que afirman explícitamente
SameSite=None
para habilitar la entrega entre sitios deben estar marcadas comoSecure
.None
es una nueva entrada para no participar. - Es compatible con las revisiones emitidas para ASP.NET Core 2.1, 2.2 y 3.0. ASP.NET Core 3.1 tiene compatibilidad adicional con SameSite.
- Está previsto que Chrome lo habilite de manera predeterminada en febrero de 2020. Los exploradores empezaron a pasar a este estándar en 2019.
API afectadas por el cambio del estándar de borrador de SameSite de 2016 al estándar de borrador de 2019
- Http.SameSiteMode
- CookieOptions.SameSite
- CookieBuilder.SameSite
- CookiePolicyOptions.MinimumSameSitePolicy
- Microsoft.Net.Http.Headers.SameSiteMode
- Microsoft.Net.Http.Headers.SetCookieHeaderValue.SameSite
Compatibilidad con exploradores más antiguos
El estándar de SameSite de 2016 obligaba a tratar los valores desconocidos como valores de SameSite=Strict
. Las aplicaciones a las que se accede desde exploradores antiguos que admiten el estándar de SameSite de 2016 pueden interrumpirse cuando obtienen una propiedad de SameSite con un valor de None
. Las aplicaciones web deben implementar la detección de navegadores si pretenden ser compatibles con navegadores antiguos. ASP.NET Core no implementa la detección del explorador porque los valores de User-Agents son muy volátiles y cambian con frecuencia. Un punto de extensión en Microsoft.AspNetCore.CookiePolicy permite conectar la lógica específica de User-Agent.
En Startup.Configure
, agrega código que llame a UseCookiePolicy antes de llamar a UseAuthentication o cualquier método que escriba 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();
});
}
En Startup.ConfigureServices
, agregue código similar al siguiente:
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);
}
}
}
En el ejemplo anterior, MyUserAgentDetectionLib.DisallowsSameSiteNone
es una biblioteca proporcionada por el usuario que detecta si el agente de usuario no admite None
de SameSite:
if (MyUserAgentDetectionLib.DisallowsSameSiteNone(userAgent))
{
options.SameSite = SameSiteMode.Unspecified;
}
El siguiente código muestra un método DisallowsSameSiteNone
de ejemplo:
Advertencia
El código siguiente es solo para demostración:
- No debería considerarse completo.
- No se mantiene ni tiene soporte.
public static bool DisallowsSameSiteNone(string userAgent)
{
// Check if a null or empty string has been passed in, since this
// will cause further interrogation of the useragent to fail.
if (String.IsNullOrWhiteSpace(userAgent))
return false;
// 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;
}
Probar aplicaciones para problemas de SameSite
Las aplicaciones que interactúan con sitios remotos, por ejemplo mediante inicio de sesión de terceros, necesitan:
- Probar la interacción en varios navegadores.
- Aplica la Detección y mitigación del navegador CookiePolicy tratada en este documento.
Probar las aplicaciones web usando una versión cliente que pueda incorporarse al nuevo comportamiento de SameSite. Chrome, Firefox y Chromium Edge tienen nuevas marcas de características de participación que se pueden usar para las pruebas. Una vez que la aplicación aplique las revisiones de SameSite, pruébela con versiones de cliente anteriores, especialmente Safari. Para más información, vea Compatibilidad con exploradores más antiguos en este documento.
Prueba con Chrome
Chrome 78+ proporciona resultados engañosos porque tiene una mitigación temporal en su lugar. La mitigación temporal de Chrome 78+ admite cookies de menos de dos minutos de antigüedad. Chrome 76 o 77 con las marcas de prueba adecuadas habilitadas proporciona resultados más precisos. Para probar el nuevo comportamiento, cambie chrome://flags/#same-site-by-default-cookies
a Habilitado. Se ha informado de que las versiones más antiguas de Chrome (75 e inferiores) fallan con la nueva configuración de None
. Consulte Compatibilidad con exploradores más antiguos en este documento.
Google no hace que las versiones de Chrome anteriores estén disponibles. Siga las instrucciones que aparecen en Descargar Chromium para probar versiones anteriores de Chrome. No descargue Chrome desde los vínculos proporcionados mediante la búsqueda de versiones anteriores de Chrome.
A partir de la versión de Canary 80.0.3975.0
, la mitigación temporal Lax+POST se puede deshabilitar con fines de prueba con la nueva marca --enable-features=SameSiteDefaultChecksMethodRigorously
para permitir la prueba de sitios y servicios en el estado final de la característica en la que se ha quitado la mitigación. Para más información, consulte las Actualizaciones de SameSite de The Chromium Projects
Prueba con Safari
Safari 12 aplica estrictamente el proyecto anterior y falla cuando el nuevo valor None
está en un cookie. None
se evita a través del código de detección del explorador Compatibilidad con exploradores más antiguos en este documento. Pruebe los inicios de sesión de estilo del sistema operativo basados en Safari 12, Safari 13 y WebKit mediante MSAL, ADAL o cualquier biblioteca que esté usando. El problema depende de la versión del sistema operativo subyacente. Se sabe que OSX Mojave (10.14) e iOS 12 tienen problemas de compatibilidad con el nuevo comportamiento de SameSite. Actualizar el sistema operativo a OSX Catalina (10.15) o iOS 13 soluciona el problema. Safari no tiene actualmente una marca de participación para probar el comportamiento de la nueva especificación.
Prueba con Firefox
La compatibilidad de Firefox con el nuevo estándar puede probarse en la versión 68+ accediendo a la página about:config
con la marca de características network.cookie.sameSite.laxByDefault
. No ha habido informes de problemas de compatibilidad con versiones anteriores de Firefox.
Prueba con el explorador Edge
Edge admite el antiguo estándar de SameSite. La versión 44 de Edge no tiene problemas de compatibilidad conocidos con el nuevo estándar.
Prueba con Edge (Chromium)
Las marcas de SameSite se establecen en la página de edge://flags/#same-site-by-default-cookies
. No se detectaron problemas de compatibilidad con Edge Chromium.
Prueba con Electron
Las versiones de Electron incluyen versiones anteriores de Chromium. Por ejemplo, la versión de Electron usada por Teams es Chromium 66, que exhibe el comportamiento anterior. Realice sus propias pruebas de compatibilidad con la versión de Electron que use el producto. Consulte Compatibilidad con exploradores más antiguos en la sección siguiente.
Recursos adicionales
- Blog de Cromo:Desarrolladores: Prepárese para el nuevo SameSite=None; Proteger configuración de Cookie
- Cookies de SameSite explicadas
- Revisiones de noviembre de 2019
Muestra | Documento |
---|---|
.NET Core MVC | Ejemplo cookie de SameSite de MVC de ASP.NET Core 2.1 |
Razor Pages de .NET Core | Ejemplo de SameSite de Razor Pages de ASP.NET Core 2.1 cookie |