Reputation: 3952
I'm trying to protect my WCF Service using DotNetOpenAuth's RelyingPartyLogic sample. I have Consumers authenticating working but when I go to make an Auhtorized Request against the Api I get the error This message has already been processed. This could indicate a replay attack in progress." with the stack trace:
at DotNetOpenAuth.Messaging.Bindings.StandardReplayProtectionBindingElement.ProcessIncomingMessage(IProtocolMessage message) at DotNetOpenAuth.Messaging.Channel.ProcessIncomingMessage(IProtocolMessage message) at DotNetOpenAuth.Messaging.Channel.ReadFromRequest(HttpRequestInfo httpRequest) at DotNetOpenAuth.Messaging.Channel.TryReadFromRequest[TRequest](HttpRequestInfo httpRequest, TRequest& request) at DotNetOpenAuth.OAuth.ServiceProvider.ReadProtectedResourceAuthorization(HttpRequestInfo request) at DotNetOpenAuth.OAuth.ServiceProvider.ReadProtectedResourceAuthorization(HttpRequestMessageProperty request, Uri requestUri) at RelyingPartyLogic.OAuthAuthorizationManager.CheckAccessCore(OperationContext operationContext) in D:\Code\Nodeler\Nodeler.RelyingPartyLogic\OAuthAuthorizationManager.cs:line 44 at System.ServiceModel.ServiceAuthorizationManager.CheckAccess(OperationContext operationContext) at System.ServiceModel.ServiceAuthorizationManager.CheckAccess(OperationContext operationContext, Message& message)
at System.ServiceModel.Dispatcher.AuthorizationBehavior.Authorize(MessageRpc& rpc)
The trace is as follows:
2011-04-02 19:16:12,414 (GMT-5) [16] DEBUG DotNetOpenAuth.Messaging.Channel - Sending message: AuthorizedTokenResponse 2011-04-02 19:16:15,362 (GMT-5) [16] INFO DotNetOpenAuth.Messaging.Channel - Scanning incoming request for messages: http://localhost:16468/Api/HelloWorld?oauth_token=7ix8k5NXN4NE1EXQWlHYE6klk7A%3D&oauth_consumer_key=f9fa91faa048434a86ab95681e9f732d&oauth_nonce=N7SPWJPl&oauth_signature_method=HMAC-SHA1&oauth_signature=HyNQvfk2OrP%2FnMFjLJdNih4c8N8%3D&oauth_version=1.0&oauth_timestamp=1301789775 2011-04-02 19:16:15,376 (GMT-5) [16] DEBUG DotNetOpenAuth.Messaging.Channel - Incoming request received: AccessProtectedResourceRequest 2011-04-02 19:16:15,377 (GMT-5) [16] INFO DotNetOpenAuth.Messaging.Channel - Processing incoming AccessProtectedResourceRequest (1.0) message: oauth_token: 7ix8k5NXN4NE1EXQWlHYE6klk7A= oauth_consumer_key: f9fa91faa048434a86ab95681e9f732d oauth_nonce: N7SPWJPl oauth_signature_method: HMAC-SHA1 oauth_signature: HyNQvfk2OrP/nMFjLJdNih4c8N8= oauth_version: 1.0 oauth_timestamp: 1301789775
2011-04-02 19:16:15,377 (GMT-5) [16] DEBUG DotNetOpenAuth.Messaging.Bindings - Verifying incoming AccessProtectedResourceRequest message signature of: HyNQvfk2OrP/nMFjLJdNih4c8N8= 2011-04-02 19:16:15,377 (GMT-5) [16] DEBUG DotNetOpenAuth.Messaging.Channel - Applying secrets to message to prepare for signing or signature verification. 2011-04-02 19:16:15,423 (GMT-5) [16] DEBUG DotNetOpenAuth.Messaging.Bindings - Constructed signature base string: GET&http%3A%2F%2Flocalhost%3A16468%2FApi%2FHelloWorld&oauth_consumer_key%3Df9fa91faa048434a86ab95681e9f732d%26oauth_nonce%3DN7SPWJPl%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1301789775%26oauth_token%3D7ix8k5NXN4NE1EXQWlHYE6klk7A%253D%26oauth_version%3D1.0 2011-04-02 19:16:15,424 (GMT-5) [16] DEBUG DotNetOpenAuth.Messaging.Bindings - Binding element DotNetOpenAuth.OAuth.ChannelElements.SigningBindingElementChain applied to message. 2011-04-02 19:16:15,424 (GMT-5) [16] DEBUG DotNetOpenAuth.Messaging.Bindings - Binding element DotNetOpenAuth.Messaging.Bindings.StandardExpirationBindingElement applied to message. 2011-04-02 19:16:15,424 (GMT-5) [16] DEBUG DotNetOpenAuth.Messaging.Bindings - Binding element DotNetOpenAuth.Messaging.Bindings.StandardReplayProtectionBindingElement applied to message. 2011-04-02 19:16:15,424 (GMT-5) [16] DEBUG DotNetOpenAuth.Messaging.Bindings - Binding element DotNetOpenAuth.OAuth.ChannelElements.OAuthHttpMethodBindingElement did not apply to message. 2011-04-02 19:16:15,528 (GMT-5) [16] DEBUG DotNetOpenAuth.Messaging.Bindings - Binding element DotNetOpenAuth.OAuth.ChannelElements.TokenHandlingBindingElement did not apply to message. 2011-04-02 19:16:15,528 (GMT-5) [16] DEBUG DotNetOpenAuth.Messaging.Channel - After binding element processing, the received AccessProtectedResourceRequest (1.0) message is: oauth_token: 7ix8k5NXN4NE1EXQWlHYE6klk7A= oauth_consumer_key: f9fa91faa048434a86ab95681e9f732d oauth_nonce: N7SPWJPl oauth_signature_method: HMAC-SHA1 oauth_signature: HyNQvfk2OrP/nMFjLJdNih4c8N8= oauth_version: 1.0 oauth_timestamp: 1301789775
2011-04-02 19:16:15,816 (GMT-5) [5] INFO DotNetOpenAuth.Messaging.Channel - Scanning incoming request for messages: http://localhost:16468/Api/HelloWorld?oauth_token=7ix8k5NXN4NE1EXQWlHYE6klk7A%3D&oauth_consumer_key=f9fa91faa048434a86ab95681e9f732d&oauth_nonce=N7SPWJPl&oauth_signature_method=HMAC-SHA1&oauth_signature=HyNQvfk2OrP%2FnMFjLJdNih4c8N8%3D&oauth_version=1.0&oauth_timestamp=1301789775 2011-04-02 19:16:15,826 (GMT-5) [5] DEBUG DotNetOpenAuth.Messaging.Channel - Incoming request received: AccessProtectedResourceRequest 2011-04-02 19:16:15,826 (GMT-5) [5] INFO DotNetOpenAuth.Messaging.Channel - Processing incoming AccessProtectedResourceRequest (1.0) message: oauth_token: 7ix8k5NXN4NE1EXQWlHYE6klk7A= oauth_consumer_key: f9fa91faa048434a86ab95681e9f732d oauth_nonce: N7SPWJPl oauth_signature_method: HMAC-SHA1 oauth_signature: HyNQvfk2OrP/nMFjLJdNih4c8N8= oauth_version: 1.0 oauth_timestamp: 1301789775
2011-04-02 19:16:15,826 (GMT-5) [5] DEBUG DotNetOpenAuth.Messaging.Bindings - Verifying incoming AccessProtectedResourceRequest message signature of: HyNQvfk2OrP/nMFjLJdNih4c8N8= 2011-04-02 19:16:15,826 (GMT-5) [5] DEBUG DotNetOpenAuth.Messaging.Channel - Applying secrets to message to prepare for signing or signature verification. 2011-04-02 19:16:15,853 (GMT-5) [5] DEBUG DotNetOpenAuth.Messaging.Bindings - Constructed signature base string: GET&http%3A%2F%2Flocalhost%3A16468%2FApi%2FHelloWorld&oauth_consumer_key%3Df9fa91faa048434a86ab95681e9f732d%26oauth_nonce%3DN7SPWJPl%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1301789775%26oauth_token%3D7ix8k5NXN4NE1EXQWlHYE6klk7A%253D%26oauth_version%3D1.0 2011-04-02 19:16:15,853 (GMT-5) [5] DEBUG DotNetOpenAuth.Messaging.Bindings - Binding element DotNetOpenAuth.OAuth.ChannelElements.SigningBindingElementChain applied to message. 2011-04-02 19:16:15,853 (GMT-5) [5] DEBUG DotNetOpenAuth.Messaging.Bindings - Binding element DotNetOpenAuth.Messaging.Bindings.StandardExpirationBindingElement applied to message. 2011-04-02 19:16:15,853 (GMT-5) [5] ERROR DotNetOpenAuth.OpenId - Replayed nonce detected (N7SPWJPl 04/03/2011 00:16:15). Rejecting message.
UPDATE: After some more digging the problem is that StandardExpirationBindingElement is being applied twice which causes the Nonce to be added to the NonceMemoryStore more then once. I can't for the life of me figure out why this is happening.
Upvotes: 1
Views: 1629
Reputation: 81801
The OAuthAuthenticationModule
that ship with the project template is already "consuming" the nonce that is included with the OAuth-authorized request. When your OAuthAuthorizationManager
is also applied, it tries to consume the nonce a second time and thus is detected as a replay attack. The first module is authorizing any incoming HTTP request at the ASP.NET level, whereas the second module is authorizing an incoming WCF request specifically (on top of the ASP.NET validation) so that WCF-style authorization is applied. Exactly one should be applied -- one or the other but not both.
Upvotes: 0
Reputation: 3952
I found the root issue. OAuthAuthenticationModule was also processing the request. Updating the IsOAuthControllerRequest function fixed it. I'm not sure if this is a proper fix or not but at this point I'm moving on. I'm not sure if it's just the nature or OAuth or if its DotNetOpenAuth itself but I haven't been this frustrated with programming for years.
private bool IsOAuthControllerRequest()
{
return string.Equals(this.application.Context.Request.Url.AbsolutePath, "/OAuth.ashx", StringComparison.OrdinalIgnoreCase)
|| this.application.Context.Request.Url.AbsolutePath.ToLower().StartsWith("/api/");
}
Upvotes: 1