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"]= 123
semble 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_SessionId
premier sur ma page login_load avant l'authentification avec OWIN.
1) avant de m'authentifier avec OWIN, je crée une Session.Content
valeur 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)
la source
Réponses:
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:
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 ...
Mais ce n'est pas le cas et OwinCookie est "perdu" ...
Tous deux testés à partir de VS2013, IISExpress et le modèle de projet MVC par défaut.
la source
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.Cookies
collection.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.
la source
app.UseKentorCookieMiddlewareSaver();
dans Startup.Auth.cs. Il devrait également gérer la suppression des cookies de déconnexion.app.UseKentorOwinCookieSaver()
et peut-être inclus dans votre réponse d'origine comme dans la page GitHub du package .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 :
Au démarrage de votre application, attribuez-le simplement lorsque vous créez vos dépendances OWIN:
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.
la source
ASP.NET Webforms, OWIN, ADFS
Startup.ConfigureAuth
nous avonsapp.UseCookieAuthentication
etapp.UseWsFederationAuthentication
enfinapp.UseStageMarker
L'équipe Katana a répondu au problème soulevé par Tomas Dolezar et a publié de la documentation sur les solutions de contournement :
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:
(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:
...et ça:
la source
ControllerContext.HttpContext.Session.RemoveAll();
dans votreExternalLogin()
action, avant d'appelerChallengeResult()
. Je ne sais pas si c'est la meilleure solution, mais c'est la plus simple.?.
(l'opérateur conditionnel nul) ne fonctionne qu'en C # 6.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
la source
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 ceowinResponseCookie1
n'est pas le cas:la source
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!
la source
La solution de code en une ligne la plus rapide:
Ajoutez simplement cette ligne avant la méthode CreateIdentity:
la source
HttpContext.Current.Session["RunSession"] = "1";
? dans Globa.asaxSession_Start
?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é
CookieAuthenticationMiddleware
avec WebApi et de la prise en charge de la compression WebApiHeureusement, j'utilisais ELMAH dans mon projet, ce qui m'a permis de consigner cette exception:
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
.la source