Les cookies ASP.NET_SessionId + OWIN ne sont pas envoyés au navigateur

145

J'ai un problème étrange avec l'utilisation de l'authentification par cookie Owin.

Lorsque je démarre mon authentification de serveur IIS fonctionne parfaitement bien sur IE / Firefox et Chrome.

J'ai commencé à faire des tests avec l'authentification et à me connecter sur différentes plates-formes et j'ai rencontré une erreur étrange. Sporadiquement, le framework Owin / IIS n'envoie tout simplement aucun cookie aux navigateurs. Je vais taper un nom d'utilisateur et un mot de passe qui sont corrects, le code s'exécute mais aucun cookie n'est livré au navigateur du tout. Si je redémarre le serveur, il commence à fonctionner, à un moment donné, j'essaierai de me connecter et à nouveau les cookies cesseront d'être livrés. Parcourir le code ne fait rien et ne génère aucune erreur.

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

Et dans ma procédure de connexion, j'ai le code suivant:

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

Mise à jour 1: Il semble qu'une des causes du problème soit lorsque j'ajoute des éléments à la session, les problèmes commencent. L'ajout de quelque chose de simple comme Session.Content["ABC"]= 123semble créer le problème.

Ce que je peux faire est le suivant: 1) (Chrome) Lorsque je me connecte, j'obtiens ASP.NET_SessionId + mon cookie d'authentification. 2) Je vais sur une page qui définit une session.contenu ... 3) Ouvrez un nouveau navigateur (Firefox) et essayez de vous connecter et il ne reçoit pas d'ASP.NET_SessionId ni de cookie d'authentification 4) Alors que le premier navigateur a le ASP.NET_SessionId il continue de fonctionner. La minute où je supprime ce cookie, il a le même problème que tous les autres navigateurs sur lesquels je travaille sur IP address (10.xxx) et localhost.

Mise à jour 2: Forcer la création du ASPNET_SessionIdpremier sur ma page login_load avant l'authentification avec OWIN.

1) avant de m'authentifier avec OWIN, je crée une Session.Contentvaleur aléatoire sur ma page de connexion pour démarrer ASP.NET_SessionId 2) puis je m'authentifie et je fais d'autres sessions 3) D'autres navigateurs semblent maintenant fonctionner

C'est bizarre. Je ne peux que conclure que cela a quelque chose à voir avec ASP et OWIN pensant qu'ils sont dans des domaines différents ou quelque chose du genre.

Mise à jour 3 - Comportement étrange entre les deux.

Comportement étrange supplémentaire identifié - Le délai d'expiration de la session Owin et ASP est différent. Ce que je vois, c'est que mes sessions Owin restent actives plus longtemps que mes sessions ASP grâce à un mécanisme. Donc lors de la connexion: 1.) J'ai une session d'authentification basée sur cookied 2.) J'ai défini quelques variables de session

Mes variables de session (2) "meurent" avant que la variable de session du cookie owin force la reconnexion, ce qui provoque un comportement inattendu dans toute mon application. (La personne est connectée mais n'est pas vraiment connectée)

Mise à jour 3B

Après quelques recherches, j'ai vu quelques commentaires sur une page indiquant que le délai d'expiration de l'authentification des «formulaires» et celui de la session doivent correspondre. Je pense que normalement les deux sont synchronisés mais pour une raison quelconque, les deux ne sont pas synchronisés.

Résumé des solutions de contournement

1) Créez toujours une session avant l'authentification. En gros, créez une session lorsque vous démarrez l'applicationSession["Workaround"] = 0;

2) [Expérimental] si vous persistez les cookies, assurez-vous que votre délai d'expiration / durée OWIN est plus long que votre sessionTimeout dans votre web.config (en test)

