Author: beaton
Date: Thu Jul  8 22:58:52 2010
New Revision: 961972

URL: http://svn.apache.org/viewvc?rev=961972&view=rev
Log:
Fix for rare nonce collisions in outbound oauth.

Modified:
    
shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth/OAuthRequest.java
    
shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth/testing/FakeOAuthServiceProvider.java

Modified: 
shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth/OAuthRequest.java
URL: 
http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth/OAuthRequest.java?rev=961972&r1=961971&r2=961972&view=diff
==============================================================================
--- 
shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth/OAuthRequest.java
 (original)
+++ 
shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth/OAuthRequest.java
 Thu Jul  8 22:58:52 2010
@@ -32,6 +32,7 @@ import org.apache.commons.io.IOUtils;
 import org.apache.commons.lang.StringUtils;
 import org.apache.shindig.auth.OAuthConstants;
 import org.apache.shindig.auth.OAuthUtil;
+import org.apache.shindig.common.crypto.Crypto;
 import org.apache.shindig.common.uri.Uri;
 import org.apache.shindig.common.uri.UriBuilder;
 import org.apache.shindig.common.util.CharsetUtil;
@@ -473,6 +474,9 @@ public class OAuthRequest {
     params.add(new Parameter(OAuth.OAUTH_VERSION, OAuth.VERSION_1_0));
     params.add(new Parameter(OAuth.OAUTH_TIMESTAMP,
         Long.toString(fetcherConfig.getClock().currentTimeMillis() / 1000)));
+    // the oauth.net java code uses a clock to generate nonces, which causes 
nonce collisions
+    // under heavy load.  A random nonce is more reliable.
+    params.add(new Parameter(OAuth.OAUTH_NONCE, "" + 
Math.abs(Crypto.RAND.nextLong())));
   }
 
   static String getAuthorizationHeader(List<Map.Entry<String, String>> 
oauthParams) {

Modified: 
shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth/testing/FakeOAuthServiceProvider.java
URL: 
http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth/testing/FakeOAuthServiceProvider.java?rev=961972&r1=961971&r2=961972&view=diff
==============================================================================
--- 
shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth/testing/FakeOAuthServiceProvider.java
 (original)
+++ 
shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth/testing/FakeOAuthServiceProvider.java
 Thu Jul  8 22:58:52 2010
@@ -39,6 +39,9 @@ import org.apache.commons.io.IOUtils;
 import org.apache.shindig.auth.OAuthConstants;
 import org.apache.shindig.auth.OAuthUtil;
 import org.apache.shindig.auth.OAuthUtil.SignatureType;
+import org.apache.shindig.common.cache.LruCache;
+import org.apache.shindig.common.cache.SoftExpiringCache;
+import org.apache.shindig.common.cache.SoftExpiringCache.CachedObject;
 import org.apache.shindig.common.crypto.Crypto;
 import org.apache.shindig.common.uri.UriBuilder;
 import org.apache.shindig.common.util.CharsetUtil;
@@ -57,6 +60,7 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Set;
 import java.util.Map.Entry;
+import java.util.concurrent.TimeUnit;
 
 public class FakeOAuthServiceProvider implements HttpFetcher {
 
@@ -182,6 +186,7 @@ public class FakeOAuthServiceProvider im
   private final OAuthConsumer signedFetchConsumer;
   private final OAuthConsumer oauthConsumer;
   private final TimeSource clock;
+  private final SoftExpiringCache<String, OAuthMessage> nonceCache;
 
   private boolean unauthorized = false;
   private boolean throttled = false;
@@ -222,6 +227,9 @@ public class FakeOAuthServiceProvider im
     tokenState = Maps.newHashMap();
     validParamLocations = Sets.newHashSet();
     validParamLocations.add(OAuthParamLocation.URI_QUERY);
+    nonceCache =
+        new SoftExpiringCache<String, OAuthMessage>(new LruCache<String, 
OAuthMessage>(10000));
+    nonceCache.setTimeSource(clock);
   }
 
   public void setVagueErrors(boolean vagueErrors) {
@@ -747,6 +755,18 @@ public class FakeOAuthServiceProvider im
           throw new RuntimeException("oauth_body_hash mismatch");
         }
     }
+    
+    // Most OAuth service providers are much laxer than this about checking 
nonces (rapidly
+    // changing server-side state scales badly), but we are very strict in 
test cases.
+    String nonceKey = info.message.getConsumerKey() + ","
+        + info.message.getParameter("oauth_nonce");
+    
+    CachedObject<OAuthMessage> previousMessage = 
nonceCache.getElement(nonceKey);
+    if (previousMessage != null) {
+      throw new RuntimeException("Reused nonce, old message = " + 
previousMessage.obj
+          + ", new message " + info.message);
+    }
+    nonceCache.addElement(nonceKey, info.message, 
TimeUnit.MINUTES.toMillis(10));
   }
 
   private HttpResponse handleNotFoundUrl(HttpRequest request) throws Exception 
{


Reply via email to