12
Oct
0

ASP.Net Membership: signout fail ?

Chère Mme Michu, veuillez m’excuser pour ce billet technique qui, je pense, ne vous intéressera pas. Enfin sauf si vous codez régulièrement en .Net. Sait-t-on jamais ?! 🙂

Suite à un billet de Toy Hunt sur le mécanisme d’authentification “Membership provider” apparu dans la version 2.0 du framework .Net, je me suis souvenu d’un problème rencontré il y a quelques mois chez un client utilisant cette solution.

Pour les non initiés le “Membership provider” est une solution décrite par Microsoft comme permettant d’implémenter rapidement et facilement un mécanisme d’authentification sûr sans avoir à réinventer la roue.

Pour ceux que cela intéresse je me permet d’intégrer la vidéo de présentation de Troy:
[youtube]http://www.youtube.com/watch?v=_2O5u9ZDzuM[/youtube]

Personnellement je trouvais ça pas mal du tout: requêtes préparées, mots de passe stockés hashés SHA-1 avec du sel, procédure de changement de mot de passe en option…

Sauf qu’il y a un couac: le mécanisme de déconnexion ne tue pas la session coté serveur mais se contente de détruire le cookie dans le navigateur… qu’il suffit alors de remettre en place pour que la session soit réactivée pendant une certaine durée (le time to live de la session paramétré dans le web.config).

Bon alors pour une techno annoncée comme sécurisée on a vu mieux… Mais pire encore, le problème est connu et documenté par Microsoft (ce qui laisse entendre que pour eux, tout ceci est normal) et la solution proposée est d’utiliser SSL et / ou de réduire le time to live de la session à 10 minutes…

Non la Microsoft tu te fous VRAIMENT de nous ! Comment justifier le fait de ne pas tuer la session coté serveur ? Mystère… D’ailleurs si quelqu’un a une explication je suis preneur !

Quoi qu’il en soit, voici une solution (oui “une” pas “la” 🙂 ) pour “patcher” ce comportement à la con:

Premièrement on créé lors de la connexion une variable dans la session utilisateur coté serveur:

if (MyProvider.ValidateUser(username, password))
{
  Session["SignoutFailPatch"] = 1;
  FormsAuthentication.RedirectFromLoginPage(username, true);
}

 

On prend soin de la supprimer lors de la déconnexion:

protected void QuitButton_Click(object sender, ImageClickEventArgs e)
{
  Session.RemoveAll();
  FormsAuthentication.SignOut();
  FormsAuthentication.RedirectToLoginPage();
}

 

Et on créé une Master Page afin de vérifier à chaque chargement de page nécessitant une authentification que la variable est bien présente (ne pas oublier de faire hériter les pages concernées de la Master Page :)):

protected void Page_Load(object sender, EventArgs e)
{
  if (Session["SignoutFailPatch"] == null)
  {
    Session.RemoveAll();
    FormsAuthentication.SignOut();
    FormsAuthentication.RedirectToLoginPage();
  }
}

 
Il faut tout faire soit même… 😛
 

Heat Miser

Commenter




Celadon theme by the Themes Boutique