Os cookies ASP.NET_SessionId + OWIN não são enviados para o navegador


145

Estou com um problema estranho ao usar a autenticação de cookies Owin.

Quando inicio a autenticação do servidor IIS, funciona perfeitamente no IE / Firefox e Chrome.

Comecei a fazer alguns testes com autenticação e a fazer login em plataformas diferentes e vi um erro estranho. Esporadicamente, o framework Owin / IIS simplesmente não envia cookies para os navegadores. Vou digitar um nome de usuário e senha corretos, o código é executado, mas nenhum cookie é entregue ao navegador. Se eu reiniciar o servidor, ele começará a funcionar e, em algum momento, tentarei fazer login e novamente os cookies deixarão de ser entregues. Passar o código não faz nada e não gera erros.

 app.UseCookieAuthentication(new CookieAuthenticationOptions
        {
            AuthenticationMode = AuthenticationMode.Active,
            CookieHttpOnly = true,
            AuthenticationType = "ABC",
            LoginPath = new PathString("/Account/Login"),
            CookiePath = "/",
            CookieName = "ABC",
            Provider = new CookieAuthenticationProvider
               {
                  OnApplyRedirect = ctx =>
                  {
                     if (!IsAjaxRequest(ctx.Request))
                     {
                        ctx.Response.Redirect(ctx.RedirectUri);
                     }
                 }
               }
        });

E dentro do meu procedimento de login, tenho o seguinte código:

IAuthenticationManager authenticationManager = HttpContext.Current.GetOwinContext().Authentication;
                            authenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie);

var authentication = HttpContext.Current.GetOwinContext().Authentication;
var identity = new ClaimsIdentity("ABC");
identity.AddClaim(new Claim(ClaimTypes.Name, user.Username));
identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, user.User_ID.ToString()));
identity.AddClaim(new Claim(ClaimTypes.Role, role.myRole.ToString()));
    authentication.AuthenticationResponseGrant =
        new AuthenticationResponseGrant(identity, new AuthenticationProperties()
                                                   {
                                                       IsPersistent = isPersistent
                                                   });

authenticationManager.SignIn(new AuthenticationProperties() {IsPersistent = isPersistent}, identity);

Atualização 1: Parece que uma das causas do problema é quando eu adiciono itens à sessão. Os problemas começam. Adicionar algo simples como Session.Content["ABC"]= 123parece criar o problema.

O que eu consigo entender é o seguinte: 1) (Chrome) Ao fazer login, recebo o ASP.NET_SessionId + meu cookie de autenticação. 2) Vou para uma página que define uma sessão. Conteúdo ... 3) Abra um novo navegador (Firefox) e tente fazer o login e ele não recebe um ASP.NET_SessionId nem recebe um cookie de autenticação 4) Enquanto o primeiro navegador tem o ASP.NET_SessionId, ele continua funcionando. No momento em que removo este cookie, ele tem o mesmo problema que todos os outros navegadores em que estou trabalhando no endereço IP (10.xxx) e no localhost.

Atualização 2: force a criação da ASPNET_SessionIdprimeira na minha página login_load antes da autenticação com o OWIN.

1) antes de me autenticar com o OWIN, faço um Session.Contentvalor aleatório na minha página de login para iniciar o ASP.NET_SessionId 2) depois autentico e faço mais sessões 3) Outros navegadores parecem funcionar agora

Isso é bizarro. Só posso concluir que isso tem algo a ver com ASP e OWIN pensando que eles estão em domínios diferentes ou algo assim.

Atualização 3 - Comportamento estranho entre os dois.

Comportamento estranho adicional identificado - O tempo limite da sessão Owin e ASP é diferente. O que estou vendo é que minhas sessões Owin permanecem vivas por mais tempo do que minhas sessões ASP através de algum mecanismo. Portanto, ao fazer login: 1.) eu tenho uma sessão de autenticação baseada em cookied 2.) eu defini algumas variáveis ​​de sessão

Minhas variáveis ​​de sessão (2) "morrem" antes da variável de sessão do cookie owin força o login novamente, o que causa comportamento inesperado em todo o aplicativo. (A pessoa está logada, mas não está realmente logada)