Piotr Stulinski
la source
1
Peut confirmer que l'ajout d'un appel de session à ActionResult Login et ActionResult ExternalLogin a résolu ce problème. Je suis sûr qu'un seul est nécessaire, mais j'ai les deux en place.
Scott
Merci! ... L'ajout d'une session dans ExternalLogin l'a corrigé pour moi ... c'est de la magie vaudou ... j'ai déjà perdu 6 heures à traquer ce problème ..
xdev

Réponses:

159

J'ai rencontré le même problème et j'ai retracé la cause de l'implémentation de l'hébergement OWIN ASP.NET. Je dirais que c'est un bug.

Un peu de contexte

Mes résultats sont basés sur ces versions d'assemblage:

  • Microsoft.Owin, Version = 2.0.2.0, Culture = neutre, PublicKeyToken = 31bf3856ad364e35
  • Microsoft.Owin.Host.SystemWeb, Version = 2.0.2.0, Culture = neutre, PublicKeyToken = 31bf3856ad364e35
  • System.Web, Version = 4.0.0.0, Culture = neutre, PublicKeyToken = b03f5f7f11d50a3a

OWIN utilise sa propre abstraction pour travailler avec les cookies de réponse ( Microsoft.Owin.ResponseCookieCollection ). Cette implémentation encapsule directement la collection d'en-têtes de réponse et met à jour en conséquence l'en - tête Set-Cookie . L'hôte OWIN ASP.NET ( Microsoft.Owin.Host.SystemWeb ) enveloppe simplement System.Web.HttpResponse et sa collection d'en-têtes. Ainsi, lorsqu'un nouveau cookie est créé via OWIN, l'en - tête Set-Cookie de la réponse est modifié directement.

Mais ASP.NET utilise également sa propre abstraction pour travailler avec les cookies de réponse. Cela nous est exposé en tant que propriété System.Web.HttpResponse.Cookies et implémenté par la classe scellée System.Web.HttpCookieCollection . Cette implémentation n'enveloppe pas directement l'en - tête Set-Cookie de la réponse, mais utilise certaines optimisations et une poignée de notifications internes pour manifester son changement d'état en objet de réponse.

Ensuite, il y a un point tardif dans la durée de vie de la demande où l' état modifié de HttpCookieCollection est testé ( System.Web.HttpResponse.GenerateResponseHeadersForCookies () ) et les cookies sont sérialisés dans l'en - tête Set-Cookie . Si cette collection est dans un état spécifique, tout l'en-tête Set-Cookie est d'abord effacé et recréé à partir des cookies stockés dans la collection.

L'implémentation de session ASP.NET utilise la propriété System.Web.HttpResponse.Cookies pour stocker son cookie ASP.NET_SessionId. Il existe également une optimisation de base dans le module d'état de session ASP.NET ( System.Web.SessionState.SessionStateModule ) implémenté via la propriété statique nommée s_sessionEverSet qui est assez explicite. Si jamais vous stockez quelque chose à l'état de session dans votre application, ce module fera un peu plus de travail pour chaque demande.


Retour à notre problème de connexion

Avec toutes ces pièces, vos scénarios peuvent être expliqués.

Cas 1 - La session n'a jamais été définie

System.Web.SessionState.SessionStateModule , la propriété s_sessionEverSet est false. Aucun identifiant de session n'est généré par le module d'état de session et l' état de la collection System.Web.HttpResponse.Cookies n'est pas détecté comme modifié . Dans ce cas, les cookies OWIN sont correctement envoyés au navigateur et la connexion fonctionne.

Cas 2 - La session a été utilisée quelque part dans l'application, mais pas avant que l'utilisateur tente de s'authentifier

System.Web.SessionState.SessionStateModule , la propriété s_sessionEverSet est true. Les identifiants de session sont générés par SessionStateModule , ASP.NET_SessionId est ajouté à la collection System.Web.HttpResponse.Cookies mais il est supprimé plus tard dans la durée de vie de la demande car la session de l'utilisateur est en fait vide. Dans ce cas, l' état de la collection System.Web.HttpResponse.Cookies est détecté comme modifié et l'en - tête Set-Cookie est d'abord effacé avant que les cookies ne soient sérialisés en valeur d'en-tête.

