Author: [email protected]
Date: Wed May 23 14:50:18 2012
New Revision: 2388
Log:
[AMDATUAUTH-157] Disabled nonce validation
Added:
trunk/amdatu-auth/oauth-server/src/test/
trunk/amdatu-auth/oauth-server/src/test/java/
trunk/amdatu-auth/oauth-server/src/test/java/org/
trunk/amdatu-auth/oauth-server/src/test/java/org/amdatu/
trunk/amdatu-auth/oauth-server/src/test/java/org/amdatu/auth/
trunk/amdatu-auth/oauth-server/src/test/java/org/amdatu/auth/test/
trunk/amdatu-auth/oauth-server/src/test/java/org/amdatu/auth/test/unit/
trunk/amdatu-auth/oauth-server/src/test/java/org/amdatu/auth/test/unit/oauth/
trunk/amdatu-auth/oauth-server/src/test/java/org/amdatu/auth/test/unit/oauth/server/
trunk/amdatu-auth/oauth-server/src/test/java/org/amdatu/auth/test/unit/oauth/server/OAuthNonceStorageProviderMock.java
trunk/amdatu-auth/oauth-server/src/test/java/org/amdatu/auth/test/unit/oauth/server/OAuthServerTest.java
Modified:
trunk/amdatu-auth/oauth-server/src/main/java/org/amdatu/auth/oauth/server/service/PluggableOAuthValidator.java
Modified:
trunk/amdatu-auth/oauth-server/src/main/java/org/amdatu/auth/oauth/server/service/PluggableOAuthValidator.java
==============================================================================
---
trunk/amdatu-auth/oauth-server/src/main/java/org/amdatu/auth/oauth/server/service/PluggableOAuthValidator.java
(original)
+++
trunk/amdatu-auth/oauth-server/src/main/java/org/amdatu/auth/oauth/server/service/PluggableOAuthValidator.java
Wed May 23 14:50:18 2012
@@ -174,7 +174,12 @@
long timestamp =
Long.parseLong(message.getParameter(OAuth.OAUTH_TIMESTAMP));
long now = currentTimeMsec();
validateTimestamp(message, timestamp, now);
- validateNonce(message, timestamp, now);
+
+ // FIXME: due to AMDATUAUTH-157 the nonce validation is disabled for
now. It requires
+ // more refactoring and an API change, therefore the fix is postponed
to at least 0.3.0
+ // Note that leaving out the nonce validation causes a (minor)
vulnerability to replay attacks,
+ // but because of this issue the nonce validation has never worked.
+ // validateNonce(message, timestamp, now);
}
/** Throw an exception if the timestamp [sec] is out of range. */
@@ -205,7 +210,7 @@
// consumer or using a different token will never result in a nonce
conflict (which could happen
// if they use the same nonce by coincidence)
String[] requestParams = new String[] {message.getConsumerKey(),
message.getToken()};
- boolean valid = m_nonceStore.addNonce(currentTimeMsec, nonce,
requestParams);
+ boolean valid = m_nonceStore.addNonce(timestamp, nonce, requestParams);
if (!valid) {
throw new OAuthProblemException(OAuth.Problems.NONCE_USED);
}
Added:
trunk/amdatu-auth/oauth-server/src/test/java/org/amdatu/auth/test/unit/oauth/server/OAuthNonceStorageProviderMock.java
==============================================================================
--- (empty file)
+++
trunk/amdatu-auth/oauth-server/src/test/java/org/amdatu/auth/test/unit/oauth/server/OAuthNonceStorageProviderMock.java
Wed May 23 14:50:18 2012
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2010-2012 The Amdatu Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.amdatu.auth.test.unit.oauth.server;
+
+import org.amdatu.auth.oauth.server.OAuthNonceStorageProvider;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+import java.util.Iterator;
+import java.util.Set;
+import java.util.TreeSet;
+
+public class OAuthNonceStorageProviderMock implements
OAuthNonceStorageProvider {
+
+ private final Set<UsedNonce> m_usedNonces = new TreeSet<UsedNonce>();
+
+ public boolean addNonce(long timestamp, String nonce, String[]
requestParams) {
+ String[] nonceEtc;
+ if (requestParams != null) {
+ nonceEtc = new String[requestParams.length + 1];
+ }
+ else {
+ nonceEtc = new String[1];
+ }
+ nonceEtc[0] = nonce;
+ if (requestParams != null) {
+ for (int i = 0; i < requestParams.length; i++) {
+ nonceEtc[i + 1] = requestParams[i];
+ }
+ }
+ UsedNonce usedNonce = new UsedNonce(timestamp, nonceEtc);
+ return m_usedNonces.add(usedNonce);
+ }
+
+ public void removeExpiredNonces(long timestamp) {
+ UsedNonce min = new UsedNonce(timestamp, new String[0]);
+ synchronized (m_usedNonces) {
+ // Because usedNonces is a TreeSet, its iterator produces
+ // elements from oldest to newest (their natural order).
+ for (Iterator<UsedNonce> iter = m_usedNonces.iterator();
iter.hasNext();) {
+ UsedNonce used = iter.next();
+ if (min.compareTo(used) <= 0) {
+ break; // all the rest are also new enough
+ }
+ iter.remove(); // too old
+ }
+ }
+ }
+
+ /**
+ * Selected parameters from an OAuth request, in a form suitable for
+ * detecting duplicate requests. The implementation is optimized for the
+ * comparison operations (compareTo, equals and hashCode).
+ *
+ * @author John Kristian
+ */
+ private static class UsedNonce implements Comparable<UsedNonce> {
+ private static final String ENCODING = "UTF-8";
+
+ private final String m_sortKey;
+
+ /**
+ * Construct an object containing the given timestamp, nonce and other
+ * parameters. The order of parameters is significant.
+ */
+ UsedNonce(final long timestamp, final String[] nonceEtc) {
+ StringBuilder key = new StringBuilder(String.format("%20d",
Long.valueOf(timestamp)));
+ // The blank padding ensures that timestamps are compared as
numbers.
+ for (String etc : nonceEtc) {
+ key.append("&");
+ if (etc == null) {
+ key.append(" ");
+ }
+ else {
+ key.append(percentEncode(etc));
+ }
+ // A null value is different from "" or any other String.
+ }
+ m_sortKey = key.toString();
+ }
+
+ private static String percentEncode(final String s) {
+ if (s == null) {
+ return "";
+ }
+ try {
+ return URLEncoder.encode(s, ENCODING)
+ // OAuth encodes some characters differently:
+ .replace("+", "%20").replace("*", "%2A")
+ .replace("%7E", "~");
+ // This could be done faster with more hand-crafted code.
+ }
+ catch (UnsupportedEncodingException wow) {
+ throw new RuntimeException(wow.getMessage(), wow);
+ }
+ }
+
+ /**
+ * Determine the relative order of <code>this</code> and
+ * <code>that</code>, as specified by Comparable. The timestamp is most
+ * significant; that is, if the timestamps are different, return 1 or
+ * -1. If <code>this</code> contains only a timestamp (with no nonce
+ * etc.), return -1 or 0. The treatment of the nonce etc. is murky,
+ * although 0 is returned only if they're all equal.
+ */
+ public int compareTo(final UsedNonce that) {
+ if (that == null) {
+ return 1;
+ }
+ else {
+ return m_sortKey.compareTo(that.m_sortKey);
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ return m_sortKey.hashCode();
+ }
+
+ /**
+ * Return true iff <code>this</code> and <code>that</code> contain
equal
+ * timestamps, nonce etc., in the same order.
+ */
+ @Override
+ public boolean equals(final Object that) {
+ if (that == null) {
+ return false;
+ }
+ if (that == this) {
+ return true;
+ }
+ if (that.getClass() != getClass()) {
+ return false;
+ }
+ return m_sortKey.equals(((UsedNonce) that).m_sortKey);
+ }
+
+ @Override
+ public String toString() {
+ return m_sortKey;
+ }
+ }
+}
Added:
trunk/amdatu-auth/oauth-server/src/test/java/org/amdatu/auth/test/unit/oauth/server/OAuthServerTest.java
==============================================================================
--- (empty file)
+++
trunk/amdatu-auth/oauth-server/src/test/java/org/amdatu/auth/test/unit/oauth/server/OAuthServerTest.java
Wed May 23 14:50:18 2012
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2010-2012 The Amdatu Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.amdatu.auth.test.unit.oauth.server;
+
+import net.oauth.OAuthConsumer;
+import net.oauth.OAuthException;
+import net.oauth.OAuthMessage;
+import net.oauth.OAuthServiceProvider;
+
+import org.amdatu.auth.oauth.api.OAuthAccessor;
+import org.amdatu.auth.oauth.server.service.PluggableOAuthValidator;
+
+import java.io.IOException;
+import java.net.URISyntaxException;
+
+import junit.framework.Assert;
+
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class OAuthServerTest {
+ private static final String REQUEST_TOKEN_URL =
"http://test.nl/requestToken";
+ private static final String AUTHORIZE_TOKEN_URL =
"http://test.nl/authorizeToken";
+ private static final String ACCESS_TOKEN_URL =
"http://test.nl/accessToken";
+ private static final String CONSUMER_KEY = "example_consumer_key";
+ private static final String CONSUMER_SECRET = "r01Bh0KuXWXx9AAwbLVtN8B";
+ private static final String CALLBACK_URL = null;
+
+ @BeforeClass
+ public static void setUpOnce() throws OAuthException, IOException,
URISyntaxException {
+ OAuthServiceProvider provider =
+ new OAuthServiceProvider(REQUEST_TOKEN_URL, AUTHORIZE_TOKEN_URL,
ACCESS_TOKEN_URL);
+ OAuthConsumer consumer = new OAuthConsumer(CALLBACK_URL, CONSUMER_KEY,
CONSUMER_SECRET, provider);
+ OAuthAccessor accessor = new OAuthAccessor(consumer);
+ OAuthMessage message = accessor.newRequestMessage(OAuthMessage.GET,
"http://test.nl", null);
+ PluggableOAuthValidator validator = new PluggableOAuthValidator(new
OAuthNonceStorageProviderMock());
+
+ // Validate twice within the same millisec should not fail, see
AMDATUAUTH-157.
+ // However, we need more refactoring to resolve this issue and
therefore this test is disabled for now
+ validator.validateMessage(message, accessor);
+ // validator.validateMessage(message, accessor);
+
+ // Manipulate the request and try again, this should result in an
invalid signature
+ message.addParameter("key", "value");
+ try {
+ validator.validateMessage(message, accessor);
+ Assert.fail("Manipulation of http request does not result in an
invalid signature");
+ }
+ catch (OAuthException e) {
+ // Expected result
+ }
+
+ // Trigger the same request again
+ }
+
+ @Before
+ public void setUp() {
+
+ }
+
+ @Test
+ public void testRobustness() {
+
+ }
+}
_______________________________________________
Amdatu-commits mailing list
[email protected]
http://lists.amdatu.org/mailman/listinfo/amdatu-commits