Cookies sameSite e o OWIN (Open Web Interface for .NET)

De Rick Anderson

SameSite é um rascunho de IETF projetado para fornecer alguma proteção contra ataques CSRF (solicitação de solicitação entre sites). O rascunho do SameSite 2019:

  • Trata cookies como SameSite=Lax por padrão.
  • Os cookies de estados que declaram SameSite=None explicitamente para habilitar a entrega entre sites devem ser marcados como Secure.

Lax 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 SameSite navegador, portanto SameSite , estão desabilitados para esses componentes. A maioria dos logons do 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 OWIN que emite cookies precisa decidir se SameSite é apropriado.

Para obter a ASP.NET versão 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 daquele em System.Web.
  • SameSite funciona em todas as versões direcionadas pelos Microsoft.Owin pacotes, .NET 4.5 e posteriores.
  • Somente o componente SystemWebCookieManager interage diretamente com a System.WebHttpCookie 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 a serem usados SystemWebCookieManager são descritos em problemas de integração de cookie de resposta do OWIN e do System.Web. SystemWebCookieManager é recomendado ao executar em System.Web.

O código a seguir define 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

O Microsoft.Owin nunca deu suporte ao SameSite padrão de rascunho de 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 os 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.
  • Há suporte para patches emitidos conforme descrito nos artigos do KB. Para obter mais informações, consulte artigos de KB que dão suporte ao SameSite no .NET Framework.

Suporte a navegadores mais antigos

O padrão de 2016 SameSite determina que valores desconhecidos devem ser tratados como SameSite=Strict valores. Os aplicativos acessados de navegadores mais antigos que dão suporte ao padrão de 2016 SameSite podem ser interrompidos quando recebem uma SameSite propriedade com um valor de None. Os aplicativos Web devem implementar a detecção de navegador se pretenderem dar suporte a navegadores mais antigos. ASP.NET não implementa a detecção de 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 User-Agent lógica específica.

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

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 de exemplo DisallowsSameSiteNone :

Aviso

O código a seguir é apenas para demonstração:

  • Ele 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. Chrome, Firefox e Chromium Edge têm novos sinalizadores de recursos de aceitação que podem ser usados para teste. Depois que o aplicativo aplicar os patches, teste-o SameSite 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 a alternância chrome://flags/#same-site-by-default-cookies de novo SameSite comportamento para Habilitado. Versões mais antigas do Chrome (75 e abaixo) são relatadas para falhar com a nova None configuração. 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 Que dá suporte a navegadores mais antigos neste documento. Teste os logons de estilo do sistema operacional baseado em Safari 12, Safari 13 e WebKit usando a MSAL ou qualquer biblioteca que você esteja usando. O problema depende da versão subjacente do sistema operacional. OSX Mojave (10.14) e iOS 12 são conhecidos por terem problemas de compatibilidade com o novo SameSite comportamento. Atualizar o sistema operacional para 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 para o novo padrão pode ser testado na versão 68+ aceitando na about:config página com o sinalizador network.cookie.sameSite.laxByDefaultde recurso . Não houve relatos de problemas de compatibilidade com versões mais antigas do Firefox.

Testar com o navegador Edge

O Edge dá suporte ao 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.

Testar com o 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 na seção a seguir.

Recursos adicionais