Dans ce cas, les cookies de réponse OWIN sont «perdus» et l'utilisateur n'est pas authentifié et est redirigé vers la page de connexion.

Cas 3 - La session est utilisée avant que l'utilisateur tente de s'authentifier

System.Web.SessionState.SessionStateModule , la propriété s_sessionEverSet est true. Les identifiants de session sont générés par SessionStateModule , ASP.NET_SessionId est ajouté à System.Web.HttpResponse.Cookies . En raison de l'optimisation interne dans System.Web.HttpCookieCollection et System.Web.HttpResponse.GenerateResponseHeadersForCookies () L'en-tête Set-Cookie n'est PAS d'abord effacé mais seulement mis à jour.

Dans ce cas, les cookies d'authentification OWIN et le cookie ASP.NET_SessionId sont envoyés en réponse et la connexion fonctionne.


Problème plus général avec les cookies

Comme vous pouvez le voir, le problème est plus général et ne se limite pas à la session ASP.NET. Si vous hébergez OWIN via Microsoft.Owin.Host.SystemWeb et que vous utilisez directement la collection System.Web.HttpResponse.Cookies , vous courez un risque.

Par exemple, cela fonctionne et les deux cookies sont correctement envoyés au navigateur ...

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

    return View();
}

Mais ce n'est pas le cas et OwinCookie est "perdu" ...

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

    return View();
}

Tous deux testés à partir de VS2013, IISExpress et le modèle de projet MVC par défaut.

Tomas Dolezal
la source
7
J'ai passé quelques jours à essayer de déboguer et de résoudre ce problème dans notre environnement de test. La seule solution de contournement que j'ai trouvée est la même que celle que vous avez suggérée (définir la session avant que l'utilisateur ne s'authentifie). J'ai signalé le problème à katanaproject ... katanaproject.codeplex.com/workitem/197 , alors peut-être que quelqu'un commentera là-bas.
Tomas Dolezal
11
C'est un défaut assez grave, d'autant plus qu'ils ont intégré le modèle pour vs2013.
Piotr Stulinski le
2
Pour tous ceux qui souhaitent approfondir cette question, j'ai créé un projet de test sur github.com/Neilski/IdentityBugDemo
Neilski
1
Rencontrer ce problème en raison de l'utilisation de Controller.TempData qui utilise Session comme magasin de stockage. Peut facilement reproduire l'incapacité de se connecter si un cookie ASP_NET.SessionId n'existe pas à partir d'une demande précédente.
kingdango
2
Finalement! Quel étrange problème c'est. Je vous remercie. C'est toujours un problème plus de deux ans après la rédaction de cette réponse.
Spivonious
43

En commençant par l'excellente analyse de @TomasDolezal, j'ai jeté un coup d'œil à la source Owin et System.Web.

Le problème est que System.Web a sa propre source principale d'informations sur les cookies et ce n'est pas l'en-tête Set-Cookie. Owin ne connaît que l'en-tête Set-Cookie. Une solution de contournement consiste à vous assurer que tous les cookies définis par Owin sont également définis dans la HttpContext.Current.Response.Cookiescollection.

J'ai créé un petit middleware ( source , nuget ) qui fait exactement cela, qui est destiné à être placé immédiatement au-dessus de l'enregistrement du middleware de cookie.

app.UseKentorOwinCookieSaver();

