2010-03-24 3 views
10

Je reçois une exception "La signature du message était incorrecte" lors de la tentative d'authentification avec MyOpenID et Yahoo.DotNetOpenAuth: la signature du message était incorrecte

J'utilise à peu près l'exemple de code ASP.NET MVC fourni avec DotNetOpenAuth 3.4.2

public ActionResult Authenticate(string openid) 
{ 
    var openIdRelyingParty = new OpenIdRelyingParty(); 
    var authenticationResponse = openIdRelyingParty.GetResponse(); 

    if (authenticationResponse == null) 
    { 
     // Stage 2: User submitting identifier 
     Identifier identifier; 

     if (Identifier.TryParse(openid, out identifier)) 
     { 
      var realm = new Realm(Request.Url.Root() + "openid"); 
      var authenticationRequest = openIdRelyingParty.CreateRequest(openid, realm); 
      authenticationRequest.RedirectToProvider(); 
     } 
     else 
     { 
      return RedirectToAction("login", "home"); 
     } 
    } 
    else 
    { 
     // Stage 3: OpenID provider sending assertion response 
     switch (authenticationResponse.Status) 
     { 
      case AuthenticationStatus.Authenticated: 
      { 
       // TODO 
      } 
      case AuthenticationStatus.Failed: 
      { 
       throw authenticationResponse.Exception; 
      } 
     } 
    } 

    return new EmptyResult(); 
} 

fonctionne bien avec Google, AOL et d'autres. Cependant, Yahoo et MyOpenID tombent dans le cas AuthenticationStatus.Failed à l'exception suivante:

DotNetOpenAuth.Messaging.Bindings.InvalidSignatureException: Message signature was incorrect. 
    at DotNetOpenAuth.OpenId.ChannelElements.SigningBindingElement.ProcessIncomingMessage(IProtocolMessage message) in c:\Users\andarno\git\dotnetopenid\src\DotNetOpenAuth\OpenId\ChannelElements\SigningBindingElement.cs:line 139 
    at DotNetOpenAuth.Messaging.Channel.ProcessIncomingMessage(IProtocolMessage message) in c:\Users\andarno\git\dotnetopenid\src\DotNetOpenAuth\Messaging\Channel.cs:line 992 
    at DotNetOpenAuth.OpenId.ChannelElements.OpenIdChannel.ProcessIncomingMessage(IProtocolMessage message) in c:\Users\andarno\git\dotnetopenid\src\DotNetOpenAuth\OpenId\ChannelElements\OpenIdChannel.cs:line 172 
    at DotNetOpenAuth.Messaging.Channel.ReadFromRequest(HttpRequestInfo httpRequest) in c:\Users\andarno\git\dotnetopenid\src\DotNetOpenAuth\Messaging\Channel.cs:line 386 
    at DotNetOpenAuth.OpenId.RelyingParty.OpenIdRelyingParty.GetResponse(HttpRequestInfo httpRequestInfo) in c:\Users\andarno\git\dotnetopenid\src\DotNetOpenAuth\OpenId\RelyingParty\OpenIdRelyingParty.cs:line 540 

semble que d'autres ont le même problème: http://trac.dotnetopenauth.net:8000/ticket/172

Quelqu'un at-il une solution de contournement?

+0

Je suis aussi obtenir la même exception en utilisant le banc d'essai DotNetOpenAuth lors de l'exécution de ce test: http://test-id.org/RP/POSTAssertion.aspx –

+0

Cela ressemble à un problème similaire: http://stackoverflow.com/questions/2508327/invalid-message-signature-when-running-openid-provider-on-cluster –

Répondre

6

Il s'avère que cela a été un problème avec l'utilisation de DotNetOpenAuth dans un environnement de batterie de serveurs Web. Lorsque vous créez votre OpenIdRelyingParty assurez-vous que vous passez null dans le constructeur

Cela met votre site Web en mode sans état OpenID ou «bête». Il est légèrement plus lent pour les utilisateurs de se connecter (même si vous le remarquez), mais vous évitez d'avoir à écrire un IRelyingPartyApplicationStore pour permettre à DotNetOpenAuth de fonctionner sur votre batterie;

var openIdRelyingParty = new OpenIdRelyingParty(null); 
+2

Je soupçonne que cela peut introduire des failles de sécurité. Quelqu'un peut-il confirmer? –

4

Nous résolu ce problème en mettant en place IRelyingPartyApplicationStore (IOpenIdApplicationStore dans les versions les plus récentes de DotNetOpenAuth) et en ajoutant le nom de classe magasin au .config

<dotNetOpenAuth> 
    <openid ...> 
    <relyingParty> 
     ... 
     <store type="some.name.space.MyRelyingPartyApplicationStore, some.assembly"/> 
    </relyingParty> 
    </openid> 
    ... 
</dotNetOpenAuth> 

L'interface est une composition de deux autres interfaces avec cinq membres tous ensemble.

/// <summary> 
/// A hybrid of the store interfaces that an OpenID Provider must implement, and 
/// an OpenID Relying Party may implement to operate in stateful (smart) mode. 
/// </summary> 
public interface IOpenIdApplicationStore : ICryptoKeyStore, INonceStore 
{ 
} 

Nous avons utilisé le mode muet comme une solution rapide pour se lever d'une course, mais à la fin vous aurez probablement envie quelque chose comme ça.

5

Toute cette discussion tourne autour de la question suivante:

Comment ne partie utilisatrice (RP) assurez-vous que la demande contenant le jeton d'authentification provient de l'OP (OpenId Provider) auquel il a transmis la demande de l'utilisateur à?

Les étapes suivantes explique comment il arrive

  1. Demande de l'utilisateur vient au Parti Replying (RP), notre site dans notre cas
  2. application stocke une signature unique correspondant à cet utilisateur dans une signature locale stocker (LSS) et puis incorpore cette signature dans le message et transmettre ce message au fournisseur OpenId (OP)
  3. L'utilisateur tape ses informations d'identification et l'OP authentifie son message, puis transmet ce message, qui a encore la signature incorporée, retour au RP
  4. RP comparer la signature qui est inclus dans le message à la signature qui est en LSS et si elles correspondent à authentifier RP l'utilisateur

Si la LSS disparaît (en quelque sorte) avant que le message revient de OP il y a Rien pour que RP ne compare la signature avec ce qu'il ne parvient pas à authentifier l'utilisateur et lance une erreur: La signature du message était incorrecte.

Comment LSS Vanish:

  1. ASP.net rafraichit le pool d'applications
  2. IIS est redémarré
  3. Dans la ferme Web du message est servi par application hébergée sur un serveur différent

Deux solutions à ce problème:

  1. Exécution de RP en mode bourdonnement

    a. Il ne stocke pas et ne signe pas localement et n'utilise donc pas la comparaison de signature pour s'assurer que le message provient de l'OP auquel il a envoyé l'utilisateur pour l'authentification

    b. Au lieu de cela, une fois que RP a reçu le message d'authentification de l'OP, il renvoie le message à OP et lui demande de vérifier s'il est celui qui a authentifié cet utilisateur et est l'expéditeur du message. Si OP répond Oui, je suis l'initiateur de ce message et j'ai créé ce message puis l'utilisateur est authentifié par RP

  2. Implémentez votre propre magasin de persistance qui ne disparaît pas, peu importe ce que ASP.net fait pour le processus, un peu comme utiliser SQL pour stocker l'état de la session.

Questions connexes