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
{