app.UseCookieAuthentication(new CookieAuthenticationOptions());
Anders Abel
la source
1
Je vais essayer. Depuis asp.net Identity 2.2.0-alpha1, j'ai commencé à avoir des problèmes non seulement lors de la connexion mais aussi lors de la déconnexion de l'utilisateur (l'utilisateur ne se déconnectera pas lors de la déconnexion, cliquez | généralement, au cas où je laisserais le site Web ouvert pendant un certain temps sans rien faire |) .. Et après avoir défini une session juste avant que l'utilisateur ne se connecte, le problème de connexion a résolu le problème de connexion, mais le problème de déconnexion persiste .. Merci pour vos efforts .. Au fait, y a-t-il quelque chose que je devrais faire sauf l'installation de le paquet?
wooer
Vous devez l'activer avec app.UseKentorCookieMiddlewareSaver();dans Startup.Auth.cs. Il devrait également gérer la suppression des cookies de déconnexion.
Anders Abel
Merci beaucoup Anders Abel, la connexion et la déconnexion fonctionnent bien maintenant. Mais le code dans le commentaire ci-dessus doit être modifié (car je l'ai suivi :) sans succès) pour être: app.UseKentorOwinCookieSaver()et peut-être inclus dans votre réponse d'origine comme dans la page GitHub du package .
wooer
1
Merci d'avoir remarqué le mauvais document. C'est en fait déjà corrigé sur la page GitHub, mais j'ai également mis à jour ma réponse ici maintenant.
Anders Abel
@AndersAbel J'essaie d'ajouter des inscriptions Meetup pour ce projet github: github.com/owin-middleware/OwinOAuthProviders ''. J'ai ajouté Asana l'autre jour et je n'ai eu aucun problème, mais pour une raison quelconque, avec Meetup, la méthode await AuthenticationManager.GetExternalLoginInfoAsync () dans Account // ExternalLoginCallback renvoie null. Malheureusement, votre package NuGet n'a pas résolu mon problème. Je me demandais si vous aviez le temps de passer en revue avec moi, car vous pourrez peut-être mieux résoudre le problème et pousser votre projet.
Anthony Ruffino
42

En bref, le gestionnaire de cookies .NET l'emportera sur le gestionnaire de cookies OWIN et écrasera les cookies définis sur la couche OWIN . Le correctif consiste à utiliser la classe SystemWebCookieManager, fournie comme solution sur le projet Katana ici . Vous devez utiliser cette classe ou une classe similaire, ce qui forcera OWIN à utiliser le gestionnaire de cookies .NET afin qu'il n'y ait pas d'incohérences :

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

Au démarrage de votre application, attribuez-le simplement lorsque vous créez vos dépendances OWIN:

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

Une réponse similaire a été fournie ici mais elle n'inclut pas toute la base de code requise pour résoudre le problème, je vois donc le besoin de l'ajouter ici car le lien externe vers le projet Katana peut tomber et cela devrait être entièrement relaté comme solution ici aussi.

Alexandru
la source
merci, ça marche moi, mais aussi j'efface toute la session en appelant ce ControllerContext.HttpContext.Session.RemoveAll (); dans la fonction externallogincallback
adnan
S'applique à ASP.NET Webforms 4.6.1 ? Mon application web utiliseASP.NET Webforms, OWIN, ADFS
Kiquenet
@Kiquenet Votre application Web utilise-t-elle des cookies OWIN? Alors oui.
Alexandru
Dans le code, Startup.ConfigureAuthnous avons app.UseCookieAuthenticationet app.UseWsFederationAuthenticationenfin app.UseStageMarker
Kiquenet
@Alexandru Vous pourriez envisager une modification, mon équipe a rencontré ce bug et c'était rare et aléatoire, il nous était caché via les environnements DEV et UAT. Cette citation de votre réponse ne tenait pas pour nous: "Le gestionnaire de cookies .NET gagnera toujours." Ce serait facile à trouver et à corriger, si les cookies OWIN étaient toujours écrasés, aucun de nos middleware OIDC ne l'aurait fait hors de nos postes de travail de développement. Mais le caractère aléatoire signifiait que le bogue a atteint la production pendant 2 jours avant de nous atteindre à grande échelle (la moitié de nos utilisateurs internes ne pouvaient pas se connecter via AAD). Ça vous dérange si je supprime le mot «toujours» de votre réponse?
yzorg
17

L'équipe Katana a répondu au problème soulevé par Tomas Dolezar et a publié de la documentation sur les solutions de contournement :

Les solutions de contournement se divisent en deux catégories. La première consiste à reconfigurer System.Web afin d'éviter d'utiliser la collection Response.Cookies et d'écraser les cookies OWIN. L'autre approche consiste à reconfigurer les composants OWIN affectés afin qu'ils écrivent des cookies directement dans la collection Response.Cookies de System.Web.

  • Assurez-vous que la session est établie avant l'authentification: le conflit entre les cookies System.Web et Katana est par demande, il peut donc être possible pour l'application d'établir la session sur une demande avant le flux d'authentification. Cela devrait être facile à faire lorsque l'utilisateur arrive pour la première fois, mais il peut être plus difficile de garantir plus tard lorsque les cookies de session ou d'authentification expirent et / ou doivent être actualisés.
  • Désactiver le SessionStateModule - Si l'application ne s'appuie pas sur les informations de session, mais que le module de session définit toujours un cookie qui provoque le conflit ci-dessus, vous pouvez envisager de désactiver le module d'état de session.
  • Reconfigurez le CookieAuthenticationMiddleware pour écrire directement dans la collection de cookies de System.Web.
app.UseCookieAuthentication(new CookieAuthenticationOptions
                                {
                                    // ...
                                    CookieManager = new SystemWebCookieManager()
                                });

Voir l'implémentation de SystemWebCookieManager dans la documentation (lien ci-dessus)

Plus d'informations ici

Éditer

Ci-dessous les étapes que nous avons suivies pour résoudre le problème. 1. et 2. ont résolu le problème séparément, mais nous avons décidé d'appliquer les deux au cas où:

1. Utilisez SystemWebCookieManager

2. Définissez la variable de session:

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

(note latérale: la méthode Initialize ci-dessus est l'endroit logique pour le correctif car base.Initialize rend la session disponible. Cependant, le correctif pourrait également être appliqué plus tard car dans OpenId il y a d'abord une requête anonyme, puis rediriger vers le fournisseur OpenId, puis revenir Les problèmes se produiraient après la redirection vers l'application alors que le correctif définit la variable de session déjà lors de la première demande anonyme, résolvant ainsi le problème avant même qu'une redirection ne se produise)

Modifier 2

Copiez-collez du projet Katana 14/05/2016:

Ajoute ça:

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

...et ça:

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),
            });
    }
}
thomius
la source
Je trouve cette réponse beaucoup plus simple et plus facile à résoudre le problème. Merci, - Peut-être que j'ai parlé trop soudainement. Cela n'a pas résolu mon problème.
JCS
@JCS Inclus les étapes que nous avons prises pour résoudre le problème. Avez-vous découvert si votre problème était lié?
thomius
J'utilise Web Api 2 + middleware Owin + cache redis pour la gestion de session pour l'authentification. J'ai essayé d'utiliser SystemWebCookieManager et cela n'a pas résolu le problème que j'avais où les cookies d'authentification n'étaient pas définis. L'utilisation de "UseKentorOwinCookieSaver" l'a résolu mais je ne suis pas trop friand d'une dépendance externe supplémentaire ...
JCS
Effacer la session a fonctionné pour moi. Aucune dépendance externe nécessaire. Mettez cela ControllerContext.HttpContext.Session.RemoveAll();dans votre ExternalLogin()action, avant d'appeler ChallengeResult(). Je ne sais pas si c'est la meilleure solution, mais c'est la plus simple.
Alisson
1
@chemitaxis bien sûr, prenez simplement note que ?.(l'opérateur conditionnel nul) ne fonctionne qu'en C # 6.
Alisson
5

Des réponses ont déjà été fournies, mais dans owin 3.1.0, il existe une classe SystemWebChunkingCookieManager qui peut être utilisée.

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()
    ...
});
Jonmeyer
la source
Est-ce toujours un problème dans la version 3.1.0?
cyberconte
1
Oui, c'est toujours un problème dans la version 3.1.0 pour moi et j'avais besoin de ce gestionnaire de cookies, car le gestionnaire par défaut est toujours ChunkingCookieManager.
jonmeyer
peut être utilisé où? et comment?
Simon_Weaver
@jonmeyer merci. Je pense qu'hier j'ai manqué la distinction entre SystemCCM et CCM, donc je vais certainement vérifier cela
Simon_Weaver
même après avoir ajouté la ligne ci-dessus, cela ne fonctionne pas pour moi. J'utilise la version 3.1.0. Je peux principalement me connecter pour la première fois, mais après la déconnexion, cela ne me permet pas de me connecter.
Mitin Dixit du
3

