Cookies SameSite e a Interface Web Aberta para .NET (OWIN)
Por Rick Anderson
SameSite
é um rascunho do IETF projetado para fornecer alguma proteção contra ataques de falsificação de solicitação entre sites (CSRF). O rascunho do SameSite 2019:
- Trata os cookies como
SameSite=Lax
por padrão. - Os cookies de estados que declaram
SameSite=None
explicitamente para permitir a entrega entre sites devem ser marcados comoSecure
.
Lax
Funciona para a maioria dos cookies de aplicativos. Algumas formas de autenticação, como OpenID Connect (OIDC) e WS-Federation, são padrão para redirecionamentos baseados em POST. Os redirecionamentos baseados em POST acionam as proteções do SameSite
navegador, portanto SameSite
, são desativados para esses componentes. A maioria dos logins OAuth não é afetada devido a diferenças na forma como a solicitação flui. Todos os outros componentes não são definidos SameSite
por padrão e usam o comportamento padrão dos clientes (antigo ou novo).
O None
parâmetro causa problemas de compatibilidade com clientes que implementaram o padrão de rascunho anterior de 2016 (por exemplo, iOS 12). Consulte Suporte a navegadores mais antigos neste documento.
Cada componente do OWIN que emite cookies precisa decidir se SameSite
é apropriado.
Para obter a versão ASP.NET 4.x deste artigo, consulte Trabalhar com cookies SameSite no ASP.NET.
Microsoft.Owin
tem sua própria SameSite
implementação:
- Isso não depende diretamente do de
System.Web
. SameSite
funciona em todas as versões direcionáveis pelosMicrosoft.Owin
pacotes, .NET 4.5 e posterior.- Somente o componente SystemWebCookieManager interage diretamente com a
System.Web
HttpCookie
classe.
SystemWebCookieManager
depende das APIs do .NET 4.7.2 System.Web
para habilitar SameSite
o suporte e dos patches para alterar o comportamento.
Os motivos para usar SystemWebCookieManager
são descritos em Problemas de integração de cookies de resposta do OWIN e System.Web. SystemWebCookieManager
é recomendado ao executar em System.Web
.
O código a seguir é definido SameSite
como Lax
:
owinContext.Response.Cookies.Append("My Key", "My Value", new CookieOptions()
{
SameSite = SameSiteMode.Lax
});
As seguintes APIs usam SameSite
:
- Microsoft.Owin.SameSiteMode
- CookieOptions.SameSite
- Classe CookieAuthenticationOptions
- CookieAuthenticationOptions.CookieSameSite
- ICookieManager
- SystemWebCookieManager
- SystemWebChunkingCookieManager
- CookieAuthenticationOptions.CookieManager
- OpenIdConnectAuthenticationOptions.CookieManager
Microsoft.Owin nunca deu suporte ao padrão de rascunho de SameSite
2016.
O suporte para o rascunho do SameSite 2019 só está disponível na Microsoft.Owin
versão 4.1.0 e posterior. Não há patches para versões anteriores.
O rascunho de 2019 da SameSite
especificação:
- Não é compatível com versões anteriores com o rascunho de 2016. Para obter mais informações, consulte Suporte a navegadores mais antigos neste documento.
- Especifica que cookies são tratados como
SameSite=Lax
por padrão. - Especifica cookies que declaram
SameSite=None
explicitamente para habilitar a entrega entre sites deve ser marcado comoSecure
.None
é uma nova entrada a ser recusada. - Está programado para ser habilitado pelo Chrome por padrão em fevereiro de 2020. Os navegadores começaram a mudar para esse padrão em 2019.
- É suportado por patches emitidos conforme descrito nos artigos da base de conhecimento. Para obter mais informações, consulte artigos da base de dados de conhecimento que dão suporte a SameSite no .NET Framework.
O padrão de 2016 SameSite
determinou que valores desconhecidos devem ser tratados como SameSite=Strict
valores. Os aplicativos acessados de navegadores mais antigos que suportam o padrão de 2016 SameSite
podem ser interrompidos quando obtêm uma SameSite
propriedade com um valor de None
. Os aplicativos da Web devem implementar a detecção de navegador se pretenderem oferecer suporte a navegadores mais antigos. ASP.NET não implementa a detecção do navegador porque os valores de User-Agents são altamente voláteis e mudam com frequência. Um ponto de extensão no ICookieManager permite conectar a lógica específica do User-Agent.
Em Startup.Configuration
, adicione um código semelhante ao seguinte:
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.UseOpenIdConnectAuthentication(
new OpenIdConnectAuthenticationOptions
{
// … Your preexisting options …
CookieManager = new SameSiteCookieManager(
new SystemWebCookieManager())
});
// Remaining code removed for brevity.
O código anterior requer o patch do .NET 4.7.2 ou posterior SameSite
.
O código a seguir mostra um exemplo de implementação de SameSiteCookieManager
:
public class SameSiteCookieManager : ICookieManager
{
private readonly ICookieManager _innerManager;
public SameSiteCookieManager() : this(new CookieManager())
{
}
public SameSiteCookieManager(ICookieManager innerManager)
{
_innerManager = innerManager;
}
public void AppendResponseCookie(IOwinContext context, string key, string value,
CookieOptions options)
{
CheckSameSite(context, options);
_innerManager.AppendResponseCookie(context, key, value, options);
}
public void DeleteCookie(IOwinContext context, string key, CookieOptions options)
{
CheckSameSite(context, options);
_innerManager.DeleteCookie(context, key, options);
}
public string GetRequestCookie(IOwinContext context, string key)
{
return _innerManager.GetRequestCookie(context, key);
}
private void CheckSameSite(IOwinContext context, CookieOptions options)
{
if (options.SameSite == Microsoft.Owin.SameSiteMode.None
&& DisallowsSameSiteNone(context))
{
options.SameSite = null;
}
}
No exemplo anterior, DisallowsSameSiteNone
é chamado no CheckSameSite
método. DisallowsSameSiteNone
é um método de usuário que detecta se o agente do usuário não dá suporte a SameSite
None
:
private void CheckSameSite(IOwinContext context, CookieOptions options)
{
if (options.SameSite == Microsoft.Owin.SameSiteMode.None
&& DisallowsSameSiteNone(context))
{
options.SameSite = null;
}
}
O código a seguir mostra um método DisallowsSameSiteNone
de exemplo:
Aviso
O código a seguir é apenas para demonstração:
- Não deve ser considerado completo.
- Ele não é mantido ou suportado.
public static bool DisallowsSameSiteNone(IOwinContext context)
{
var userAgent = context.Request.Headers["User-Agent"];
if (string.IsNullOrEmpty(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;
}
Os aplicativos que interagem com sites remotos, como por meio de logon de terceiros, precisam:
- Teste a interação em vários navegadores.
- Aplique a detecção e mitigação do navegador discutidas neste documento.
Teste aplicativos Web usando uma versão do cliente que pode aceitar o novo SameSite
comportamento. O Chrome, o Firefox e o Chromium Edge têm novos sinalizadores de recursos de aceitação que podem ser usados para teste. Depois que seu aplicativo aplicar os patches, teste-o com versões mais antigas do cliente, especialmente o SameSite
Safari. Para obter mais informações, consulte Suporte a navegadores mais antigos neste documento.
O Chrome 78+ fornece resultados enganosos porque tem uma mitigação temporária em vigor. A mitigação temporária do Chrome 78+ permite cookies com menos de dois minutos. O Chrome 76 ou 77 com os sinalizadores de teste apropriados habilitados fornece resultados mais precisos. Para testar o novo SameSite
comportamento, alterne chrome://flags/#same-site-by-default-cookies
para Habilitado. Versões mais antigas do Chrome (75 e inferiores) são relatadas para falhar com a nova configuração None
. Consulte Suporte a navegadores mais antigos neste documento.
O Google não disponibiliza versões mais antigas do Chrome. Siga as instruções em Baixar Chromium para testar versões mais antigas do Chrome. Não baixe o Chrome de links fornecidos pesquisando versões mais antigas do Chrome.
O Safari 12 implementou estritamente o rascunho anterior e falha quando o novo None
valor está em um cookie. None
é evitado por meio do código de detecção do navegador Suporte a navegadores mais antigos neste documento. Teste logins no estilo operacional baseados no Safari 12, Safari 13 e WebKit usando MSAL ou qualquer biblioteca que você esteja usando. O problema depende da versão subjacente do sistema operacional. O OSX Mojave (10.14) e o iOS 12 são conhecidos por terem problemas de compatibilidade com o novo SameSite
comportamento. A atualização do SO para o OSX Catalina (10.15) ou iOS 13 corrige o problema. No momento, o Safari não tem um sinalizador de aceitação para testar o novo comportamento de especificação.
O suporte do Firefox ao novo padrão pode ser testado na versão 68+ aceitando-o na página about:config
com o sinalizador de recurso network.cookie.sameSite.laxByDefault
. Não houve relatos de problemas de compatibilidade com versões mais antigas do Firefox.
O Edge suporta o padrão antigo SameSite
. A versão 44 do Edge não tem problemas de compatibilidade conhecidos com o novo padrão.
SameSite
Os sinalizadores são definidos na edge://flags/#same-site-by-default-cookies
página. Nenhum problema de compatibilidade foi descoberto com o Edge Chromium.
As versões do Electron incluem versões mais antigas do Chromium. Por exemplo, a versão do Electron usada pelo Teams é o Chromium 66, que exibe o comportamento mais antigo. Você deve realizar seu próprio teste de compatibilidade com a versão do Electron que seu produto usa. Consulte Suporte a navegadores mais antigos na seção a seguir.