I'm getting a "Message signature was incorrect" exception when trying to authenticate with MyOpenID and Yahoo.
I'm using pretty much the ASP.NET MVC sample code that came with 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();
}
Working fine with Google, AOL and others. However, Yahoo and MyOpenID fall into the AuthenticationStatus.Failed case with the following exception:
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
Appears that others are having the same problem: http://trac.dotnetopenauth.net:8000/ticket/172
Does anyone have a workaround?
Turns out this was an issue with using DotNetOpenAuth in a web farm environment.
When you create your OpenIdRelyingParty make sure you pass null in the constructor.
This puts your web site into OpenID stateless or 'dumb' mode. It's slightly slower for users to log in (if you even notice) but you avoid having to write an IRelyingPartyApplicationStore to allow DotNetOpenAuth to work across your farm;
var openIdRelyingParty = new OpenIdRelyingParty(null);
All this discussion revolves around the following question:
How does Relying Party (RP) make sure the request containing the authentication token is coming from the OP(OpenId Provider ) to which he forwarded the user’s request to?
Following steps explains how it happens
If the LSS vanishes (somehow) before the Message comes back from OP there is nothing for RP to compare the signature with thus it fails to authenticate user and throws error: Message signature was incorrect.
How can LSS Vanish:
Two solutions to this issue:
RP run’s in dumb mode
a. It does not store and signature locally and thus does not use signature comparison to make sure the Message is coming from the OP to which he forwarded the user to for authentication
b. Instead, once RP received the authentication Message from the OP it send the Message back to OP and ask him to check if he is the one who has authenticate this user and is the originator of the Message. If OP replies Yes I am the originator of this Message and I have created this message then the user is authenticated by RP
Implement your own persistence store that does not vanish, not matter what ASP.net does to the process, much like using SQL to store session state.
We fixed this issue by implementing IRelyingPartyApplicationStore
(IOpenIdApplicationStore
in newer versions of DotNetOpenAuth) and adding the store class name to the .config
<dotNetOpenAuth>
<openid ...>
<relyingParty>
...
<store type="some.name.space.MyRelyingPartyApplicationStore, some.assembly"/>
</relyingParty>
</openid>
...
</dotNetOpenAuth>
The interface is a composition of two other interfaces with five members all together.
/// <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
{
}
We used dumb mode as a quick fix to get up an running, but in the end you'll probably want something like this.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With