Si vous définissez vous-même des cookies dans le middleware OWIN, utilisez OnSendingHeaders semble contourner le problème.

Par exemple, l'utilisation du code ci owinResponseCookie2- dessous sera définie, même si ce owinResponseCookie1n'est pas le cas:

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");
}
Appetere
la source
3

J'ai rencontré le problème similaire avec Visual Studio 2017 et .net MVC 5.2.4 , la mise à jour de Nuget Microsoft.Owin.Security.Google vers la dernière version qui est actuellement 4.0.1 a fonctionné pour moi! J'espère que cela aide quelqu'un!

Ikram Shah
la source
1
J'ai sauvé mon bacon sur celui-ci! Avait un problème avec Android Chrome perdant spécifiquement l'authentification au hasard. Rien d'autre dans ce fil n'a fonctionné. J'utilise VS2019 et ASP MVC 5.
zfrank
2

La solution de code en une ligne la plus rapide:

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

Ajoutez simplement cette ligne avant la méthode CreateIdentity:

HttpContext.Current.Session["RunSession"] = "1";
var userIdentity = userManager.CreateIdentity(user, DefaultAuthenticationTypes.ApplicationCookie);
_authenticationManager.SignIn(new AuthenticationProperties { IsPersistent = rememberLogin }, userIdentity);
Alexandre Trofimov
la source
1
Où avez-vous mis ce code HttpContext.Current.Session["RunSession"] = "1";? dans Globa.asax Session_Start ?
Kiquenet
1
C'est en fait la solution la plus simple et la plus rapide disponible, et jusqu'à ce que la solution de ce problème ne soit pas incluse dans le Framework (déjà annoncé qu'elle le fera) - je préférerais, par exemple, une seule ligne, au lieu d'une classe + un tas de dépendances . Cette solution est sous-estimée à mon humble avis.
Der Zinger
Je l'ai ajouté dans mon AuthManager en haut de la méthode IssueAuthToken
Alexander Trofimov
1

J'ai eu le même symptôme que l'en-tête Set-Cookie n'était pas envoyé mais aucune de ces réponses ne m'a aidé. Tout fonctionnait sur ma machine locale, mais une fois déployé en production, les en-têtes de cookies définis ne seraient jamais définis.

Il s'avère que c'était une combinaison de l'utilisation d'un personnalisé CookieAuthenticationMiddlewareavec WebApi et de la prise en charge de la compression WebApi

Heureusement, j'utilisais ELMAH dans mon projet, ce qui m'a permis de consigner cette exception:

System.Web.HttpException Server ne peut pas ajouter d'en-tête après l'envoi des en-têtes HTTP.

Ce qui m'a conduit à ça problème GitHub

Fondamentalement, si vous avez une configuration étrange comme la mienne, vous voudrez désactiver la compression pour vos contrôleurs / méthodes WebApi qui définissent les cookies, ou essayez le OwinServerCompressionHandler.

Hugh Jeffner
la source