Atualização 3B

Após algumas pesquisas, vi alguns comentários em uma página dizendo que o tempo limite da autenticação "forms" e o tempo limite da sessão precisam corresponder. Penso que normalmente os dois estão sincronizados, mas por qualquer motivo os dois não estão sincronizados.

Resumo das soluções alternativas

1) Crie sempre uma sessão antes da autenticação. Basicamente, crie uma sessão ao iniciar o aplicativoSession["Workaround"] = 0;

2) [Experimental] se você persistir com cookies, verifique se o tempo limite / duração do OWIN é maior que o tempo da sua sessão no seu web.config (em teste)


1
Pode confirmar que a adição de uma chamada de sessão ao ActionResult Login e ao ActionResult ExternalLogin corrigiu esse problema. Tenho certeza de que apenas um é necessário, mas tenho os dois no lugar.
6164 Scott

! Obrigado ... Adicionando Session em ExternalLogin fixa-lo para mim ... isso é mágica voodoo ... eu já ter desperdiçado 6 horas para caçar esta questão para baixo ..
XDev

Respostas:


159

Eu encontrei o mesmo problema e rastreei a causa da implementação de hospedagem do ASP.NET do OWIN. Eu diria que é um bug.

Alguma experiência

Minhas descobertas são baseadas nessas versões de montagem:

  • Microsoft.Owin, versão = 2.0.2.0, Culture = neutral, PublicKeyToken = 31bf3856ad364e35
  • Microsoft.Owin.Host.SystemWeb, versão = 2.0.2.0, Culture = neutral, PublicKeyToken = 31bf3856ad364e35
  • System.Web, Versão = 4.0.0.0, Cultura = neutra, PublicKeyToken = b03f5f7f11d50a3a

O OWIN usa sua própria abstração para trabalhar com os cookies de resposta ( Microsoft.Owin.ResponseCookieCollection ). Essa implementação envolve diretamente a coleção de cabeçalhos de resposta e atualiza o cabeçalho Set-Cookie . O host OWIN ASP.NET ( Microsoft.Owin.Host.SystemWeb ) apenas envolve System.Web.HttpResponse e sua coleção de cabeçalhos. Portanto, quando um novo cookie é criado por meio do OWIN, o cabeçalho Set-Cookie da resposta é alterado diretamente.

Mas o ASP.NET também usa sua própria abstração para trabalhar com os cookies de resposta. Isso é exposto a nós como propriedade System.Web.HttpResponse.Cookies e implementado pela classe selada System.Web.HttpCookieCollection . Essa implementação não envolve diretamente o cabeçalho Set-Cookie da resposta, mas usa algumas otimizações e um punhado de notificações internas para manifestar seu estado alterado para o objeto de resposta.

Depois, há um ponto no final da vida útil da solicitação em que o estado alterado de HttpCookieCollection é testado ( System.Web.HttpResponse.GenerateResponseHeadersForCookies () ) e os cookies são serializados no cabeçalho Set-Cookie . Se essa coleção estiver em algum estado específico, o cabeçalho Set-Cookie inteiro será limpo e recriado primeiro a partir de cookies armazenados na coleção.

A implementação da sessão do ASP.NET usa a propriedade System.Web.HttpResponse.Cookies para armazenar seu cookie ASP.NET_SessionId. Também há alguma otimização básica no módulo de estado da sessão do ASP.NET ( System.Web.SessionState.SessionStateModule ) implementado através da propriedade estática chamada s_sessionEverSet, que é bastante autoexplicativa. Se você armazenar algo no estado da sessão em seu aplicativo, este módulo fará um pouco mais de trabalho para cada solicitação.


Voltar ao nosso problema de login

Com todas essas peças, seus cenários podem ser explicados.

Caso 1 - A sessão nunca foi definida

System.Web.SessionState.SessionStateModule , a propriedade s_sessionEverSet é falsa. Nenhuma identificação de sessão é gerada pelo módulo de estado da sessão e o estado da coleção System.Web.HttpResponse.Cookies não é detectado como alterado . Nesse caso, os cookies OWIN são enviados corretamente para o navegador e o login funciona.

