2010-10-17 5 views
2

J'utilise DotNetOpenAuth (OpenID) et l'authentification par formulaire comme mécanisme d'authentification pour un site que je construis. Cependant, je ne suis pas satisfait des parties de la solution que j'ai trouvées et je devrais vérifier avec vous comment cela se fait habituellement. J'ai défini l'authentification par formulaire loginUrl à login.aspx. Voici le code derrière la page de connexion:DotNetOpenAuth et FormsAuthentication


public partial class Login : DataAccessPage { 
    protected void Page_Load(object sender, EventArgs e) { 
     if (Request.QueryString["dnoa.receiver"] != "openId") { 
      openId.ReturnToUrl = Request.Url.ToString(); 
      openId.LogOn(); 
     } 
    } 

    protected void openId_LoggedIn(object sender, DotNetOpenAuth.OpenId.RelyingParty.OpenIdEventArgs e) { 
     var fetch = e.Response.GetExtension(); 

     if (fetch != null) { 
      string eMail = fetch.GetAttributeValue(WellKnownAttributes.Contact.Email); 
      string name = fetch.GetAttributeValue(WellKnownAttributes.Name.FullName); 

      var usr = db.Users.SingleOrDefault(u => u.EMailAddress == eMail); 

      if (usr != null) { 
       // update the name in db if it has been changed on Google 
       if (usr.Name != name) { 
        usr.Name = name; 
        db.SaveChanges(); 
       } 

       FormsAuthentication.RedirectFromLoginPage(usr.UserId.ToString(), false); 
      } 
     } 
    } 

    protected void openId_LoggingIn(object sender, DotNetOpenAuth.OpenId.RelyingParty.OpenIdEventArgs e) { 
     var fetch = new FetchRequest(); 
     fetch.Attributes.AddRequired(WellKnownAttributes.Contact.Email); 
     fetch.Attributes.AddRequired(WellKnownAttributes.Name.FullName); 
     e.Request.AddExtension(fetch); 
    } 
} 

donc directement lorsqu'un utilisateur n'est pas connecté, il est envoyé à la login.aspx page qui tente directement de se connecter en utilisant OpenID contre Google. Il vérifie si l'utilisateur est sur la liste des utilisateurs autorisés, puis FormsAuthentication.RedirectFromLoginPage().

Jusqu'à présent, aucun problème ... le problème est à la déconnexion. Idéalement, j'aimerais que la connexion soit directement connectée au statut de connexion au compte Google. Si l'utilisateur est connecté à Google, il/elle doit également être connecté sur mon site. Lorsque l'utilisateur se déconnecte de Google, il/elle doit être déconnecté de mon site. Cependant, étant donné que l'authentification par formulaires est utilisée, le ticket durera un certain temps même si l'utilisateur se déconnecte de Google.

Quelqu'un a-t-il des idées pour résoudre ce problème?

Merci d'avance!

+0

Petite note: Google ne renvoie pas le nom complet dans WellKnownAttributes.Name.FullName. Pour obtenir le nom complet, demandez WellKnownAttributes.Name.First et WellKnownAttributes.Name.Last. – joscarsson

Répondre

6

D'abord pour répondre à votre question: OpenID ne pas fournir un moyen de lier la longueur de la session de Google à votre propre session. Le mieux que vous puissiez faire est de fournir un cookie de session (non persistant) comme vous le faites déjà, de sorte que si l'utilisateur se déconnecte de Google et ferme son navigateur, il sera également déconnecté de votre site. . C'est une limitation de protocole OpenID - aucune autre bibliothèque OpenID ne peut le réparer non plus.

Maintenant à la question que vous n'avez pas demandé, mais je ne peux pas l'ignorer - votre mise en œuvre est assez dangereuse. Vous faites implicitement confiance à l'extension de réponse AX fetch, en autorisant l'utilisateur connecté à indiquer l'adresse e-mail que l'utilisateur contrôle. Cela signifie que n'importe qui peut facilement configurer un fournisseur OpenID qui ment sur l'adresse e-mail et usurper l'identité de vos utilisateurs. Vous pouvez supposer à tort que, simplement parce que vous redirigez vos utilisateurs vers Google, cela signifie que toutes les réponses proviennent de Google (et en supposant que vous ayez confiance en Google). Ce n'est pas parce que vous envoyez une requête à Google que quelqu'un ne peut pas synthétiser une réponse de son propre serveur non-Google.

Il existe deux façons de résoudre votre problème de sécurité. D'abord (et de préférence) n'utilisez pas votre adresse e-mail comme nom d'utilisateur. Utilisez plutôt le IAuthenticationResponse.ClaimedIdentifier comme nom d'utilisateur. C'est ce qui est là pour vous, et vous protégera contre de nombreuses attaques différentes. La solution la moins préférable est de continuer à utiliser le courrier électronique, mais de vérifier que la réponse provient bien de Google avant que vous ayez confiance en ce courrier électronique. Vous pouvez le faire via la propriété IAuthenticationResponse.Provider.Uri et vérifiez que c'est celui (s) que vous attendez et en qui vous avez confiance.

+0

Ok, merci d'avoir répondu à ma question. Aussi, merci pour l'astuce sur la sécurité! J'ai défini l'URL du fournisseur sur mon adresse OpenIdTextBox to Googles (quelque chose comme http://www.google.com/o8/accounts/, ne peut pas se souvenir exactement maintenant). Comment un pirate pourrait-il changer cela? L'utilisation de IAuthenticationResponse.ClaimedIdentifier n'est pas vraiment une option pour moi, car cela signifierait que je devrais connaître cet ClaimedIdentifier avant la première connexion des utilisateurs. Comme vous pouvez le voir dans mon code, je vérifie si l'adresse e-mail retournée par Google figure dans la liste des adresses e-mail autorisées. – joscarsson

+0

Vous avez raison avec un Google claim_id, il est impossible de savoir ce que ce sera jusqu'à ce qu'ils se connectent, donc si vous avez une liste blanche d'utilisateurs autorisés à se connecter, ce n'est pas optimal. –

+0

En ce qui concerne le pirate, il n'a rien à changer sur votre page de connexion. Un OpenID Provider d'un hacker peut envoyer une réponse à votre page sans que votre page ait jamais envoyé la requête. C'est pourquoi il est important de valider que la "réponse" provient de Provider.Url que vous attendez. –