Ler em inglês

Compartilhar via


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 como Secure.

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.

Uso de API com SameSite

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 pelos Microsoft.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:

Histórico e alterações

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 como Secure. 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.

Suporte a navegadores mais antigos

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

Testar aplicativos para problemas do SameSite

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 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.

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. 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.

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 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.

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

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.

Testar com o Edge (Chromium)

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.

Teste com Electron

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.

Recursos adicionais