Trabalhar com cookies SameSite no ASP.NET

De Rick Anderson

SameSite é um padrão de rascunho IETF projetado para fornecer alguma proteção contra ataques CSRF (solicitação de solicitação entre sites). Originalmente redigido em 2016, o rascunho padrão foi atualizado em 2019. O padrão atualizado não é compatível com versões anteriores com o padrão anterior, sendo as seguintes diferenças mais perceptíveis:

  • Cookies sem cabeçalho SameSite são tratados como SameSite=Lax por padrão.
  • SameSite=None deve ser usado para permitir o uso de cookie entre sites.
  • Os cookies que declaram SameSite=None também devem ser marcados como Secure.
  • Os aplicativos que usam <iframe> podem enfrentar problemas com sameSite=Lax cookies ou sameSite=Strict porque <iframe> são tratados como cenários entre sites.
  • O valor SameSite=None não é permitido pelo padrão de 2016 e faz com que algumas implementações tratem cookies como SameSite=Strict. Consulte Suporte a navegadores mais antigos neste documento.

A SameSite=Lax configuração funciona para a maioria dos cookies de aplicativo. 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 disparam as proteções do navegador SameSite, portanto, SameSite está desabilitado para esses componentes. A maioria dos logons do OAuth não é afetada devido a diferenças na forma como a solicitação flui.

Cada componente ASP.NET que emite cookies precisa decidir se o SameSite é apropriado.

Consulte Problemas conhecidos para problemas com aplicativos depois de instalar as atualizações do .Net SameSite 2019.

Usando o SameSite no ASP.NET 4.7.2 e 4.8

O .Net 4.7.2 e 4.8 dá suporte ao padrão de rascunho de 2019 para o SameSite desde o lançamento das atualizações em dezembro de 2019. Os desenvolvedores podem controlar programaticamente o valor do cabeçalho SameSite usando a propriedade HttpCookie.SameSite. Definir a SameSite propriedade Strictcomo , Laxou None resulta na gravação desses valores na rede com o cookie. Defini-lo como igual a (SameSiteMode)(-1) indica que nenhum cabeçalho SameSite deve ser incluído na rede com o cookie. A Propriedade HttpCookie.Secure ou 'requireSSL' em arquivos de configuração pode ser usada para marcar o cookie como Secure ou não.

Novas HttpCookie instâncias usarão como padrão SameSite=(SameSiteMode)(-1) e Secure=false. Esses padrões podem ser substituídos na seção de configuração, em system.web/httpCookies que a cadeia de "Unspecified" caracteres é uma sintaxe amigável somente de configuração para (SameSiteMode)(-1):

<configuration>
 <system.web>
  <httpCookies sameSite="[Strict|Lax|None|Unspecified]" requireSSL="[true|false]" />
 <system.web>
<configuration>

ASP.Net também emite quatro cookies específicos para esses recursos: Autenticação Anônima, Autenticação de Formulários, Estado de Sessão e Gerenciamento de Funções. Instâncias desses cookies obtidas em runtime podem ser manipuladas usando as SameSite propriedades e Secure , assim como qualquer outra instância HttpCookie. No entanto, devido ao surgimento do padrão SameSite, as opções de configuração para esses quatro recursos são inconsistentes. As seções e atributos de configuração relevantes, com padrões, são mostrados abaixo. Se não houver nenhum SameSite atributo ou Secure relacionado para um recurso, o recurso retornará os padrões configurados na system.web/httpCookies seção discutida acima.

<configuration>
 <system.web>
  <anonymousIdentification cookieRequireSSL="false" /> <!-- No config attribute for SameSite -->
  <authentication>
   <forms cookieSameSite="Lax" requireSSL="false" />
  </authentication>
  <sessionState cookieSameSite="Lax" /> <!-- No config attribute for Secure -->
  <roleManager cookieRequireSSL="false" /> <!-- No config attribute for SameSite -->
 <system.web>
<configuration>

Observação: 'Não especificado' só está disponível para system.web/httpCookies@sameSite no momento. Esperamos adicionar uma sintaxe semelhante aos atributos cookieSameSite mostrados anteriormente em atualizações futuras. A configuração (SameSiteMode)(-1) no código ainda funciona em instâncias desses cookies.*

Se você estiver lendo isso em um idioma diferente do inglês, informe-nos neste problema de discussão do GitHub se quiser ver os comentários de código em seu idioma nativo.

