DotNetOpenAuth: подпись сообщения неверна

Я получаю исключение «Подпись сообщения неверна» при попытке аутентификации с помощью MyOpenID и Yahoo.

Я использую в значительной степени пример кода ASP.NET MVC, который поставляется с 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();
}

Прекрасно работает с Google, AOL и другими. Однако Yahoo и MyOpenID попадают в случай AuthenticationStatus.Failed со следующим исключением:

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

Похоже, что у других такая же проблема: http://trac.dotnetopenauth.net:8000/ticket/172

Есть ли у кого-нибудь обходной путь?


person Shawn Miller    schedule 24.03.2010    source источник
comment
Я также получаю такое же исключение при использовании тестового стенда DotNetOpenAuth при выполнении этого теста: test-id. org / RP / POSTAssertion.aspx   -  person Shawn Miller    schedule 24.03.2010
comment
Это похоже на аналогичную проблему: stackoverflow.com/questions/2508327/   -  person Shawn Miller    schedule 24.03.2010


Ответы (3)


Оказывается, это была проблема с использованием DotNetOpenAuth в среде веб-фермы.

Когда вы создаете свой OpenIdRelyingParty, убедитесь, что вы передаете null в конструкторе.

Это переводит ваш веб-сайт в режим без сохранения состояния OpenID или в «немой» режим. Для пользователей это немного медленнее для входа в систему (если вы даже заметили), но вам не нужно писать IRelyingPartyApplicationStore, чтобы позволить DotNetOpenAuth работать в вашей ферме;

var openIdRelyingParty = new OpenIdRelyingParty(null);
person Shawn Miller    schedule 24.03.2010
comment
Однако я подозреваю, что это может привести к уязвимостям безопасности. Может кто-нибудь подтвердить? - person Drew Noakes; 17.09.2012

Все обсуждение вращается вокруг следующего вопроса:

Как проверяющая сторона (RP) проверяет, что запрос, содержащий токен аутентификации, поступает от OP (поставщика OpenId), которому он перенаправил запрос пользователя?

Следующие шаги объясняют, как это происходит

  1. Пользовательский запрос поступает на отвечающую сторону (RP), в нашем случае на наш веб-сайт.
  2. Приложение сохраняет уникальную подпись, соответствующую этому пользователю, в локальном хранилище подписей (LSS), а затем встраивает эту подпись в сообщение и пересылает это сообщение поставщику OpenId (OP).
  3. Пользователь вводит свои учетные данные, и OP проверяет подлинность его сообщения, а затем пересылает это сообщение, в которое все еще встроена подпись, обратно в RP.
  4. RP сравнивает подпись, которая встроена в сообщение, с подписью, которая находится в LSS, и если они соответствуют RP, аутентифицируют пользователя

Если LSS исчезает (каким-то образом) до того, как сообщение возвращается из OP, RP не с чем сравнивать подпись, поэтому он не может аутентифицировать пользователя и выдает ошибку: подпись сообщения была неправильной.

Как LSS может исчезнуть:

  1. ASP.net обновляет пул приложений
  2. IIS перезапущен
  3. В веб-ферме сообщение обслуживается приложением, размещенным на другом сервере.

Два решения этой проблемы:

  1. RP работает в немом режиме

    a. Он не хранит и не подписывает локально и, следовательно, не использует сравнение подписей, чтобы убедиться, что сообщение поступает от OP, на который он перенаправил пользователя для аутентификации.

    b. Вместо этого, как только RP получил сообщение аутентификации от OP, он отправляет сообщение обратно OP и просит его проверить, является ли он тем, кто аутентифицировал этого пользователя и является ли отправителем сообщения. Если OP отвечает: «Да», я являюсь автором этого сообщения, и я создал это сообщение, тогда пользователь аутентифицирован RP.

  2. Внедрите собственное хранилище постоянства, которое не исчезает, независимо от того, что ASP.net делает с процессом, подобно использованию SQL для хранения состояния сеанса.

person vkoul    schedule 30.09.2010

Мы исправили эту проблему, реализовав IRelyingPartyApplicationStore (IOpenIdApplicationStore в новых версиях DotNetOpenAuth) и добавив имя класса магазина в файл .config.

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

Интерфейс представляет собой композицию из двух других интерфейсов с пятью участниками вместе.

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

Мы использовали тупой режим как быстрое решение, чтобы начать работу, но в конце концов вам, вероятно, понадобится что-то вроде этого.

person Garth    schedule 25.03.2010