Caso 2 - A sessão foi usada em algum lugar do aplicativo, mas não antes que o usuário tente autenticar

System.Web.SessionState.SessionStateModule , a propriedade s_sessionEverSet é verdadeira. Os IDs de sessão são gerados por SessionStateModule , o ASP.NET_SessionId é adicionado à coleção System.Web.HttpResponse.Cookies, mas é removido posteriormente na vida útil da solicitação, pois a sessão do usuário está realmente vazia. Nesse caso, o estado da coleção System.Web.HttpResponse.Cookies é detectado como alterado e o cabeçalho Set-Cookie é limpo primeiro antes que os cookies sejam serializados com o valor do cabeçalho.

Nesse caso, os cookies de resposta OWIN são "perdidos" e o usuário não é autenticado e é redirecionado de volta à página de login.

Caso 3 - A sessão é usada antes que o usuário tente se autenticar

System.Web.SessionState.SessionStateModule , a propriedade s_sessionEverSet é verdadeira. Os IDs de sessão são gerados pelo SessionStateModule , o ASP.NET_SessionId é adicionado ao System.Web.HttpResponse.Cookies . Devido à otimização interna no System.Web.HttpCookieCollection e System.Web.HttpResponse.GenerateResponseHeadersForCookies () , o cabeçalho Set-Cookie NÃO é limpo primeiro, mas é atualizado apenas.

Nesse caso, os cookies de autenticação OWIN e o ASP.NET_SessionId são enviados em resposta e o login funciona.


Problema mais geral com cookies

Como você pode ver, o problema é mais geral e não se limita à sessão do ASP.NET. Se você estiver hospedando o OWIN através do Microsoft.Owin.Host.SystemWeb e você / alguma coisa estiver usando diretamente a coleção System.Web.HttpResponse.Cookies, você estará em risco.

Por exemplo, isso funciona e os dois cookies são enviados corretamente ao navegador ...

public ActionResult Index()
{
    HttpContext.GetOwinContext()
        .Response.Cookies.Append("OwinCookie", "SomeValue");
    HttpContext.Response.Cookies["ASPCookie"].Value = "SomeValue";

    return View();
}

Mas isso não acontece e o OwinCookie está "perdido" ...

public ActionResult Index()
{
    HttpContext.GetOwinContext()
        .Response.Cookies.Append("OwinCookie", "SomeValue");
    HttpContext.Response.Cookies["ASPCookie"].Value = "SomeValue";
    HttpContext.Response.Cookies.Remove("ASPCookie");

    return View();
}

Ambos testados no VS2013, IISExpress e modelo de projeto MVC padrão.


7
Passei alguns dias tentando depurar e resolver esse problema em nosso ambiente de teste. A única solução alternativa que encontrei é a mesma sugerida (configuração da sessão antes da autenticação do usuário). Eu relatei o problema para katanaproject ... katanaproject.codeplex.com/workitem/197 , então talvez alguém faça um comentário lá.
Tomas Dolezal

11
Essa é uma falha bastante séria, especialmente porque eles foram empacotados devido ao modelo do vs2013.
Piotr Stulinski

2
Para alguém que quer investigar mais este, eu criei um projeto de teste em github.com/Neilski/IdentityBugDemo
Neilski

1
Correndo para esse problema por causa do uso de Controller.TempData que usa Session como o armazenamento de backup. Pode reproduzir facilmente a incapacidade de efetuar o login se um cookie ASP_NET.SessionId não existir a partir de uma solicitação anterior.
kingdango 30/09

2
Finalmente! Que questão estranha é essa. Obrigado. Esse ainda é um problema mais de dois anos depois que essa resposta foi escrita.
Spivonious

43

Começando com a ótima análise de @TomasDolezal, observei as fontes Owin e System.Web.

O problema é que o System.Web possui sua própria fonte principal de informações sobre cookies e esse não é o cabeçalho Set-Cookie. Owin conhece apenas o cabeçalho Set-Cookie. Uma solução alternativa é garantir que todos os cookies definidos por Owin também estejam definidos na HttpContext.Current.Response.Cookiescoleção.