Redirecionar aplicativos .NET

Para direcionar o .NET 4.7.2 ou posterior:

  • Verifique se web.config contém o seguinte:

    <system.web>
      <compilation targetFramework="4.7.2"/>
      <httpRuntime targetFramework="4.7.2"/>
    </system.web>
    
    
  • Verifique se o arquivo de projeto contém o TargetFrameworkVersion correto:

    <TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
    

    O Guia de Migração do .NET tem mais detalhes.

  • Verifique se os pacotes NuGet no projeto são direcionados para a versão correta da estrutura. Você pode verificar a versão correta da estrutura examinando o arquivo packages.config , por exemplo:

    <?xml version="1.0" encoding="utf-8"?>
    <packages>
      <package id="Microsoft.AspNet.Mvc" version="5.2.7" targetFramework="net472" />
      <package id="Microsoft.ApplicationInsights" version="2.4.0" targetFramework="net451" />
    </packages>
    

    No arquivo packages.config anterior, o Microsoft.ApplicationInsights pacote:

    • É direcionado ao .NET 4.5.1.
    • Deve ter seu targetFramework atributo atualizado para se houver um pacote atualizado direcionado ao net472 seu destino de estrutura.

Versões do .NET anteriores à 4.7.2

A Microsoft não dá suporte a versões do .NET inferiores à 4.7.2 para gravar o atributo de cookie do mesmo site. Não encontramos uma maneira confiável de:

  • Verifique se o atributo foi gravado corretamente com base na versão do navegador.
  • Interceptar e ajustar cookies de autenticação e de sessão em versões mais antigas da estrutura.

Alterações de comportamento de patch de dezembro

A alteração de comportamento específica para .NET Framework é como a SameSite propriedade interpreta o None valor:

  • Antes do patch, um valor de None significa:
    • Não emita o atributo.
  • Após o patch:
    • Um valor de None significa "Emitir o atributo com um valor de None".
    • Um SameSite valor de (SameSiteMode)(-1) faz com que o atributo não seja emitido.

O valor sameSite padrão para autenticação de formulários e cookies de estado de sessão foi alterado de None para Lax.

Resumo do impacto da alteração nos navegadores

Se você instalar o patch e emitir um cookie com SameSite.None, uma das duas coisas acontecerá:

  • O Chrome v80 tratará esse cookie de acordo com a nova implementação e não imporá as mesmas restrições de site ao cookie.
  • Qualquer navegador que não tenha sido atualizado para dar suporte à nova implementação seguirá a implementação antiga. A implementação antiga diz:
    • Se você vir um valor que não entende, ignore-o e alterne para restrições estritas do mesmo site.

Portanto, o aplicativo é interrompido no Chrome ou você divide em vários outros lugares.

Histórico e alterações

O suporte ao SameSite foi implementado pela primeira vez no .NET 4.7.2 usando o padrão de rascunho de 2016.

As atualizações de 19 de novembro de 2019 para o Windows atualizaram o .NET 4.7.2+ do padrão 2016 para o padrão 2019. Atualizações adicionais estão próximas para outras versões do Windows. Para obter mais informações, consulte artigos de KB que dão suporte ao SameSite no .NET Framework.

O rascunho de 2019 da especificação SameSite:

  • 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 os cookies são tratados como SameSite=Lax por padrão.
  • Especifica cookies que declaram SameSite=None explicitamente para habilitar a entrega entre sites também devem ser marcados como Secure.
  • Há suporte para patches emitidos conforme descrito na KB listada acima.
  • 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.

Problemas conhecidos

Como as especificações de rascunho de 2016 e 2019 não são compatíveis, a atualização do .Net Framework de novembro de 2019 apresenta algumas alterações que podem estar falhando.

  • Os cookies de Autenticação de Formulários e Estado de Sessão agora são gravados na rede como Lax em vez de não especificados.
    • Embora a maioria dos aplicativos trabalhe com SameSite=Lax cookies, os aplicativos que POSTam entre sites ou aplicativos que fazem uso do podem descobrir que seus cookies de autorização de formulários ou estado de iframe sessão não estão sendo usados conforme o esperado. Para corrigir isso, altere o cookieSameSite valor na seção de configuração apropriada, conforme discutido anteriormente.
  • HttpCookies que definem SameSite=None explicitamente no código ou na configuração agora têm esse valor gravado com o cookie, enquanto ele foi omitido anteriormente. Isso pode causar problemas com navegadores mais antigos que dão suporte apenas ao padrão de rascunho de 2016.
    • Ao direcionar navegadores que dão suporte ao padrão de rascunho de 2019 com SameSite=None cookies, lembre-se de também marcá-los Secure ou eles podem não ser reconhecidos.
    • Para reverter ao comportamento de 2016 de não gravar SameSite=None, use a configuração aspnet:SupressSameSiteNone=truedo aplicativo . Observe que isso se aplicará a todos os HttpCookies no aplicativo.

