2010-03-24 20 views
10

Recibo una excepción de "La firma del mensaje era incorrecta" al intentar autenticar con MyOpenID y Yahoo.DotNetOpenAuth: La firma del mensaje fue incorrecta

estoy usando más o menos el código de ejemplo ASP.NET MVC que viene con 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(); 
} 

Trabajar bien con Google, AOL y otros. Sin embargo, Yahoo y MyOpenID caen en el caso AuthenticationStatus.Failed con la siguiente excepción:

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 

parece que otros están teniendo el mismo problema: http://trac.dotnetopenauth.net:8000/ticket/172

¿Alguien tiene alguna solución?

+0

También estoy recibiendo la misma excepción de usar el banco de pruebas DotNetOpenAuth al ejecutar esta prueba: http://test-id.org/RP/POSTAssertion.aspx –

+0

Esto parece un problema similar: http://stackoverflow.com/questions/2508327/invalid-message-signature-when-running-openid-provider-on-cluster –

Respuesta

6

Resulta que esto fue un problema con el uso de DotNetOpenAuth en un entorno de granja de servidores web.

Cuando crea su OpenIdRelyingParty, asegúrese de pasar null en el constructor.

Esto coloca su sitio web en el modo sin estado o "tonto" de OpenID. Es un poco más lento para los usuarios iniciar sesión (si lo notan) pero evita tener que escribir un IRelyingPartyApplicationStore para permitir que DotNetOpenAuth funcione en toda la granja;

var openIdRelyingParty = new OpenIdRelyingParty(null); 
+2

sospecho que esto puede introducir vulnerabilidades de seguridad sin embargo. ¿Alguien puede confirmar? –

4

Hemos arreglado este problema mediante la implementación de IRelyingPartyApplicationStore (IOpenIdApplicationStore en nuevas versiones de DotNetOpenAuth) y añadiendo el nombre de la clase a la tienda de .config

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

La interfaz es una composición de otras dos interfaces con cinco miembros todos juntos.

/// <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 
{ 
} 

Se utilizó el modo mudo como una solución rápida para levantarse de una carrera, pero al final es probable que desee algo como esto.

5

Toda esta discusión gira en torno a la siguiente pregunta:

¿Cómo de confianza (RP) asegúrese de que la solicitud que contiene el token de autenticación viene de la OP (OpenID Provider) a la que se remitió el la solicitud del usuario a?

Los siguientes pasos explican cómo sucede

  1. Solicitud usuario llega al partido que responden (RP), nuestro sitio web en nuestro caso
  2. aplicación almacena una firma única que corresponde a este usuario en una firma local, tienda (LSS) y luego incorpore esta firma en el mensaje y envía este mensaje a OpenID Provider (OP)
  3. usuario escribe sus credenciales y el PO autentica su mensaje y luego reenvía este mensaje que tiene la firma todavía incrustado en él, volver a RP
  4. RP comparar la firma que está incrustado en el mensaje a la firma que se encuentra en la LSS y si coinciden RP autenticar al usuario

Si la LSS se desvanece (de alguna manera) antes de que el mensaje se vuelve de OP existe nada para RP para comparar la firma con lo que no puede autenticar al usuario y arroja un error: la firma del mensaje fue incorrecta.

¿Cómo puede LSS Vanish:

  1. ASP.net refresca el grupo de aplicaciones
  2. se reinicie IIS
  3. En la granja de servidores web mensaje es servida por aplicación alojada en un servidor diferente

Dos soluciones a este problema:

  1. RP run en modo mudo

    a. No almacena ni firma localmente, por lo que no utiliza la comparación de firmas para asegurarse de que el mensaje proviene del OP al que reenvió al usuario para la autenticación

    b. En cambio, una vez que RP recibió el mensaje de autenticación de la OP, envíe el mensaje nuevamente a OP y pídale que verifique si él es el que ha autenticado a este usuario y es el creador del mensaje. Si OP responde Sí, soy el autor de este Mensaje y he creado este mensaje, entonces el usuario es autenticado por RP

  2. Implemente su propio almacén de persistencia que no desaparezca, no importa lo que ASP.net haga con el proceso, muy parecido a usar SQL para almacenar el estado de la sesión.

Cuestiones relacionadas