2010-03-24 13 views
10

Otrzymuję wyjątek "Podpis wiadomości był nieprawidłowy" podczas próby uwierzytelnienia za pomocą MyOpenID i Yahoo.DotNetOpenAuth: Podpis wiadomości był niepoprawny

Używam dość dużo przykładowego kodu ASP.NET MVC dostarczonej z 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(); 
} 

działa dobrze z Google, AOL i innych. Jednakże, Yahoo i MyOpenID wpaść w przypadku AuthenticationStatus.Failed z następującym wyjątkiem:

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 

się, że inni mają ten sam problem: http://trac.dotnetopenauth.net:8000/ticket/172

Czy ktoś ma obejście?

+0

Ja również otrzymuję ten sam wyjątek przy użyciu testu ławki DotNetOpenAuth podczas wykonywania tego testu: http://test-id.org/RP/POSTAssertion.aspx –

+0

To wygląda podobnego problemu: http://stackoverflow.com/questions/2508327/invalid-message-signature-when-running-openid-provider-on-cluster –

Odpowiedz

6

Okazało się, że to był problem z używaniem DotNetOpenAuth w środowisku farmy internetowej.

Po utworzeniu OpenIdRelyingParty upewnij się, że przekazałeś null w konstruktorze.

Dzięki temu twoja strona internetowa staje się bezstanowym systemem OpenID lub trybem "niemy". Logowanie jest nieco wolniejsze (jeśli zauważysz), ale unikasz konieczności pisania IRelyingPartyApplicationStore, aby umożliwić DotNetOpenAuth pracę w twojej farmie;

var openIdRelyingParty = new OpenIdRelyingParty(null); 
+2

Podejrzewam, że może to jednak powodować luki w zabezpieczeniach. Czy ktoś może potwierdzić? –

4

Naprawiliśmy ten problem poprzez wdrożenie IRelyingPartyApplicationStore (IOpenIdApplicationStore w nowszych wersjach DotNetOpenAuth) i dodanie nazwy sklepu klasy do pliku .config

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

Interfejs jest kompozycją dwóch innych interfejsów z pięciu członkowie razem.

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

Używaliśmy głupiego trybu jako szybkiej poprawki, aby uzyskać bieg, ale na koniec prawdopodobnie będziesz chciał czegoś takiego.

5

Cała ta dyskusja toczy się wokół następujące pytanie:

Jak Powołując Party (RP) upewnij się, że wniosek zawierający token uwierzytelniający pochodzi z PO (OpenID Provider), do którego przesłany Żądanie użytkownika do?

Poniższe kroki wyjaśnia, jak to się dzieje

  1. żądanie użytkownika przychodzi do Partii odpowiadanie (RP), naszej stronie internetowej w naszym przypadku
  2. przechowuje aplikacji unikalny podpis odpowiadający użytkownikowi w lokalnej podpisu przechowywać (LSS), a następnie osadzać ten podpis w wiadomości i przekazywać tę wiadomość do OpenId Provider (OP)
  3. Typy użytkowników jego poświadczenia i OP uwierzytelnia swoją wiadomość, a następnie przekazuje dalej tę wiadomość, która ma podpis nadal w niej osadzony, powrót do RP
  4. RP porównać podpis, który jest osadzony w Orędziu do podpisu, który jest w LSS i jeśli pasują RP uwierzytelnienia użytkownika

Jeśli LSS znika (jakoś) zanim wiadomość wraca z PO istnieje nic dla RP, aby porównać podpis, przez co nie uwierzytelnia użytkownika i zgłasza błąd: Podpis wiadomości był niepoprawny.

Jak można LSS Vanish:

  1. ASP.net odświeża pulę aplikacji
  2. IIS zostaje wznowiona
  3. W gospodarstwie internetowej Message serwowane jest przez aplikację hostowane na innym serwerze

Dwa rozwiązania tego problemu:

  1. Uruchomienie RP w trybie głuchym

    a. To nie przechowuje i podpis lokalnie, a tym samym nie korzysta porównanie podpisu upewnić się, że wiadomość pochodzi z PO, do którego przekazywane użytkownikowi w celu uwierzytelnienia

    b. Zamiast tego, gdy RP otrzyma wiadomość uwierzytelniającą z PO, wysyła wiadomość z powrotem do OP i prosi go, aby sprawdził, czy to on uwierzytelnił tego użytkownika i jest twórcą wiadomości. Jeśli OP odpowie: Tak, jestem twórcą tej wiadomości i utworzyłem ten komunikat, a następnie użytkownik jest uwierzytelniany przez RP

  2. Wdrożenie własnego magazynu trwałości, który nie znika, niezależnie od tego, co ASP.net robi z procesem, podobnie jak przy użyciu SQL do przechowywania stanu sesji.

Powiązane problemy