Consulte Serviço de Aplicativo do Azure – Manipulação de cookies SameSite e patch .NET Framework 4.7.2 para obter informações sobre como Serviço de Aplicativo do Azure está configurando comportamentos sameSite em aplicativos .Net 4.7.2.

Suporte a navegadores mais antigos

O padrão do SameSite de 2016 determina que valores desconhecidos sejam tratados como valores SameSite=Strict. Os aplicativos acessados de navegadores mais antigos que dão suporte ao padrão SameSite de 2016 podem ser interrompidos quando recebem uma propriedade SameSite 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.

A abordagem da Microsoft para corrigir o problema é ajudá-lo a implementar componentes de detecção de navegador para remover o sameSite=None atributo de cookies se um navegador for conhecido por não dar suporte a ele. O conselho do Google era emitir cookies duplos, um com o novo atributo e outro sem o atributo. No entanto, consideramos os conselhos do Google limitados. Alguns navegadores, especialmente navegadores móveis, têm limites muito pequenos no número de cookies que um site ou um nome de domínio pode enviar. O envio de vários cookies, especialmente cookies grandes, como cookies de autenticação, pode atingir o limite do navegador móvel muito rapidamente, causando falhas de aplicativo difíceis de diagnosticar e corrigir. Além disso, como uma estrutura, há um grande ecossistema de código e componentes de terceiros que podem não ser atualizados para usar uma abordagem de cookie duplo.

O código de detecção do navegador usado nos projetos de exemplo neste repositório GitHub está contido em dois arquivos

Essas detecções são os agentes de navegador mais comuns que vimos que dão suporte ao padrão 2016 e para os quais o atributo precisa ser completamente removido. Isso não se destina a uma implementação completa:

  • Seu aplicativo pode ver navegadores que nossos sites de teste não fazem.
  • Você deve estar preparado para adicionar detecções conforme necessário para seu ambiente.

A forma como você conecta a detecção varia de acordo com a versão do .NET e a estrutura da Web que você está usando. O código a seguir pode ser chamado no site de chamada HttpCookie :

private void CheckSameSite(HttpContext httpContext, HttpCookie cookie)
{
    if (cookie.SameSite == SameSiteMode.None)
    {
        var userAgent = httpContext.Request.UserAgent;
        if (BrowserDetection.DisallowsSameSiteNone(userAgent))
        {
            cookie.SameSite = (SameSiteMode)(-1);
        }
    }
}

Consulte os seguintes tópicos de cookie do SameSite do ASP.NET 4.7.2:

Garantir que seu site redirecione para HTTPS

Para ASP.NET 4.x, WebForms e MVC, o recurso de Reescrita de URL do IIS pode ser usado para redirecionar todas as solicitações para HTTPS. O XML a seguir mostra uma regra de exemplo:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <system.webServer>
    <rewrite>
      <rules>
        <rule name="Redirect to https" stopProcessing="true">
          <match url="(.*)"/>
          <conditions>
            <add input="{HTTPS}" pattern="Off"/>
            <add input="{REQUEST_METHOD}" pattern="^get$|^head$" />
          </conditions>
          <action type="Redirect" url="https://{HTTP_HOST}/{R:1}" redirectType="Permanent"/>
        </rule>
      </rules>
    </rewrite>
  </system.webServer>
</configuration>

Em instalações locais da Reescrita de URL do IIS , há um recurso opcional que pode precisar ser instalado.

Testar aplicativos para problemas do SameSite