Eu criei um pequeno middleware ( fonte , pepita ) que faz exatamente isso, que deve ser colocado imediatamente acima do registro do middleware do cookie.

app.UseKentorOwinCookieSaver();

app.UseCookieAuthentication(new CookieAuthenticationOptions());

1
Nos vamos dar uma chance a isso. Desde que após o asp.net Identity 2.2.0-alpha1, comecei a ter problemas não apenas no login, mas também no logout do usuário (o usuário não efetuará logout no logout, clique em | | geralmente, no caso de quando eu deixei o site aberto por algum tempo sem fazer nada |) .. E depois de definir uma sessão imediatamente antes do logon do usuário resolver o problema de logon, mas o problema de logout persiste .. Obrigado pelo seu esforço .. A propósito, há algo que eu deva fazer, exceto pela instalação do o pacote?
wooer

Você precisa ativá-lo app.UseKentorCookieMiddlewareSaver();em Startup.Auth.cs. Ele também deve lidar com a limpeza de cookies de logout.
Anders Abel

Muito obrigado Anders Abel, tanto o login como o logout funcionam bem agora. Mas o código no comentário acima precisa ser alterado (porque eu o segui :) sem sucesso) para ser: app.UseKentorOwinCookieSaver()e talvez incluído na sua resposta original, como na página GitHub do pacote .
#

1
Obrigado por perceber o documento incorreto. Na verdade, ele já está corrigido na página do GitHub, mas também atualizei minha resposta aqui.
Anders Abel

@AndersAbel Estou tentando adicionar inscrições Meetup para este projeto do github: github.com/owin-middleware/OwinOAuthProviders ''. Eu adicionei o Asana outro dia e não tive problemas, mas por algum motivo, com o Meetup, o método Aguard AuthenticationManager.GetExternalLoginInfoAsync () em Account // ExternalLoginCallback está retornando nulo. Infelizmente, seu pacote NuGet não resolveu meu problema. Gostaria de saber se você teve algum tempo para revisar comigo, pois poderá solucionar melhor o problema e enviar para o seu projeto.
Anthony Ruffino

42

Em resumo, o gerenciador de cookies .NET conquistará o gerenciador de cookies OWIN e substituirá os cookies definidos na camada OWIN . A correção é usar a classe SystemWebCookieManager, fornecida como uma solução no Projeto Katana aqui . Você precisa usar essa classe ou semelhante a ela, o que forçará o OWIN a usar o gerenciador de cookies .NET para que não haja inconsistências :

public class SystemWebCookieManager : ICookieManager
{
    public string GetRequestCookie(IOwinContext context, string key)
    {
        if (context == null)
        {
            throw new ArgumentNullException("context");
        }

        var webContext = context.Get<HttpContextBase>(typeof(HttpContextBase).FullName);
        var cookie = webContext.Request.Cookies[key];
        return cookie == null ? null : cookie.Value;
    }

    public void AppendResponseCookie(IOwinContext context, string key, string value, CookieOptions options)
    {
        if (context == null)
        {
            throw new ArgumentNullException("context");
        }
        if (options == null)
        {
            throw new ArgumentNullException("options");
        }

        var webContext = context.Get<HttpContextBase>(typeof(HttpContextBase).FullName);

        bool domainHasValue = !string.IsNullOrEmpty(options.Domain);
        bool pathHasValue = !string.IsNullOrEmpty(options.Path);
        bool expiresHasValue = options.Expires.HasValue;

        var cookie = new HttpCookie(key, value);
        if (domainHasValue)
        {
            cookie.Domain = options.Domain;
        }
        if (pathHasValue)
        {
            cookie.Path = options.Path;
        }
        if (expiresHasValue)
        {
            cookie.Expires = options.Expires.Value;
        }
        if (options.Secure)
        {
            cookie.Secure = true;
        }
        if (options.HttpOnly)
        {
            cookie.HttpOnly = true;
        }

        webContext.Response.AppendCookie(cookie);
    }

