We are currently delevoping an app which uses the DotNetOpenAuth library to secure a wcf SOAP web service via OAuth. The whole thing runs on IIS7. The web service and the DotNetOpenAuth library are running smoothly, at least when running on a PC. Calling the service from an android platform, however, causes a few hickups. Sometimes it’ll run just fine, and sometimes it’ll cause an exception saying “sequence contains no elements”.
Unfortunately I don’t have all the details, since I myself don’t actually have an android available. However, when reading log files created by my colleagues, a few things stand out.
The Windows Event log indicates that this is a KeyNotFoundException, which happens because the token is recognized (the token, in fact, is present in the database so this shouldn’t happen- I’ve checked).
Furthermore, what’s really interesting, is that this exception only happens whenever a + or / symbol is present in the oauth_token parameter. I’m kinda leaning towards thinking this is an encoding problem where the two characters are not encoded properly. When checking the Windows Event log, anytime the oauth_token parameter contains a + or /, it is replaced by a space. However I have no idea where this is encoded, why those two characters are replaced with a space and, most importantly right now, how to fix it.
I’ve also enabled log4net logging, which shows that the oauth_token variable is identitcal to what’s in the database. It does, however, show the constructed signature base string to contain the oauth_token, only the / character is replaced with %252F. A few lines lower, however, the oauth_token variable is shown seperately (ie not as part of the base string, but in a summary of variables), and there the / is actually displayed as a /.
Any help with this issue would be greatly appreciated.
EDIT
Logs retrieved from log4net
2012-05-18 13:05:21,588 (GMT+2) [5] DEBUG DotNetOpenAuth.Messaging.Channel - Preparing to send UnauthorizedTokenResponse (1.0.1) message.
2012-05-18 13:05:22,099 (GMT+2) [5] DEBUG DotNetOpenAuth.Messaging.Bindings - Binding element DotNetOpenAuth.OAuth.ChannelElements.TokenHandlingBindingElement applied to message.
2012-05-18 13:05:22,100 (GMT+2) [5] DEBUG DotNetOpenAuth.Messaging.Bindings - Binding element DotNetOpenAuth.OAuth.ChannelElements.OAuthHttpMethodBindingElement did not apply to message.
2012-05-18 13:05:22,102 (GMT+2) [5] DEBUG DotNetOpenAuth.Messaging.Bindings - Binding element DotNetOpenAuth.Messaging.Bindings.StandardReplayProtectionBindingElement did not apply to message.
2012-05-18 13:05:22,104 (GMT+2) [5] DEBUG DotNetOpenAuth.Messaging.Bindings - Binding element DotNetOpenAuth.Messaging.Bindings.StandardExpirationBindingElement did not apply to message.
2012-05-18 13:05:22,109 (GMT+2) [5] DEBUG DotNetOpenAuth.Messaging.Bindings - Binding element DotNetOpenAuth.OAuth.ChannelElements.SigningBindingElementChain did not apply to message.
2012-05-18 13:05:22,113 (GMT+2) [5] INFO DotNetOpenAuth.Messaging.Channel - Prepared outgoing UnauthorizedTokenResponse (1.0.1) message for <response>:
oauth_token: LgelzDbE0hd8Z+HrRQWD63SzNA8=
oauth_token_secret: eK1sVTQvF6LrHqrtDGXe4LpLunI=
oauth_callback_confirmed: true
2012-05-18 13:05:22,113 (GMT+2) [5] DEBUG DotNetOpenAuth.Messaging.Channel - Sending message: UnauthorizedTokenResponse
2012-05-18 13:05:22,463 (GMT+2) [5] INFO DotNetOpenAuth.Messaging.Channel - Scanning incoming request for messages: https://websrv.hszuyd.nl/serviceprovider/v2/OAuth.ashx?oauth_token=LgelzDbE0hd8Z+HrRQWD63SzNA8=
2012-05-18 13:05:22,996 (GMT+2) [5] ERROR DotNetOpenAuth.OAuthServiceProvider - An unhandled exception occurred in ASP.NET processing: DotNetOpenAuth.Messaging.ProtocolException: A token in the message was not recognized by the service provider. ---> System.Collections.Generic.KeyNotFoundException: Unrecognized token ---> System.InvalidOperationException: Sequence contains no elements
at System.Data.Linq.SqlClient.SqlProvider.Execute(Expression query, QueryInfo queryInfo, IObjectReaderFactory factory, Object[] parentArgs, Object[] userArgs, ICompiledSubQuery[] subQueries, Object lastResult)
at System.Data.Linq.SqlClient.SqlProvider.ExecuteAll(Expression query, QueryInfo[] queryInfos, IObjectReaderFactory factory, Object[] userArguments, ICompiledSubQuery[] subQueries)
at System.Data.Linq.SqlClient.SqlProvider.System.Data.Linq.Provider.IProvider.Execute(Expression query)
at System.Data.Linq.Table`1.System.Linq.IQueryProvider.Execute[TResult](Expression expression)
at System.Linq.Queryable.First[TSource](IQueryable`1 source, Expression`1 predicate)
at OAuthServiceProvider.Code.DatabaseTokenManager.GetRequestToken(String token) in C:\Program Files\TimeTableWebService\sp\Code\DatabaseTokenManager.cs:line 31
--- End of inner exception stack trace ---
at OAuthServiceProvider.Code.DatabaseTokenManager.GetRequestToken(String token) in C:\Program Files\TimeTableWebService\sp\Code\DatabaseTokenManager.cs:line 35
at DotNetOpenAuth.OAuth.ChannelElements.OAuthServiceProviderMessageFactory.GetNewRequestMessage(MessageReceivingEndpoint recipient, IDictionary`2 fields) in c:\BuildAgent\work\a02b428f36957bca\src\DotNetOpenAuth\OAuth\ChannelElements\OAuthServiceProviderMessageFactory.cs:line 80
--- End of inner exception stack trace ---
at DotNetOpenAuth.OAuth.ChannelElements.OAuthServiceProviderMessageFactory.GetNewRequestMessage(MessageReceivingEndpoint recipient, IDictionary`2 fields) in c:\BuildAgent\work\a02b428f36957bca\src\DotNetOpenAuth\OAuth\ChannelElements\OAuthServiceProviderMessageFactory.cs:line 100
at OAuthServiceProvider.Code.CustomOAuthMessageFactory.GetNewRequestMessage(MessageReceivingEndpoint recipient, IDictionary`2 fields) in C:\Program Files\TimeTableWebService\sp\Code\CustomOAuthTypeProvider.cs:line 24
at DotNetOpenAuth.Messaging.Channel.Receive(Dictionary`2 fields, MessageReceivingEndpoint recipient) in c:\BuildAgent\work\a02b428f36957bca\src\DotNetOpenAuth\Messaging\Channel.cs:line 713
at DotNetOpenAuth.OAuth.ChannelElements.OAuthChannel.ReadFromRequestCore(HttpRequestInfo request) in c:\BuildAgent\work\a02b428f36957bca\src\DotNetOpenAuth\OAuth\ChannelElements\OAuthChannel.cs:line 194
at DotNetOpenAuth.Messaging.Channel.ReadFromRequest(HttpRequestInfo httpRequest) in c:\BuildAgent\work\a02b428f36957bca\src\DotNetOpenAuth\Messaging\Channel.cs:line 422
at OAuth.ProcessRequest(HttpContext context) in d:\oauthSiteTest\serviceprovider\v2\OAuth.ashx:line 21
at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)
DotNetOpenAuth.Messaging.ProtocolException: A token in the message was not recognized by the service provider. ---> System.Collections.Generic.KeyNotFoundException: Unrecognized token ---> System.InvalidOperationException: Sequence contains no elements
at System.Data.Linq.SqlClient.SqlProvider.Execute(Expression query, QueryInfo queryInfo, IObjectReaderFactory factory, Object[] parentArgs, Object[] userArgs, ICompiledSubQuery[] subQueries, Object lastResult)
at System.Data.Linq.SqlClient.SqlProvider.ExecuteAll(Expression query, QueryInfo[] queryInfos, IObjectReaderFactory factory, Object[] userArguments, ICompiledSubQuery[] subQueries)
at System.Data.Linq.SqlClient.SqlProvider.System.Data.Linq.Provider.IProvider.Execute(Expression query)
at System.Data.Linq.Table`1.System.Linq.IQueryProvider.Execute[TResult](Expression expression)
at System.Linq.Queryable.First[TSource](IQueryable`1 source, Expression`1 predicate)
at OAuthServiceProvider.Code.DatabaseTokenManager.GetRequestToken(String token) in C:\Program Files\TimeTableWebService\sp\Code\DatabaseTokenManager.cs:line 31
--- End of inner exception stack trace ---
at OAuthServiceProvider.Code.DatabaseTokenManager.GetRequestToken(String token) in C:\Program Files\TimeTableWebService\sp\Code\DatabaseTokenManager.cs:line 35
at DotNetOpenAuth.OAuth.ChannelElements.OAuthServiceProviderMessageFactory.GetNewRequestMessage(MessageReceivingEndpoint recipient, IDictionary`2 fields) in c:\BuildAgent\work\a02b428f36957bca\src\DotNetOpenAuth\OAuth\ChannelElements\OAuthServiceProviderMessageFactory.cs:line 80
--- End of inner exception stack trace ---
at DotNetOpenAuth.OAuth.ChannelElements.OAuthServiceProviderMessageFactory.GetNewRequestMessage(MessageReceivingEndpoint recipient, IDictionary`2 fields) in c:\BuildAgent\work\a02b428f36957bca\src\DotNetOpenAuth\OAuth\ChannelElements\OAuthServiceProviderMessageFactory.cs:line 100
at OAuthServiceProvider.Code.CustomOAuthMessageFactory.GetNewRequestMessage(MessageReceivingEndpoint recipient, IDictionary`2 fields) in C:\Program Files\TimeTableWebService\sp\Code\CustomOAuthTypeProvider.cs:line 24
at DotNetOpenAuth.Messaging.Channel.Receive(Dictionary`2 fields, MessageReceivingEndpoint recipient) in c:\BuildAgent\work\a02b428f36957bca\src\DotNetOpenAuth\Messaging\Channel.cs:line 713
at DotNetOpenAuth.OAuth.ChannelElements.OAuthChannel.ReadFromRequestCore(HttpRequestInfo request) in c:\BuildAgent\work\a02b428f36957bca\src\DotNetOpenAuth\OAuth\ChannelElements\OAuthChannel.cs:line 194
at DotNetOpenAuth.Messaging.Channel.ReadFromRequest(HttpRequestInfo httpRequest) in c:\BuildAgent\work\a02b428f36957bca\src\DotNetOpenAuth\Messaging\Channel.cs:line 422
at OAuth.ProcessRequest(HttpContext context) in d:\oauthSiteTest\serviceprovider\v2\OAuth.ashx:line 21
at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)
2012-05-18 13:05:27,382 (GMT+2) [6] DEBUG DotNetOpenAuth.Messaging.Channel - Preparing to send UnauthorizedTokenResponse (1.0.1) message.
2012-05-18 13:05:27,430 (GMT+2) [6] DEBUG DotNetOpenAuth.Messaging.Bindings - Binding element DotNetOpenAuth.OAuth.ChannelElements.TokenHandlingBindingElement applied to message.
2012-05-18 13:05:27,430 (GMT+2) [6] DEBUG DotNetOpenAuth.Messaging.Bindings - Binding element DotNetOpenAuth.OAuth.ChannelElements.OAuthHttpMethodBindingElement did not apply to message.
2012-05-18 13:05:27,430 (GMT+2) [6] DEBUG DotNetOpenAuth.Messaging.Bindings - Binding element DotNetOpenAuth.Messaging.Bindings.StandardReplayProtectionBindingElement did not apply to message.
2012-05-18 13:05:27,430 (GMT+2) [6] DEBUG DotNetOpenAuth.Messaging.Bindings - Binding element DotNetOpenAuth.Messaging.Bindings.StandardExpirationBindingElement did not apply to message.
2012-05-18 13:05:27,430 (GMT+2) [6] DEBUG DotNetOpenAuth.Messaging.Bindings - Binding element DotNetOpenAuth.OAuth.ChannelElements.SigningBindingElementChain did not apply to message.
2012-05-18 13:05:27,430 (GMT+2) [6] INFO DotNetOpenAuth.Messaging.Channel - Prepared outgoing UnauthorizedTokenResponse (1.0.1) message for <response>:
oauth_token: tdKwMhsNOyQPTiz+K5th/RZr0F8=
oauth_token_secret: UtfdLNG0VqrTGinchsNfjbyFBtE=
oauth_callback_confirmed: true
2012-05-18 13:05:27,430 (GMT+2) [6] DEBUG DotNetOpenAuth.Messaging.Channel - Sending message: UnauthorizedTokenResponse
2012-05-18 13:05:27,503 (GMT+2) [6] INFO DotNetOpenAuth.Messaging.Channel - Scanning incoming request for messages: https://websrv.hszuyd.nl/serviceprovider/v2/OAuth.ashx?oauth_token=tdKwMhsNOyQPTiz+K5th/RZr0F8=
2012-05-18 13:05:27,512 (GMT+2) [6] ERROR DotNetOpenAuth.OAuthServiceProvider - An unhandled exception occurred in ASP.NET processing: DotNetOpenAuth.Messaging.ProtocolException: A token in the message was not recognized by the service provider. ---> System.Collections.Generic.KeyNotFoundException: Unrecognized token ---> System.InvalidOperationException: Sequence contains no elements
at System.Data.Linq.SqlClient.SqlProvider.Execute(Expression query, QueryInfo queryInfo, IObjectReaderFactory factory, Object[] parentArgs, Object[] userArgs, ICompiledSubQuery[] subQueries, Object lastResult)
at System.Data.Linq.SqlClient.SqlProvider.ExecuteAll(Expression query, QueryInfo[] queryInfos, IObjectReaderFactory factory, Object[] userArguments, ICompiledSubQuery[] subQueries)
at System.Data.Linq.SqlClient.SqlProvider.System.Data.Linq.Provider.IProvider.Execute(Expression query)
at System.Data.Linq.Table`1.System.Linq.IQueryProvider.Execute[TResult](Expression expression)
at System.Linq.Queryable.First[TSource](IQueryable`1 source, Expression`1 predicate)
at OAuthServiceProvider.Code.DatabaseTokenManager.GetRequestToken(String token) in C:\Program Files\TimeTableWebService\sp\Code\DatabaseTokenManager.cs:line 31
--- End of inner exception stack trace ---
at OAuthServiceProvider.Code.DatabaseTokenManager.GetRequestToken(String token) in C:\Program Files\TimeTableWebService\sp\Code\DatabaseTokenManager.cs:line 35
at DotNetOpenAuth.OAuth.ChannelElements.OAuthServiceProviderMessageFactory.GetNewRequestMessage(MessageReceivingEndpoint recipient, IDictionary`2 fields) in c:\BuildAgent\work\a02b428f36957bca\src\DotNetOpenAuth\OAuth\ChannelElements\OAuthServiceProviderMessageFactory.cs:line 80
--- End of inner exception stack trace ---
at DotNetOpenAuth.OAuth.ChannelElements.OAuthServiceProviderMessageFactory.GetNewRequestMessage(MessageReceivingEndpoint recipient, IDictionary`2 fields) in c:\BuildAgent\work\a02b428f36957bca\src\DotNetOpenAuth\OAuth\ChannelElements\OAuthServiceProviderMessageFactory.cs:line 100
at OAuthServiceProvider.Code.CustomOAuthMessageFactory.GetNewRequestMessage(MessageReceivingEndpoint recipient, IDictionary`2 fields) in C:\Program Files\TimeTableWebService\sp\Code\CustomOAuthTypeProvider.cs:line 24
at DotNetOpenAuth.Messaging.Channel.Receive(Dictionary`2 fields, MessageReceivingEndpoint recipient) in c:\BuildAgent\work\a02b428f36957bca\src\DotNetOpenAuth\Messaging\Channel.cs:line 713
at DotNetOpenAuth.OAuth.ChannelElements.OAuthChannel.ReadFromRequestCore(HttpRequestInfo request) in c:\BuildAgent\work\a02b428f36957bca\src\DotNetOpenAuth\OAuth\ChannelElements\OAuthChannel.cs:line 194
at DotNetOpenAuth.Messaging.Channel.ReadFromRequest(HttpRequestInfo httpRequest) in c:\BuildAgent\work\a02b428f36957bca\src\DotNetOpenAuth\Messaging\Channel.cs:line 422
at OAuth.ProcessRequest(HttpContext context) in d:\oauthSiteTest\serviceprovider\v2\OAuth.ashx:line 21
at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)
DotNetOpenAuth.Messaging.ProtocolException: A token in the message was not recognized by the service provider. ---> System.Collections.Generic.KeyNotFoundException: Unrecognized token ---> System.InvalidOperationException: Sequence contains no elements
at System.Data.Linq.SqlClient.SqlProvider.Execute(Expression query, QueryInfo queryInfo, IObjectReaderFactory factory, Object[] parentArgs, Object[] userArgs, ICompiledSubQuery[] subQueries, Object lastResult)
at System.Data.Linq.SqlClient.SqlProvider.ExecuteAll(Expression query, QueryInfo[] queryInfos, IObjectReaderFactory factory, Object[] userArguments, ICompiledSubQuery[] subQueries)
at System.Data.Linq.SqlClient.SqlProvider.System.Data.Linq.Provider.IProvider.Execute(Expression query)
at System.Data.Linq.Table`1.System.Linq.IQueryProvider.Execute[TResult](Expression expression)
at System.Linq.Queryable.First[TSource](IQueryable`1 source, Expression`1 predicate)
at OAuthServiceProvider.Code.DatabaseTokenManager.GetRequestToken(String token) in C:\Program Files\TimeTableWebService\sp\Code\DatabaseTokenManager.cs:line 31
--- End of inner exception stack trace ---
at OAuthServiceProvider.Code.DatabaseTokenManager.GetRequestToken(String token) in C:\Program Files\TimeTableWebService\sp\Code\DatabaseTokenManager.cs:line 35
at DotNetOpenAuth.OAuth.ChannelElements.OAuthServiceProviderMessageFactory.GetNewRequestMessage(MessageReceivingEndpoint recipient, IDictionary`2 fields) in c:\BuildAgent\work\a02b428f36957bca\src\DotNetOpenAuth\OAuth\ChannelElements\OAuthServiceProviderMessageFactory.cs:line 80
--- End of inner exception stack trace ---
at DotNetOpenAuth.OAuth.ChannelElements.OAuthServiceProviderMessageFactory.GetNewRequestMessage(MessageReceivingEndpoint recipient, IDictionary`2 fields) in c:\BuildAgent\work\a02b428f36957bca\src\DotNetOpenAuth\OAuth\ChannelElements\OAuthServiceProviderMessageFactory.cs:line 100
at OAuthServiceProvider.Code.CustomOAuthMessageFactory.GetNewRequestMessage(MessageReceivingEndpoint recipient, IDictionary`2 fields) in C:\Program Files\TimeTableWebService\sp\Code\CustomOAuthTypeProvider.cs:line 24
at DotNetOpenAuth.Messaging.Channel.Receive(Dictionary`2 fields, MessageReceivingEndpoint recipient) in c:\BuildAgent\work\a02b428f36957bca\src\DotNetOpenAuth\Messaging\Channel.cs:line 713
at DotNetOpenAuth.OAuth.ChannelElements.OAuthChannel.ReadFromRequestCore(HttpRequestInfo request) in c:\BuildAgent\work\a02b428f36957bca\src\DotNetOpenAuth\OAuth\ChannelElements\OAuthChannel.cs:line 194
at DotNetOpenAuth.Messaging.Channel.ReadFromRequest(HttpRequestInfo httpRequest) in c:\BuildAgent\work\a02b428f36957bca\src\DotNetOpenAuth\Messaging\Channel.cs:line 422
at OAuth.ProcessRequest(HttpContext context) in d:\oauthSiteTest\serviceprovider\v2\OAuth.ashx:line 21
at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)
2012-05-18 13:05:30,486 (GMT+2) [5] INFO DotNetOpenAuth.Messaging.Channel - Scanning incoming request for messages: https://websrv.hszuyd.nl/serviceprovider/v2/OAuth.ashx
2012-05-18 13:05:30,487 (GMT+2) [5] DEBUG DotNetOpenAuth.Messaging.Channel - Incoming request received: RequestScopedTokenMessage
2012-05-18 13:05:30,487 (GMT+2) [5] INFO DotNetOpenAuth.Messaging.Channel - Processing incoming RequestScopedTokenMessage (1.0.1) message:
scope: http://tempuri.org/DataApi/retrieveTimeTable
oauth_callback: x-oauthflow://callback/
oauth_consumer_key: sampleconsumer
oauth_nonce: 913320039
oauth_signature_method: HMAC-SHA1
oauth_signature: yfPMlcFo6/NgJltyCLc++RMyQCY=
oauth_version: 1.0
oauth_timestamp: 1337339130
We’d need a callstack of the exception to know for sure. Likely this exception is only an inner exception (ASP.NET has a habit of reporting inner exceptions rather than outer ones) and the outer exception would likely add the context we need as well. Since you’ve already enabled logging, you should be able to get all exception details from there, I hope.
If the
/and+characters are not being encoded in the HTTP URL, that is a bug in the client that should be fixed.