10 Stimmen

DotNetOpenAuth: Nachrichtensignatur war falsch

Ich erhalte eine Ausnahme "Message signature was incorrect", wenn ich versuche, mich mit MyOpenID und Yahoo zu authentifizieren.

Ich verwende ziemlich genau den ASP.NET MVC-Beispielcode, der mit DotNetOpenAuth 3.4.2 geliefert wurde.

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();
}

Funktioniert gut mit Google, AOL und anderen. Allerdings fallen Yahoo und MyOpenID in den AuthenticationStatus.Failed Fall mit der folgenden Ausnahme:

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

Es scheint, dass andere das gleiche Problem haben: http://trac.dotnetopenauth.net:8000/ticket/172

Hat jemand eine Lösung parat?

6voto

Shawn Miller Punkte 7007

Es stellte sich heraus, dass dies ein Problem bei der Verwendung von DotNetOpenAuth in einer Webfarm-Umgebung war.

Wenn Sie Ihre OpenIdRelyingParty erstellen, stellen Sie sicher, dass Sie null im Konstruktor übergeben.

Dies versetzt Ihre Website in den zustandslosen oder "stummen" OpenID-Modus. Es ist etwas langsamer für Benutzer, sich anzumelden (wenn Sie es überhaupt bemerken), aber Sie vermeiden es, einen IRelyingPartyApplicationStore zu schreiben, damit DotNetOpenAuth in Ihrer Farm funktioniert;

var openIdRelyingParty = new OpenIdRelyingParty(null);

5voto

vkoul Punkte 51

Die ganze Diskussion dreht sich um die folgende Frage:

Wie stellt die Relying Party (RP) sicher, dass die Anfrage, die das Authentifizierungs-Token enthält, von dem OP (OpenId Provider) kommt, an den er die Anfrage des Nutzers weitergeleitet hat?

Die folgenden Schritte erklären, wie dies geschieht

  1. Die Anfrage des Nutzers geht an die antwortende Partei (RP), in unserem Fall unsere Website
  2. Die Anwendung speichert eine eindeutige Signatur, die diesem Benutzer entspricht, in einem lokalen Signaturspeicher (LSS) und bettet diese Signatur dann in die Nachricht ein und leitet diese Nachricht an den OpenId Provider (OP) weiter
  3. Der Benutzer gibt seine Anmeldedaten ein, der OP authentifiziert seine Nachricht und leitet diese Nachricht, in der die Signatur noch eingebettet ist, an den RP weiter.
  4. RP vergleicht die in der Nachricht eingebettete Signatur mit der Signatur im LSS, und wenn sie übereinstimmen, authentifiziert RP den Benutzer

Wenn der LSS (irgendwie) verschwindet, bevor die Nachricht vom OP zurückkommt, gibt es für den RP nichts, womit er die Signatur vergleichen könnte, so dass die Authentifizierung des Benutzers fehlschlägt und ein Fehler ausgegeben wird: Die Signatur der Nachricht war falsch.

Wie kann LSS Vanish:

  1. ASP.net aktualisiert den Anwendungspool
  2. IIS wird neu gestartet
  3. In der Webfarm wird die Nachricht von einer Anwendung bedient, die auf einem anderen Server gehostet wird.

Es gibt zwei Lösungen für dieses Problem:

  1. RP läuft im Stumm-Modus

    a. Er speichert die Signatur nicht lokal und verwendet daher keinen Signaturvergleich, um sicherzustellen, dass die Nachricht von dem OP stammt, an den er den Benutzer zur Authentifizierung weitergeleitet hat.

    b. Stattdessen sendet der RP, sobald er die Authentifizierungsnachricht vom OP erhalten hat, die Nachricht an den OP zurück und bittet ihn zu prüfen, ob er derjenige ist, der diesen Benutzer authentifiziert hat und der Absender der Nachricht ist. Wenn der OP antwortet: Ja, ich bin der Urheber dieser Nachricht und ich habe diese Nachricht erstellt, dann wird der Benutzer von RP authentifiziert.

  2. Implementieren Sie Ihren eigenen Persistenzspeicher, der nicht verschwindet, unabhängig davon, was ASP.net mit dem Prozess macht, ähnlich wie die Verwendung von SQL zum Speichern des Sitzungsstatus.

4voto

Garth Punkte 555

Wir haben dieses Problem durch die Implementierung von IRelyingPartyApplicationStore ( IOpenIdApplicationStore in neueren Versionen von DotNetOpenAuth) und das Hinzufügen des Namens der Speicherklasse zur .config

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

Die Schnittstelle ist eine Zusammensetzung aus zwei anderen Schnittstellen mit insgesamt fünf Mitgliedern.

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

Wir haben den stummen Modus als schnelle Lösung verwendet, um den Betrieb aufzunehmen, aber letztendlich werden Sie wahrscheinlich etwas wie das hier wollen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X