Você deve testar seu aplicativo com os navegadores compatíveis e percorrer seus cenários que envolvem cookies. Cenários de cookie normalmente envolvem

  • Formulários de logon
  • Mecanismos de logon externos, como Facebook, Azure AD, OAuth e OIDC
  • Páginas que aceitam solicitações de outros sites
  • Páginas em seu aplicativo projetadas para serem inseridas em iframes

Você deve marcar que os cookies sejam criados, persistidos e excluídos corretamente em seu aplicativo.

Os aplicativos que interagem com sites remotos, como por meio de logon de terceiros, precisam:

Teste aplicativos Web usando uma versão do cliente que pode aceitar o novo comportamento SameSite. 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 o aplicativo aplicar os patches SameSite, teste-o com versões mais antigas do cliente, especialmente o Safari. Para obter mais informações, consulte Suporte a navegadores mais antigos neste documento.

Testar com o Chrome

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 de idade. O Chrome 76 ou 77 com os sinalizadores de teste apropriados habilitados fornece resultados mais precisos. Para testar o novo comportamento do SameSite, 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.

A partir da versão 80.0.3975.0canário, a mitigação temporária lax+POST pode ser desabilitada para fins de teste usando o novo sinalizador --enable-features=SameSiteDefaultChecksMethodRigorously para permitir testes de sites e serviços no estado final eventual do recurso em que a mitigação foi removida. Para obter mais informações, consulte Atualizações do SameSite do The Chromium Projects

Testar com o Chrome 80+

Baixe uma versão do Chrome que dê suporte ao novo atributo. No momento da gravação, a versão atual é o Chrome 80. O Chrome 80 precisa do sinalizador chrome://flags/#same-site-by-default-cookies habilitado para usar o novo comportamento. Você também deve habilitar (chrome://flags/#cookies-without-same-site-must-be-secure) para testar o comportamento futuro de cookies que não têm o mesmo Atributo de site habilitado. O Chrome 80 está no destino para fazer a opção de tratar cookies sem o atributo como SameSite=Lax, embora com um período de carência cronometrado para determinadas solicitações. Para desabilitar o período de carência cronometrado, o Chrome 80 pode ser iniciado com o seguinte argumento de linha de comando:

--enable-features=SameSiteDefaultChecksMethodRigorously

O Chrome 80 tem mensagens de aviso no console do navegador sobre atributos sameSite ausentes. Use F12 para abrir o console do navegador.

Testar com o Safari

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 os logons de estilo do sistema operacional baseados em Safari 12, Safari 13 e WebKit usando MSAL, ADAL ou qualquer biblioteca que você esteja usando. O problema depende da versão subjacente do sistema operacional. Sabe-se que o OSX Mojave (10.14) e o iOS 12 têm problemas de compatibilidade com o novo comportamento do SameSite. 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.

Testar com o Firefox

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.

Testar com o navegador Edge (Herdado)

O Edge dá suporte ao antigo padrão SameSite. A versão 44+ do Edge não tem problemas de compatibilidade conhecidos com o novo padrão.

Testar com o Edge (Chromium)

Os sinalizadores SameSite são definidos na página edge://flags/#same-site-by-default-cookies. Nenhum problema de compatibilidade foi descoberto com o Edge Chromium.

Testar com Electron

As versões do Electron incluem versões mais antigas do Chromium. Por exemplo, a versão do Electron usada pelo Teams é Chromium 66, que exibe o comportamento mais antigo. Você deve executar seu próprio teste de compatibilidade com a versão do Electron que seu produto usa. Consulte Suporte a navegadores mais antigos.

Revertendo patches SameSite

Você pode reverter o comportamento atualizado do sameSite em aplicativos .NET Framework ao comportamento anterior em que o atributo sameSite não é emitido para um valor de Nonee reverter os cookies de autenticação e de sessão para não emitir o valor. Isso deve ser visto como uma correção extremamente temporária, pois as alterações do Chrome interromperão quaisquer solicitações POST externas ou autenticação para usuários que usam navegadores que dão suporte às alterações no padrão.

Revertendo o comportamento do .NET 4.7.2

Atualize web.config para incluir as seguintes definições de configuração:

<configuration> 
  <appSettings>
    <add key="aspnet:SuppressSameSiteNone" value="true" />
  </appSettings>
 
  <system.web> 
    <authentication> 
      <forms cookieSameSite="None" /> 
    </authentication> 
    <sessionState cookieSameSite="None" /> 
  </system.web> 
</configuration>

Recursos adicionais