    public void DeleteCookie(IOwinContext context, string key, CookieOptions options)
    {
        if (context == null)
        {
            throw new ArgumentNullException("context");
        }
        if (options == null)
        {
            throw new ArgumentNullException("options");
        }

        AppendResponseCookie(
            context,
            key,
            string.Empty,
            new CookieOptions
            {
                Path = options.Path,
                Domain = options.Domain,
                Expires = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc),
            });
    }
}

Na inicialização do aplicativo, atribua-o ao criar suas dependências OWIN:

app.UseCookieAuthentication(new CookieAuthenticationOptions
{
    ...
    CookieManager = new SystemWebCookieManager()
    ...
});

Uma resposta semelhante foi fornecida aqui, mas ela não inclui toda a base de código necessária para resolver o problema. Por isso, vejo a necessidade de adicioná-la aqui, pois o link externo para o Projeto Katana pode ficar inativo e isso deve ser totalmente registrado. como uma solução aqui também.


obrigado, seu trabalho me, mas também eu limpo todas as sessões chamando este ControllerContext.HttpContext.Session.RemoveAll (); na função externallogincallback
adnan

É aplicável aos ASP.NET Webforms 4.6.1 ? O meu webApp usaASP.NET Webforms, OWIN, ADFS
Kiquenet 25/10/16

@Kiquenet Seu aplicativo da web usa cookies OWIN? Então sim.
Alexandru

No código Startup.ConfigureAuthtemos app.UseCookieAuthenticatione app.UseWsFederationAuthenticationfinalmente app.UseStageMarker
Kiquenet

@Alexandru Você pode considerar uma edição, minha equipe encontrou esse bug e foi raro e aleatório, ocultou-se de nós nos ambientes DEV e UAT. Esta citação de sua resposta não foi válida para nós: "O gerenciador de cookies .NET sempre vencerá". Isso seria fácil de encontrar e corrigir, se os cookies OWIN fossem sempre substituídos, nenhum de nosso middleware OIDC conseguiria sair de nossas estações de trabalho de desenvolvimento. Mas a aleatoriedade significou que o bug chegou até a produção por 2 dias antes de nos atingir em grande escala (metade de nossos usos internos não conseguia acessar via AAD). Se importa se eu remover a palavra "sempre" da sua resposta?
yzorg 18/08/19

17

A equipe de Katana respondeu ao problema levantado por Tomas Dolezar e postou a documentação sobre as soluções alternativas :

As soluções alternativas se enquadram em duas categorias. Uma é reconfigurar o System.Web para evitar o uso da coleção Response.Cookies e substituir os cookies OWIN. A outra abordagem é reconfigurar os componentes OWIN afetados para que eles gravem cookies diretamente na coleção Response.Cookies do System.Web.

  • Garantir que a sessão seja estabelecida antes da autenticação: o conflito entre os cookies System.Web e Katana é por solicitação, portanto, pode ser possível que o aplicativo estabeleça a sessão em alguma solicitação antes do fluxo de autenticação. Isso deve ser fácil quando o usuário chegar pela primeira vez, mas pode ser mais difícil garantir mais tarde quando a sessão ou os cookies de autenticação expirarem e / ou precisarem ser atualizados.
  • Desativar o SessionStateModule - Se o aplicativo não confiar nas informações da sessão, mas o módulo da sessão ainda estiver configurando um cookie que causa o conflito acima, considere desativar o módulo de estado da sessão.
  • Reconfigure o CookieAuthenticationMiddleware para gravar diretamente na coleção de cookies do System.Web.
app.UseCookieAuthentication(new CookieAuthenticationOptions
                                {
                                    // ...
                                    CookieManager = new SystemWebCookieManager()
                                });

Consulte a implementação do SystemWebCookieManager na documentação (link acima)

Mais informações aqui

Editar

Abaixo os passos que tomamos para resolver o problema. 1. e 2. resolveram o problema também separadamente, mas decidimos aplicar os dois por precaução:

1. Use SystemWebCookieManager

2. Defina a variável da sessão:

protected override void Initialize(RequestContext requestContext)
{
    base.Initialize(requestContext);

    // See http://stackoverflow.com/questions/20737578/asp-net-sessionid-owin-cookies-do-not-send-to-browser/
    requestContext.HttpContext.Session["FixEternalRedirectLoop"] = 1;
}

