Pergunta

Estou recebendo uma exceção "assinatura da mensagem estava incorreta" ao tentar autenticar com miopenid e yahoo.

Estou usando praticamente o código de amostra ASP.NET MVC que acompanha o 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();
}

Trabalhando bem com o Google, AOL e outros. No entanto, o Yahoo e o Myopenid se enquadram no caso AuthenticationStatus.Failed com a seguinte exceção:

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 outros estão tendo o mesmo problema: http://trac.dotnetopenauth.net:8000/ticket/172

Alguém tem uma solução alternativa?

Foi útil?

Solução

Acontece que isso foi um problema no uso do Dotnetopenauth em um ambiente agrícola na web.

Quando você cria seu OpenidrelyingParty, certifique -se de passar nulo no construtor.

Isso coloca seu site no modo apátrido ou 'burro' OpenID. É um pouco mais lento para os usuários fazer login (se você notar), mas evita ter que escrever um IrlyingPartyApplicationStore para permitir que o Dotnetopenauth trabalhe em sua fazenda;

var openIdRelyingParty = new OpenIdRelyingParty(null);

Outras dicas

Toda essa discussão gira em torno da seguinte pergunta:

Como a Parte de Confiar (RP) garante que a solicitação que contém o token de autenticação esteja proveniente do OP (OpenID Provedor) para o qual ele encaminhou a solicitação do usuário?

As etapas seguintes explica como isso acontece

  1. A solicitação do usuário chega à festa de resposta (RP), nosso site em nosso caso
  2. O aplicativo armazena uma assinatura exclusiva correspondente a esse usuário em um armazenamento de assinatura local (LSS) e, em seguida, incorpora essa assinatura na mensagem e encaminhe esta mensagem ao OpenID Proves (OP)
  3. O usuário digita suas credenciais e o OP autentica sua mensagem e depois encaminha esta mensagem, que tem a assinatura ainda incorporada, de volta ao RP
  4. RP Compare a assinatura que está incorporada na mensagem à assinatura que está no LSS e se eles corresponderem ao RP autenticar o usuário

Se o LSS desaparecer (de alguma forma) antes que a mensagem volte do OP, não há nada para o RP comparar a assinatura com o fato de não autenticar o usuário e lança erro: a assinatura da mensagem estava incorreta.

Como o LSS pode desaparecer:

  1. Asp.net atualiza o pool de aplicativos
  2. IIS é reiniciado
  3. Na Web Farm, a mensagem é servida por aplicativos hospedados em diferentes servidores

Duas soluções para esta questão:

  1. RP Run's no modo idiota

    uma. Ele não armazena e assinatura localmente e, portanto, não usa comparação de assinatura para garantir que a mensagem esteja proveniente do OP para o qual ele encaminhou o usuário para autenticação

    b. Em vez disso, uma vez que o RP recebeu a mensagem de autenticação do OP, ele envia a mensagem de volta ao OP e peça que ele verifique se ele é quem tem autenticar esse usuário e é o criador da mensagem. Se o OP responde sim, eu sou o criador desta mensagem e criei esta mensagem, o usuário é autenticado por RP

  2. Implemente seu próprio armazenamento de persistência que não desaparece, não importa o que o ASP.NET faz com o processo, assim como o uso do SQL para armazenar o estado da sessão.

Corrigimos esse problema implementando IRelyingPartyApplicationStore (IOpenIdApplicationStore em versões mais recentes do Dotnetopenauth) e adicionando o nome da classe da loja ao .config

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

A interface é uma composição de duas outras interfaces com cinco membros 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
{
}

Usamos o modo idiota como uma correção rápida para acumular uma corrida, mas no final você provavelmente vai querer algo assim.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top