Consider two websites, "
accounts.example.com" which is an openid provider and "
app.example.com" which is an openid relaying provider both using version 4.0.1.12097 of the dotnetopenauth framework.
Assume the websites was never visited before, or that IIS was restarted, or
ASP.NET is compiling the site because something changed. When visiting "
app.example.com" and trying to sign in, it almost always throws a ProtocolException with an exception "No OpenID endpoint found". The exception orginates from the call "
return _openid.CreateRequest(value).RedirectingResponse.AsActionResult();
And the stack trace looks as follows:
[InvalidOperationException: Sequence contains no elements]
System.Linq.Enumerable.First(IEnumerable`1 source) +498
DotNetOpenAuth.OpenId.RelyingParty.OpenIdRelyingParty.CreateRequest(Identifier userSuppliedIdentifier) +64
[ProtocolException: No OpenID endpoint found.]
DotNetOpenAuth.OpenId.RelyingParty.OpenIdRelyingParty.CreateRequest(Identifier userSuppliedIdentifier) +187
MyApp.Controllers.OpenIdRelyingPartyController.SignIn(String returnUrl)
[OpenIdRelayingPartyException: Unable to create open id request]
MyApp.Controllers.OpenIdRelyingPartyController.SignIn(String returnUrl)
lambda_method(Closure , ControllerBase , Object[] ) +127
System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary`2 parameters) +260
System.Web.Mvc.Async.<>c__DisplayClass42.<BeginInvokeSynchronousActionMethod>b__41() +40
System.Web.Mvc.Async.<>c__DisplayClass39.<BeginInvokeActionMethodWithFilters>b__33() +129
System.Web.Mvc.Async.<>c__DisplayClass4f.<InvokeActionMethodFilterAsynchronously>b__49() +882151
System.Web.Mvc.Async.<>c__DisplayClass37.<BeginInvokeActionMethodWithFilters>b__36(IAsyncResult asyncResult) +15
System.Web.Mvc.Async.<>c__DisplayClass2a.<BeginInvokeAction>b__20() +33
System.Web.Mvc.Async.<>c__DisplayClass25.<BeginInvokeAction>b__22(IAsyncResult asyncResult) +882732
System.Web.Mvc.<>c__DisplayClass1d.<BeginExecuteCore>b__18(IAsyncResult asyncResult) +28
System.Web.Mvc.Async.<>c__DisplayClass4.<MakeVoidDelegate>b__3(IAsyncResult ar) +20
System.Web.Mvc.Controller.EndExecuteCore(IAsyncResult asyncResult) +67
System.Web.Mvc.Async.<>c__DisplayClass4.<MakeVoidDelegate>b__3(IAsyncResult ar) +20
System.Web.Mvc.Controller.EndExecute(IAsyncResult asyncResult) +53
System.Web.Mvc.<>c__DisplayClassb.<BeginProcessRequest>b__4(IAsyncResult asyncResult) +42
System.Web.Mvc.Async.<>c__DisplayClass4.<MakeVoidDelegate>b__3(IAsyncResult ar) +20
System.Web.Mvc.<>c__DisplayClasse.<EndProcessRequest>b__d() +54
System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +469
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +375
If we visit the website again to sign in, it works as expected. The source of this issue seems to stem from the time it takes for the openid provider to respond back. If one takes the sample
ASP.NET MVC open id provider and artificially delay the response by 30 seconds whenever the XRDS documents are requested or in the OpenIdProvider.Provider method, then the open id relaying party (
app.example.com) will fail.
So I suspect that we may experience intermittent failures depending on the response times of the open id provider and this may actually be very hard to track given the logs and the exception message being thrown. What is possibly worse, is from a usability standpoint, we do not know that this failure is due to slow response times and thus cannot provide the user with an appropriate message (such as "We are experiencing some delays and cannot process your request right now").
Has anyone else experienced this behavior? Is there something one can set to make the relaying party more resilient to slow response times? If not, should we consider this a defect?