(observação: o método Initialize acima é o local lógico da correção porque base.Initialize disponibiliza a Session. No entanto, a correção também pode ser aplicada posteriormente, porque no OpenId há primeiro uma solicitação anônima, depois redireciona para o provedor OpenId e depois volta Os problemas ocorreriam após o redirecionamento de volta para o aplicativo, enquanto a correção já define a variável de sessão durante a primeira solicitação anônima, corrigindo o problema antes que ocorra qualquer redirecionamento de volta)

Editar 2

Copie e cole do projeto Katana 14-05-2016:

Adicione isso:

app.UseCookieAuthentication(new CookieAuthenticationOptions
                                {
                                    // ...
                                    CookieManager = new SystemWebCookieManager()
                                });

...e isto:

public class SystemWebCookieManager : ICookieManager
{
    public string GetRequestCookie(IOwinContext context, string key)
    {
        if (context == null)
        {
            throw new ArgumentNullException("context");
        }

        var webContext = context.Get<HttpContextBase>(typeof(HttpContextBase).FullName);
        var cookie = webContext.Request.Cookies[key];
        return cookie == null ? null : cookie.Value;
    }

    public void AppendResponseCookie(IOwinContext context, string key, string value, CookieOptions options)
    {
        if (context == null)
        {
            throw new ArgumentNullException("context");
        }
        if (options == null)
        {
            throw new ArgumentNullException("options");
        }

        var webContext = context.Get<HttpContextBase>(typeof(HttpContextBase).FullName);

        bool domainHasValue = !string.IsNullOrEmpty(options.Domain);
        bool pathHasValue = !string.IsNullOrEmpty(options.Path);
        bool expiresHasValue = options.Expires.HasValue;

        var cookie = new HttpCookie(key, value);
        if (domainHasValue)
        {
            cookie.Domain = options.Domain;
        }
        if (pathHasValue)
        {
            cookie.Path = options.Path;
        }
        if (expiresHasValue)
        {
            cookie.Expires = options.Expires.Value;
        }
        if (options.Secure)
        {
            cookie.Secure = true;
        }
        if (options.HttpOnly)
        {
            cookie.HttpOnly = true;
        }

        webContext.Response.AppendCookie(cookie);
    }

    public void DeleteCookie(IOwinContext context, string key, CookieOptions options)
    {
        if (context == null)
        {
            throw new ArgumentNullException("context");
        }
        if (options == null)
        {
            throw new ArgumentNullException("options");
        }

        AppendResponseCookie(
            context,
            key,
            string.Empty,
            new CookieOptions
            {
                Path = options.Path,
                Domain = options.Domain,
                Expires = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc),
            });
    }
}

Acho essa resposta muito mais direta e fácil de resolver o problema. Obrigado - Talvez eu tenha falado de repente. Isso não resolveu meu problema.
JCS

@JCS Incluímos as etapas que tomamos para resolver o problema. Você descobriu se seu problema estava relacionado?
Thomius

Estou usando o Web Api 2 + Owin middleware + redis cache para gerenciamento de sessões para autenticação. Tentei usar o SystemWebCookieManager e ele não resolveu o problema que estava tendo onde os cookies de autenticação não estavam sendo definidos. O uso do "UseKentorOwinCookieSaver" resolveu o problema, mas não gosto muito de uma dependência externa extra ...
JCS

Limpar a sessão funcionou para mim. Nenhuma dependência externa necessária. Coloque isso ControllerContext.HttpContext.Session.RemoveAll();em sua ExternalLogin()ação, antes de ligar ChallengeResult(). Não sei se é a melhor solução, mas é a mais simples.
Alisson

1
@chemitax, com certeza, observe que o ?.operador nulo-condicional só funciona em C # 6. #
Alisson

5

As respostas já foram fornecidas, mas no owin 3.1.0, há uma classe SystemWebChunkingCookieManager que pode ser usada.

https://github.com/aspnet/AspNetKatana/blob/dev/src/Microsoft.Owin.Host.SystemWeb/SystemWebChunkingCookieManager.cs

https://raw.githubusercontent.com/aspnet/AspNetKatana/c33569969e79afd9fb4ec2d6bdff877e376821b2/src/Microsoft.Owin.Host.SystemWeb/SystemWebChunkingCookieManager.cs

app.UseCookieAuthentication(new CookieAuthenticationOptions
{
    ...
    CookieManager = new SystemWebChunkingCookieManager()
    ...
});

Isso ainda é um problema no 3.1.0?
cyberconte

1
Sim, ainda é um problema no 3.1.0 para mim e precisava desse gerenciador de cookies, pois o padrão ainda é o ChunkingCookieManager.
jonmeyer

pode ser usado onde? e como?
22417 Simon Oneweaver

@jonmeyer thanks. Acho que ontem perdi a distinção entre o SystemCCM e o CCM, por isso vou definitivamente verificar isso #
Simon_Weaver 6/17/17

mesmo depois de adicionar a linha acima, não está funcionando para mim. Eu estou usando a versão 3.1.0. Principalmente, sou capaz de fazer login pela primeira vez, mas após o logout, isso não me permite fazer login.
Mitin Dixit

3

Se você está configurando cookies no middleware OWIN, o uso OnSendingHeadersparece contornar o problema.

Por exemplo, o uso do código abaixo owinResponseCookie2será definido, mesmo que owinResponseCookie1não seja:

private void SetCookies()
{
    var owinContext = HttpContext.GetOwinContext();
    var owinResponse = owinContext.Response;

    owinResponse.Cookies.Append("owinResponseCookie1", "value1");

    owinResponse.OnSendingHeaders(state =>
    {
        owinResponse.Cookies.Append("owinResponseCookie2", "value2");
    },
    null);

    var httpResponse = HttpContext.Response;
    httpResponse.Cookies.Remove("httpResponseCookie1");
}

3

Eu enfrentei o problema semelhante com o Visual Studio 2017 e o .net MVC 5.2.4 , atualizando o Nuget Microsoft.Owin.Security.Google para a versão mais recente, que atualmente é 4.0.1, funcionou para mim! Espero que isso ajude alguém!


1
Salvo meu bacon neste! Estava tendo um problema com o Android Chrome, perdendo especificamente a autenticação aleatoriamente. Nada mais neste segmento funcionou. Eu estou usando VS2019 e ASP MVC 5.
zfrank

2

A solução mais rápida de código de uma linha:

HttpContext.Current.Session["RunSession"] = "1";

Basta adicionar esta linha antes do método CreateIdentity:

HttpContext.Current.Session["RunSession"] = "1";
var userIdentity = userManager.CreateIdentity(user, DefaultAuthenticationTypes.ApplicationCookie);
_authenticationManager.SignIn(new AuthenticationProperties { IsPersistent = rememberLogin }, userIdentity);

1
Onde você coloca esse código HttpContext.Current.Session["RunSession"] = "1";? em Globa.asax Session_Start ?
26516 Kiquenet

1
Na verdade, é a solução mais simples e rápida disponível, e até que a solução desse problema não seja incluída no Framework (já anunciado que será) - eu, por exemplo, preferiria uma linha, em vez de uma classe + um monte de dependências . Esta solução está subestimada IMHO.
precisa

Eu adicionei-lo na minha AuthManager na parte superior do método IssueAuthToken
Alexander Trofimov

1

Eu tinha o mesmo sintoma do cabeçalho Set-Cookie não sendo enviado, mas nenhuma dessas respostas me ajudou. Tudo funcionou na minha máquina local, mas, quando implantados na produção, os cabeçalhos de conjunto de cookies nunca seriam configurados.

Acontece que foi uma combinação do uso de um personalizado CookieAuthenticationMiddlewarecom o WebApi junto com o suporte à compactação do WebApi

Felizmente eu estava usando o ELMAH no meu projeto, o que permitiu que essa exceção fosse registrada:

O System.Web.HttpException Server não pode acrescentar cabeçalho após o envio dos cabeçalhos HTTP.

O que me levou a esta edição do GitHub

Basicamente, se você tiver uma configuração estranha como a minha, desabilitará a compactação para os métodos / controladores WebApi que configuram cookies ou tente o OwinServerCompressionHandler.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.