Author: ivol37 at gmail.com
Date: Mon Dec  6 16:21:52 2010
New Revision: 479

Log:
[AMDATU-182] Implemented 2-legged oAuth by supporting persistent storage of 
userids that granted access to service consumers by a 3-legged oAuth 
negotiation once before.

Added:
   
trunk/amdatu-authentication/oauth-consumerregistry-fs/src/main/java/org/amdatu/authentication/oauth/consumerregistry/fs/internal/FSOAuthServiceConsumer.java
   
trunk/integration-tests/src/test/java/org/amdatu/test/integration/tests/OAuthTwoLeggedTest.java
Modified:
   
trunk/amdatu-authentication/oauth-api/src/main/java/org/amdatu/authentication/oauth/api/OAuthServiceConsumerRegistry.java
   
trunk/amdatu-authentication/oauth-consumerregistry-fs/src/main/java/org/amdatu/authentication/oauth/consumerregistry/fs/internal/FSConsumerStore.java
   
trunk/amdatu-authentication/oauth-consumerregistry-fs/src/main/java/org/amdatu/authentication/oauth/consumerregistry/fs/service/FSConsumerRegistryImpl.java
   
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/osgi/Activator.java
   
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/service/OAuthTokenProviderImpl.java
   
trunk/amdatu-libraries/utilities/src/main/java/org/amdatu/libraries/utilities/FSUtil.java
   
trunk/integration-tests/src/test/java/org/amdatu/test/integration/base/OAuthTestBase.java
   
trunk/integration-tests/src/test/java/org/amdatu/test/integration/mock/OAuthProtectedTestServlet.java
   
trunk/integration-tests/src/test/java/org/amdatu/test/integration/tests/OAuthSignedRequestsTest.java
   
trunk/integration-tests/src/test/java/org/amdatu/test/integration/tests/OAuthThreeLeggedTest.java

Modified: 
trunk/amdatu-authentication/oauth-api/src/main/java/org/amdatu/authentication/oauth/api/OAuthServiceConsumerRegistry.java
==============================================================================
--- 
trunk/amdatu-authentication/oauth-api/src/main/java/org/amdatu/authentication/oauth/api/OAuthServiceConsumerRegistry.java
   (original)
+++ 
trunk/amdatu-authentication/oauth-api/src/main/java/org/amdatu/authentication/oauth/api/OAuthServiceConsumerRegistry.java
   Mon Dec  6 16:21:52 2010
@@ -69,4 +69,37 @@
      * @throws ConsumerRegistryStorageException If an internal error occurred 
in the consumer registry storage
      */
     void updateConsumer(OAuthServiceConsumer consumer) throws 
ConsumerNotFoundException, ConsumerRegistryStorageException;
+    
+    /**
+     * Adds the id of a user that allowed this service consumer to access 
protected resources on its behalf.
+     * This information can be used to support a 2-legged oAuth scenario. In 
this scenario the user grants access
+     * to this consumer using a 3-legged oAuth dance once. This information is 
then persisted in the consumer registry
+     * and so the service provider can verify if the user granted this access 
before, preventing the need of another
+     * explicit approval the next time.
+     * @param consumer The service consumer to which access is granted
+     * @param userId the id of the user that granted the access
+     * @throws ConsumerRegistryStorageException If an internal error occurred 
in the consumer registry storage
+     */
+    void grantResourceAccess(OAuthServiceConsumer consumer, String userId) 
throws ConsumerRegistryStorageException;
+    
+    /**
+     * Removes the id of a user that allowed this service consumer to access 
protected resources on its behalf.
+     * This method can be used to support a kind of 'unsubscribe' 
functionality; a user that wants to withdraw
+     * the rights of a service consumer to access its resources on its behalf.
+     * @param consumer The service consumer for which the access should be 
withdrawn
+     * @param userId the id of the user that withdraws the access
+     * @throws ConsumerRegistryStorageException If an internal error occurred 
in the consumer registry storage
+     */
+    void withdrawResourceAccess(OAuthServiceConsumer consumer, String userId) 
throws ConsumerRegistryStorageException;
+    
+    /**
+     * Returns if the specified user id granted access to the specified 
consumer to access its protected resource
+     * (using a 3-legged oAuth dance) on its behalf before.
+     * @param consumer The service consumer to validate for
+     * @param userId The user id to check
+     * @return <code>true</code> if the user with this id granted access to 
the specified service consumer
+     * to access its resources on its behalf.
+     * @throws ConsumerRegistryStorageException If an internal error occurred 
in the consumer registry storage
+     */
+    boolean hasResourceAccess(OAuthServiceConsumer consumer, String userId) 
throws ConsumerRegistryStorageException;
 }

Modified: 
trunk/amdatu-authentication/oauth-consumerregistry-fs/src/main/java/org/amdatu/authentication/oauth/consumerregistry/fs/internal/FSConsumerStore.java
==============================================================================
--- 
trunk/amdatu-authentication/oauth-consumerregistry-fs/src/main/java/org/amdatu/authentication/oauth/consumerregistry/fs/internal/FSConsumerStore.java
       (original)
+++ 
trunk/amdatu-authentication/oauth-consumerregistry-fs/src/main/java/org/amdatu/authentication/oauth/consumerregistry/fs/internal/FSConsumerStore.java
       Mon Dec  6 16:21:52 2010
@@ -24,6 +24,7 @@
 import java.io.ObjectOutputStream;
 import java.io.UnsupportedEncodingException;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 
 import org.amdatu.authentication.oauth.api.ConsumerRegistryStorageException;
@@ -32,11 +33,11 @@
 
 public class FSConsumerStore {
     private final File m_file;
-    private final Map<String, OAuthServiceConsumer> m_consumers;
+    private final Map<String, FSOAuthServiceConsumer> m_consumers;
 
     public FSConsumerStore(File file) throws ConsumerRegistryStorageException {
         m_file = file;
-        m_consumers = new HashMap<String, OAuthServiceConsumer>();
+        m_consumers = new HashMap<String, FSOAuthServiceConsumer>();
         try {
             readConsumers();
         }
@@ -50,7 +51,7 @@
     }
 
     public OAuthServiceConsumer addConsumer(final OAuthServiceConsumer 
consumer) {
-        return m_consumers.put(consumer.getConsumerKey(), consumer);
+        return m_consumers.put(consumer.getConsumerKey(), new 
FSOAuthServiceConsumer(consumer));
     }
 
     public OAuthServiceConsumer removeConsumer(final String consumerId) {
@@ -78,7 +79,7 @@
             ois = new ObjectInputStream(fis);
             final int numberOfConsumers = ois.readInt();
             for (int i = 0; i < numberOfConsumers; i++) {
-                final OAuthServiceConsumer consumer = readConsumer(ois);
+                final FSOAuthServiceConsumer consumer = readConsumer(ois);
                 m_consumers.put(consumer.getConsumerKey(), consumer);
             }
         }
@@ -87,33 +88,21 @@
         }
     }
 
-    private OAuthServiceConsumer readConsumer(ObjectInputStream ois) throws 
IOException, UnsupportedEncodingException {
+    private FSOAuthServiceConsumer readConsumer(ObjectInputStream ois) throws 
IOException, UnsupportedEncodingException {
         final String name = FSUtil.readString(ois);
         final String key = FSUtil.readString(ois);
         final String secret = FSUtil.readString(ois);
         final String callbackUrl = FSUtil.readString(ois);
+        final List<String> allowedUserids = FSUtil.readList(ois);
         final Map<String, String> properties = FSUtil.readProperties(ois);
-        return new OAuthServiceConsumer() {
-            public String getName() {
-                return name;
-            }
-
-            public String getConsumerKey() {
-                return key;
-            }
-
-            public String getConsumerSecret() {
-                return secret;
-            }
-
-            public String getCallbackUrl() {
-                return callbackUrl;
-            }
-
-            public Map<String, String> getProperties() {
-                return properties;
-            }
-        };
+        FSOAuthServiceConsumer consumer = new FSOAuthServiceConsumer();
+        consumer.setName(name);
+        consumer.setConsumerKey(key);
+        consumer.setConsumerSecret(secret);
+        consumer.setCallbackUrl(callbackUrl);
+        consumer.setAllowedUserIds(allowedUserids);
+        consumer.setProperties(properties);
+        return consumer;
     }
 
     private void writeConsumers() throws IOException {
@@ -127,7 +116,7 @@
             fos = new FileOutputStream(m_file);
             oos = new ObjectOutputStream(fos);
             oos.writeInt(m_consumers.size());
-            for (OAuthServiceConsumer consumer : m_consumers.values()) {
+            for (FSOAuthServiceConsumer consumer : m_consumers.values()) {
                 writeConsumer(oos, consumer);
             }
             oos.flush();
@@ -137,12 +126,13 @@
         }
     }
 
-    private void writeConsumer(ObjectOutputStream oos, OAuthServiceConsumer 
consumer)
+    private void writeConsumer(ObjectOutputStream oos, FSOAuthServiceConsumer 
consumer)
         throws UnsupportedEncodingException, IOException {
         FSUtil.writeString(oos, consumer.getName());
         FSUtil.writeString(oos, consumer.getConsumerKey());
         FSUtil.writeString(oos, consumer.getConsumerSecret());
         FSUtil.writeString(oos, consumer.getCallbackUrl());
+        FSUtil.writeList(oos, consumer.getAllowedUserIds());
         FSUtil.writeProperties(oos, consumer.getProperties());
     }
 }

Added: 
trunk/amdatu-authentication/oauth-consumerregistry-fs/src/main/java/org/amdatu/authentication/oauth/consumerregistry/fs/internal/FSOAuthServiceConsumer.java
==============================================================================
--- (empty file)
+++ 
trunk/amdatu-authentication/oauth-consumerregistry-fs/src/main/java/org/amdatu/authentication/oauth/consumerregistry/fs/internal/FSOAuthServiceConsumer.java
        Mon Dec  6 16:21:52 2010
@@ -0,0 +1,97 @@
+/*
+    Copyright (C) 2010 Amdatu.org
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+package org.amdatu.authentication.oauth.consumerregistry.fs.internal;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.amdatu.authentication.oauth.api.OAuthServiceConsumer;
+
+/**
+ * Internal class to store OAuth service consumer properties, including a list 
of userids that granted access
+ * to this service consumer to invoke the provider on its behalf.
+ * 
+ * @author ivol
+ */
+public class FSOAuthServiceConsumer implements OAuthServiceConsumer {
+    private String m_consumerKey;
+    private String m_consumerSecret;
+    private String m_name;
+    private String m_callbackUrl;
+    private List<String> m_allowedUserIds = new ArrayList<String>();
+    private Map<String, String> m_properties;
+
+    public FSOAuthServiceConsumer() {
+    }
+
+    public FSOAuthServiceConsumer(OAuthServiceConsumer consumer) {
+        setName(consumer.getName());
+        setConsumerKey(consumer.getConsumerKey());
+        setConsumerSecret(consumer.getConsumerSecret());
+        setCallbackUrl(consumer.getCallbackUrl());
+        setProperties(consumer.getProperties());
+    }
+
+    public String getConsumerKey() {
+        return m_consumerKey;
+    }
+
+    public void setConsumerKey(String consumerKey) {
+        m_consumerKey = consumerKey;
+    }
+
+    public String getConsumerSecret() {
+        return m_consumerSecret;
+    }
+
+    public void setConsumerSecret(String consumerSecret) {
+        m_consumerSecret = consumerSecret;
+    }
+
+    public String getName() {
+        return m_name;
+    }
+
+    public void setName(String name) {
+        m_name = name;
+    }
+
+    public String getCallbackUrl() {
+        return m_callbackUrl;
+    }
+
+    public void setCallbackUrl(String callbackUrl) {
+        m_callbackUrl = callbackUrl;
+    }
+
+    public Map<String, String> getProperties() {
+        return m_properties;
+    }
+
+    public void setAllowedUserIds(List<String> allowedUserIds) {
+        m_allowedUserIds = allowedUserIds;
+    }
+
+    public List<String> getAllowedUserIds() {
+        return m_allowedUserIds;
+    }
+
+    public void setProperties(Map<String, String> properties) {
+        m_properties = properties;
+    }
+}

Modified: 
trunk/amdatu-authentication/oauth-consumerregistry-fs/src/main/java/org/amdatu/authentication/oauth/consumerregistry/fs/service/FSConsumerRegistryImpl.java
==============================================================================
--- 
trunk/amdatu-authentication/oauth-consumerregistry-fs/src/main/java/org/amdatu/authentication/oauth/consumerregistry/fs/service/FSConsumerRegistryImpl.java
 (original)
+++ 
trunk/amdatu-authentication/oauth-consumerregistry-fs/src/main/java/org/amdatu/authentication/oauth/consumerregistry/fs/service/FSConsumerRegistryImpl.java
 Mon Dec  6 16:21:52 2010
@@ -17,7 +17,9 @@
 package org.amdatu.authentication.oauth.consumerregistry.fs.service;
 
 import java.io.File;
+import java.util.ArrayList;
 import java.util.Dictionary;
+import java.util.List;
 
 import org.amdatu.authentication.oauth.api.ConsumerAlreadyExistsException;
 import org.amdatu.authentication.oauth.api.ConsumerNotFoundException;
@@ -26,6 +28,7 @@
 import org.amdatu.authentication.oauth.api.OAuthServiceConsumerRegistry;
 import 
org.amdatu.authentication.oauth.consumerregistry.fs.internal.ConsumerKeyList;
 import 
org.amdatu.authentication.oauth.consumerregistry.fs.internal.FSConsumerStore;
+import 
org.amdatu.authentication.oauth.consumerregistry.fs.internal.FSOAuthServiceConsumer;
 import org.osgi.service.cm.ConfigurationException;
 import org.osgi.service.cm.ManagedService;
 import org.osgi.service.log.LogService;
@@ -144,6 +147,33 @@
         consumerStorageFile.save();
         m_logService.log(LogService.LOG_DEBUG, "Removed consumer with key '" + 
consumer.getConsumerKey() + "' from the oAuth service consumer registry");
     }
+    
+    public void grantResourceAccess(OAuthServiceConsumer consumer, String 
userId) throws ConsumerRegistryStorageException {
+        FSConsumerStore consumerStorageFile = 
getStorageFile(consumer.getConsumerKey());
+        FSOAuthServiceConsumer fsConsumer = (FSOAuthServiceConsumer) 
consumerStorageFile.getConsumer(consumer.getConsumerKey());
+        List<String> allowedUserIds = fsConsumer.getAllowedUserIds();
+        if (allowedUserIds == null) {
+            allowedUserIds = new ArrayList<String>();
+        }
+        allowedUserIds.add(userId);
+        consumerStorageFile.save();
+    }
+    
+    public void withdrawResourceAccess(OAuthServiceConsumer consumer, String 
userId) throws ConsumerRegistryStorageException {
+        FSConsumerStore consumerStorageFile = 
getStorageFile(consumer.getConsumerKey());
+        FSOAuthServiceConsumer fsConsumer = (FSOAuthServiceConsumer) 
consumerStorageFile.getConsumer(consumer.getConsumerKey());
+        List<String> allowedUserIds = fsConsumer.getAllowedUserIds();
+        if (allowedUserIds == null) {
+            allowedUserIds = new ArrayList<String>();
+        }
+        allowedUserIds.remove(userId);
+        consumerStorageFile.save();
+    }
+    
+    public boolean hasResourceAccess(OAuthServiceConsumer consumer, String 
userId) throws ConsumerRegistryStorageException {
+        FSOAuthServiceConsumer fsConsumer = (FSOAuthServiceConsumer) 
getConsumer(consumer.getConsumerKey());
+        return fsConsumer.getAllowedUserIds().contains(userId);
+    }
 
     private FSConsumerStore getStorageFile(final String entityId) throws 
ConsumerRegistryStorageException {
         final int hash = Math.abs(entityId.hashCode());

Modified: 
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/osgi/Activator.java
==============================================================================
--- 
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/osgi/Activator.java
   (original)
+++ 
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/osgi/Activator.java
   Mon Dec  6 16:21:52 2010
@@ -21,7 +21,6 @@
 
 import javax.servlet.Servlet;
 
-import org.amdatu.authentication.oauth.api.OAuthServiceConsumer;
 import org.amdatu.authentication.oauth.api.OAuthServiceConsumerRegistry;
 import org.amdatu.authentication.oauth.api.OAuthServiceProvider;
 import org.amdatu.authentication.oauth.server.OAuthAccessTokenServlet;
@@ -59,7 +58,8 @@
             .setInterface(OAuthTokenProvider.class.getName(), null)
             .setImplementation(OAuthTokenProviderImpl.class)
             
.add(createServiceDependency().setService(LogService.class).setRequired(true))
-            
.add(createServiceDependency().setService(OAuthServiceConsumer.class).setCallbacks("onAdded",
 "onRemoved")));
+            
.add(createServiceDependency().setService(OAuthServiceProvider.class).setRequired(true))
+            
.add(createServiceDependency().setService(OAuthServiceConsumerRegistry.class).setRequired(true)));
 
         // Create and register the resource provider
         manager.add(

Modified: 
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/service/OAuthTokenProviderImpl.java
==============================================================================
--- 
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/service/OAuthTokenProviderImpl.java
   (original)
+++ 
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/service/OAuthTokenProviderImpl.java
   Mon Dec  6 16:21:52 2010
@@ -18,10 +18,7 @@
 
 import java.io.IOException;
 import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
 import java.util.HashSet;
-import java.util.Map;
 
 import javax.servlet.ServletException;
 import javax.servlet.http.HttpServletRequest;
@@ -36,7 +33,10 @@
 import net.oauth.SimpleOAuthValidator;
 import net.oauth.server.OAuthServlet;
 
+import org.amdatu.authentication.oauth.api.ConsumerRegistryStorageException;
 import org.amdatu.authentication.oauth.api.OAuthServiceConsumer;
+import org.amdatu.authentication.oauth.api.OAuthServiceConsumerRegistry;
+import org.amdatu.authentication.oauth.api.OAuthServiceProvider;
 import org.amdatu.authentication.oauth.server.OAuthTokenProvider;
 import org.apache.commons.codec.digest.DigestUtils;
 import org.osgi.service.log.LogService;
@@ -44,52 +44,40 @@
 public class OAuthTokenProviderImpl implements OAuthTokenProvider {
     // Service dependencies injected by the dependency manager
     private volatile LogService m_logService;
-
+    private volatile OAuthServiceProvider m_serviceProvider;
+    private volatile OAuthServiceConsumerRegistry m_consumerRegistry;
+    
+    // The oAuth validator
     public OAuthValidator m_oAuthValidator = new SimpleOAuthValidator();
 
-    private Map<String, OAuthConsumer> m_oAuthConsumers =
-        Collections.synchronizedMap(new HashMap<String, OAuthConsumer>(10));
-
+    // Distributed tokens
     private Collection<OAuthAccessor> m_tokens = new HashSet<OAuthAccessor>();
 
     public void start() {
         m_logService.log(LogService.LOG_DEBUG, "OAuthTokenProvider service 
started");
     }
 
-    public void onAdded(OAuthServiceConsumer oAuthService) {
-        OAuthConsumer consumer = new OAuthConsumer(
-            oAuthService.getCallbackUrl(),
-            oAuthService.getConsumerKey(),
-            oAuthService.getConsumerSecret(),
-            null);
-        consumer.setProperty("description", oAuthService.getName());
-        m_oAuthConsumers.put(oAuthService.getConsumerKey(), consumer);
-        m_logService.log(LogService.LOG_DEBUG, "New OAuthServiceConsumer 
registered with key "
-            + oAuthService.getConsumerKey());
-    }
-
-    public void onRemoved(OAuthServiceConsumer oAuthService) {
-        m_oAuthConsumers.remove(oAuthService.getConsumerKey());
-        m_logService.log(LogService.LOG_DEBUG, "OAuthServiceConsumer with key 
" + oAuthService.getConsumerKey()
-            + " was removed");
-    }
-
     public synchronized OAuthConsumer getConsumer(OAuthMessage requestMessage) 
throws IOException,
         OAuthProblemException {
-        OAuthConsumer consumer = null;
-
-        // try to load from local cache if not throw exception
-        String consumer_key = requestMessage.getConsumerKey();
-        consumer = m_oAuthConsumers.get(consumer_key);
-        if (consumer == null) {
-            OAuthProblemException problem = new 
OAuthProblemException("token_rejected");
-            throw problem;
+        try {
+            // try to load from local cache if not throw exception
+            String consumer_key = requestMessage.getConsumerKey();
+            if (consumer_key == null || "".equals(consumer_key)) {
+                throw new OAuthProblemException("token_rejected");
+            }
+            OAuthServiceConsumer serviceConsumer = 
m_consumerRegistry.getConsumer(consumer_key);
+            if (serviceConsumer == null) {
+                throw new OAuthProblemException("token_rejected");
+            }
+            return copy(serviceConsumer);
+        }
+        catch (ConsumerRegistryStorageException e) {
+            throw new OAuthProblemException(e.toString());
         }
-        return consumer;
     }
 
     public OAuthValidator getOAuthValidator() {
-        // TODO: We need to provide an external REST service to validate OAuth 
messages and 
+        // TODO: We need to provide an external REST service to validate OAuth 
messages and
         // retrieve context information like userid and consumer key
         return m_oAuthValidator;
     }
@@ -160,6 +148,19 @@
         accessor.setProperty("user", userId);
         accessor.setProperty("authorized", Boolean.TRUE);
 
+        // In the consumer registry we store that this end-user allowed this 
consumer to access its
+        // procted resources on its behalf. Its up to the service provider to 
do something with this
+        // information. Storage of this information facilitates the 2-leggged 
oAuth scenario.
+        String consumerKey = accessor.consumer.consumerKey;
+        try {
+            OAuthServiceConsumer consumer = 
m_consumerRegistry.getConsumer(consumerKey);
+            m_consumerRegistry.grantResourceAccess(consumer, userId);
+        }
+        catch (ConsumerRegistryStorageException e) {
+            m_logService.log(LogService.LOG_ERROR, "Could not find consumer 
with key '" + consumerKey
+                + "', userid could not be persisted in the consumer registry 
for 2-legged oAuth support.", e);
+        }
+
         // update token in local cache
         m_tokens.add(accessor);
     }
@@ -189,8 +190,19 @@
 
     public synchronized void handleException(Exception e, HttpServletRequest 
request, HttpServletResponse response,
         boolean sendBody) throws IOException, ServletException {
-        String realm = (request.isSecure())?"https://":"http://";;
+        String realm = (request.isSecure()) ? "https://"; : "http://";;
         realm += request.getLocalName();
         OAuthServlet.handleException(response, e, realm, sendBody);
     }
+
+    private OAuthConsumer copy(OAuthServiceConsumer serviceConsumer) {
+        String callbackUrl = serviceConsumer.getCallbackUrl();
+        String key = serviceConsumer.getConsumerKey();
+        String secret = serviceConsumer.getConsumerSecret();
+        String request = m_serviceProvider.getRequestTokenURL();
+        String authorize = m_serviceProvider.getAuthorizeTokenURL();
+        String access = m_serviceProvider.getAccessTokenURL();
+        net.oauth.OAuthServiceProvider provider = new 
net.oauth.OAuthServiceProvider(request, authorize, access);
+        return new OAuthConsumer(callbackUrl, key, secret, provider);
+    }
 }

Modified: 
trunk/amdatu-libraries/utilities/src/main/java/org/amdatu/libraries/utilities/FSUtil.java
==============================================================================
--- 
trunk/amdatu-libraries/utilities/src/main/java/org/amdatu/libraries/utilities/FSUtil.java
   (original)
+++ 
trunk/amdatu-libraries/utilities/src/main/java/org/amdatu/libraries/utilities/FSUtil.java
   Mon Dec  6 16:21:52 2010
@@ -21,7 +21,9 @@
 import java.io.IOException;
 import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
+import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 
 /**
@@ -35,6 +37,15 @@
         ois.readFully(keyBytes);
         return new String(keyBytes, "utf-8");
     }
+    
+    public static List<String> readList(final ObjectInputStream ois) throws 
IOException {
+        final int listLength = ois.readInt();
+        List<String> list = new ArrayList<String>(listLength);
+        for (int i=0; i<listLength; i++) {
+            list.add(readString(ois));
+        }
+        return list;
+    }
 
     public static Map<String, String> readProperties(final ObjectInputStream 
ois) throws IOException {
         final int numberOfProperties = ois.readInt();
@@ -59,6 +70,13 @@
         oos.writeInt(bytes.length);
         oos.write(bytes);
     }
+    
+    public static void writeList(final ObjectOutputStream oos, final 
List<String> values) throws IOException {
+        oos.writeInt(values.size());
+        for (String value : values) {
+            writeString(oos, value);
+        }
+    }
 
     public static void writeProperties(final ObjectOutputStream oos, final 
Map<String, String> properties)
         throws IOException {

Modified: 
trunk/integration-tests/src/test/java/org/amdatu/test/integration/base/OAuthTestBase.java
==============================================================================
--- 
trunk/integration-tests/src/test/java/org/amdatu/test/integration/base/OAuthTestBase.java
   (original)
+++ 
trunk/integration-tests/src/test/java/org/amdatu/test/integration/base/OAuthTestBase.java
   Mon Dec  6 16:21:52 2010
@@ -25,11 +25,6 @@
 
 import javax.servlet.Servlet;
 
-import net.oauth.OAuth;
-import net.oauth.OAuthConsumer;
-import net.oauth.OAuthMessage;
-import net.oauth.OAuthProblemException;
-
 import org.amdatu.authentication.oauth.api.OAuthServiceConsumer;
 import org.amdatu.authentication.oauth.api.OAuthServiceConsumerRegistry;
 import org.amdatu.authentication.oauth.api.OAuthServiceProvider;
@@ -40,7 +35,6 @@
 import org.apache.felix.dm.Component;
 import org.apache.felix.dm.DependencyManager;
 import org.apache.http.HttpStatus;
-import org.junit.Assert;
 import org.ops4j.pax.exam.Option;
 import org.ops4j.pax.exam.junit.Configuration;
 import org.osgi.service.cm.ConfigurationAdmin;
@@ -48,11 +42,14 @@
 import org.osgi.service.log.LogService;
 
 public class OAuthTestBase extends IntegrationTestBase {
+    protected final String TEST_USERID = "ivol";
+    
     protected volatile LogService m_logService;
     protected volatile OAuthServiceProvider m_oAuthServiceProvider;
     protected volatile ConfigurationAdmin m_configAdmin;
     protected volatile DependencyManager m_dependencyManager;
     protected volatile OAuthTokenProvider m_tokenProvider;
+    protected volatile OAuthServiceConsumerRegistry m_consumerRegistry;
     
     @Configuration
     public Option[] configure() {
@@ -80,6 +77,7 @@
             .setImplementation(m_testServlet)
             .setInterface(new String[] { Servlet.class.getName() }, 
servletProperties)
             
.add(manager.createServiceDependency().setService(LogService.class).setRequired(true))
+            
.add(manager.createServiceDependency().setService(OAuthServiceConsumerRegistry.class).setRequired(true))
             
.add(manager.createServiceDependency().setService(OAuthTokenProvider.class).setRequired(true));
 
         Component testComponent = manager.createComponent()
@@ -127,42 +125,4 @@
         waitForURL( m_oAuthServiceProvider.getAccessTokenURL(), 
HttpStatus.SC_UNAUTHORIZED);
         m_logService.log(LogService.LOG_DEBUG, "oAuth servlets available");
     }
-    
-    // Register the test service consumer
-    protected OAuthServiceConsumer registerTestServiceConsumer() throws 
Exception {
-        Dictionary<String, String> properties = new Hashtable<String, 
String>();
-        properties.put("consumer_key", OAuthTestConsumer.DEFAULT_CONSUMER_KEY);
-        OAuthTestConsumer testConsumer = new OAuthTestConsumer();
-        m_dependencyManager.add(
-            m_dependencyManager.createComponent()
-            .setInterface(OAuthServiceConsumer.class.getName(), properties)
-            .setImplementation(testConsumer));
-
-        // Check if it becomes available
-        Assert.assertTrue("OAuth service consumer is not begin registered", 
getService(OAuthServiceConsumer.class,
-            "consumer_key=" + OAuthTestConsumer.DEFAULT_CONSUMER_KEY) != null);
-
-        // We have to wait until the service consumer is picked up by our 
token provider. We retry this for a
-        // maximum amount of 5 times
-        OAuthMessage message = new OAuthMessage(null, null, null);
-        message.addParameter(OAuth.OAUTH_CONSUMER_KEY, 
OAuthTestConsumer.DEFAULT_CONSUMER_KEY);
-        OAuthConsumer consumer = null;
-        int retryCount = 0;
-        while (consumer == null && retryCount < 5) {
-            try {
-                consumer = m_tokenProvider.getConsumer(message);
-            }
-            catch (IOException e) {}
-            catch (OAuthProblemException e) {}
-            if (consumer == null) {
-                m_logService.log(LogService.LOG_DEBUG,
-                    "OAuth consumer not yet picked by by token provider, 
retrycount=" + (retryCount + 1));
-                Thread.sleep(1000);
-                retryCount++;
-            }
-        }
-        Assert.assertTrue("OAuth service consumer seems not being picked up by 
the token provider", consumer != null);
-        m_logService.log(LogService.LOG_DEBUG, "Service consumer registered 
successfully");
-        return testConsumer;
-    }
 }

Modified: 
trunk/integration-tests/src/test/java/org/amdatu/test/integration/mock/OAuthProtectedTestServlet.java
==============================================================================
--- 
trunk/integration-tests/src/test/java/org/amdatu/test/integration/mock/OAuthProtectedTestServlet.java
       (original)
+++ 
trunk/integration-tests/src/test/java/org/amdatu/test/integration/mock/OAuthProtectedTestServlet.java
       Mon Dec  6 16:21:52 2010
@@ -40,6 +40,8 @@
 import net.oauth.OAuthProblemException;
 import net.oauth.server.OAuthServlet;
 
+import org.amdatu.authentication.oauth.api.ConsumerRegistryStorageException;
+import org.amdatu.authentication.oauth.api.OAuthServiceConsumerRegistry;
 import org.amdatu.authentication.oauth.server.OAuthTokenProvider;
 import org.osgi.service.log.LogService;
 
@@ -48,9 +50,15 @@
     private static final long serialVersionUID = 8834974378869705614L;
 
     public static final String SERVLET_ALIAS = "/test/oauth/protectedresource";
-
+    public static final String OAUTH_TYPE_PARAM = "oauthtype";
+    public static final String OAUTH_TYPE_SIGNED_REQUEST = "signedrequest";
+    public static final String OAUTH_TYPE_TWO_LEGGED = "2legged";
+    public static final String OAUTH_TYPE_THREE_LEGGED = "3legged";
+    
+    
     private volatile LogService m_logService;
     private volatile OAuthTokenProvider m_tokenProvider;
+    private volatile OAuthServiceConsumerRegistry m_consumerRegistry;
 
     public void doGet(HttpServletRequest request, HttpServletResponse response)
         throws IOException, ServletException {
@@ -62,16 +70,18 @@
         processRequest("POST", request, response);
     }
 
-    public void processRequest(String method, HttpServletRequest request, 
HttpServletResponse response)
-        throws IOException, ServletException {
-        m_logService.log(LogService.LOG_DEBUG,
-            "Protected resource test servlet received incoming request, 
validating token");
-
+    public void processRequest(String method, HttpServletRequest request, 
HttpServletResponse response) throws IOException, ServletException {
         try {
+            // Get the oAuth scenario type
+            String oAuthType = request.getParameter(OAUTH_TYPE_PARAM);
+            m_logService.log(LogService.LOG_DEBUG, "Protected resource test 
servlet received incoming request, oAuth type=" + oAuthType);
+            
             // Validate oAuth message and get userId from it
             String body = "";
-            String userId = validateOAuth(request);
-            if (userId == null) {
+            OAuthAccessor accessor = validateOAuth(request);
+            String consumerKey = accessor.consumer.consumerKey;
+            String userId = (String) accessor.getProperty("user");
+            if (oAuthType.equals(OAUTH_TYPE_SIGNED_REQUEST)) {
                 // In case of Signed Requests we return the received 
parameters and headers and in case of a POST the body
                 if ("GET".equals(method)) {
                     body = "\ninputparameters:";
@@ -93,7 +103,15 @@
                     body += "\ncontent=" + toString(request.getInputStream());
                 }
             }
-            else {
+            else if (oAuthType.equals(OAUTH_TYPE_TWO_LEGGED)) {
+                // Validate if the userid did allow access to access this 
protected resource before
+                if 
(m_consumerRegistry.hasResourceAccess(m_consumerRegistry.getConsumer(consumerKey),
 userId)) {
+                    body = "userid=" + userId;
+                } else {
+                    body = "access denied";
+                }
+            }
+            else if (oAuthType.equals(OAUTH_TYPE_THREE_LEGGED)) {
                 body = "userid=" + userId;
             }
             response.setContentType("text/plain");
@@ -115,9 +133,12 @@
         catch (URISyntaxException e) {
             throw new ServletException(e);
         }
+        catch (ConsumerRegistryStorageException e) {
+            throw new ServletException(e);
+        }
     }
 
-    private String validateOAuth(HttpServletRequest request) throws 
IOException, OAuthException, URISyntaxException {
+    private OAuthAccessor validateOAuth(HttpServletRequest request) throws 
IOException, OAuthException, URISyntaxException {
         OAuthMessage requestMessage = OAuthServlet.getMessage(request, null);
 
         // In case of tow-legged or three-legged oAuth, the oAuth message 
contains a request or access token
@@ -133,7 +154,7 @@
             accessor = m_tokenProvider.getAccessor(requestMessage);
         }
         m_tokenProvider.getOAuthValidator().validateMessage(requestMessage, 
accessor);
-        return (String) accessor.getProperty("user");
+        return accessor;
     }
 
     private String toString(InputStream is) throws IOException {

Modified: 
trunk/integration-tests/src/test/java/org/amdatu/test/integration/tests/OAuthSignedRequestsTest.java
==============================================================================
--- 
trunk/integration-tests/src/test/java/org/amdatu/test/integration/tests/OAuthSignedRequestsTest.java
        (original)
+++ 
trunk/integration-tests/src/test/java/org/amdatu/test/integration/tests/OAuthSignedRequestsTest.java
        Mon Dec  6 16:21:52 2010
@@ -16,6 +16,10 @@
  */
 package org.amdatu.test.integration.tests;
 
+import static 
org.amdatu.test.integration.mock.OAuthProtectedTestServlet.OAUTH_TYPE_PARAM;
+import static 
org.amdatu.test.integration.mock.OAuthProtectedTestServlet.OAUTH_TYPE_SIGNED_REQUEST;
+import static 
org.amdatu.test.integration.mock.OAuthProtectedTestServlet.SERVLET_ALIAS;
+
 import java.io.ByteArrayInputStream;
 import java.io.InputStream;
 import java.util.Hashtable;
@@ -26,7 +30,7 @@
 import org.amdatu.authentication.oauth.client.OAuthServiceConsumerClient;
 import org.amdatu.test.integration.base.ConfigProvider;
 import org.amdatu.test.integration.base.OAuthTestBase;
-import org.amdatu.test.integration.mock.OAuthProtectedTestServlet;
+import org.amdatu.test.integration.mock.OAuthTestConsumer;
 import org.junit.Assert;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -47,7 +51,8 @@
 
         // Step 1: Register a service consumer
         m_logService.log(LogService.LOG_DEBUG, "*** Step 1: Register service 
consumer ***");
-        OAuthServiceConsumer consumer = registerTestServiceConsumer();
+        OAuthServiceConsumer consumer = new OAuthTestConsumer();
+        m_consumerRegistry.addConsumer(consumer);
 
         // Step 2: Create an OAuthClient for our Amdatu OAuth server
         m_logService.log(LogService.LOG_DEBUG, "*** Step 2: Create OAuth 
Client ***");
@@ -55,7 +60,8 @@
 
         // Step 3a: Send a simple signed GET request and verify the result
         m_logService.log(LogService.LOG_DEBUG, "*** Step 3a: Send simple 
signed GET request ***");
-        String url = "http://"; + ConfigProvider.HOSTNAME + ":" + 
ConfigProvider.PORTNR + OAuthProtectedTestServlet.SERVLET_ALIAS;
+        String url = "http://"; + ConfigProvider.HOSTNAME + ":" + 
ConfigProvider.PORTNR + SERVLET_ALIAS;
+        url += "?" + OAUTH_TYPE_PARAM + "=" + OAUTH_TYPE_SIGNED_REQUEST;
         OAuthMessage message = consumerClient.invokeSignedRequest("GET", url, 
null);
         String body = message.readBodyAsString();
         m_logService.log(LogService.LOG_DEBUG, "Protected resource returns 
response: '" + body + "'");
@@ -86,5 +92,8 @@
         body = message.readBodyAsString();
         m_logService.log(LogService.LOG_DEBUG, "Protected resource returns 
POST response: '" + body + "'");
         Assert.assertTrue(body.indexOf("content=" + testSentence) != -1);
+        
+        // Step 4: Remove the consumer
+        m_consumerRegistry.removeConsumer(consumer);        
     }
 }

Modified: 
trunk/integration-tests/src/test/java/org/amdatu/test/integration/tests/OAuthThreeLeggedTest.java
==============================================================================
--- 
trunk/integration-tests/src/test/java/org/amdatu/test/integration/tests/OAuthThreeLeggedTest.java
   (original)
+++ 
trunk/integration-tests/src/test/java/org/amdatu/test/integration/tests/OAuthThreeLeggedTest.java
   Mon Dec  6 16:21:52 2010
@@ -16,6 +16,8 @@
  */
 package org.amdatu.test.integration.tests;
 
+import static 
org.amdatu.test.integration.mock.OAuthProtectedTestServlet.OAUTH_TYPE_PARAM;
+import static 
org.amdatu.test.integration.mock.OAuthProtectedTestServlet.OAUTH_TYPE_THREE_LEGGED;
 import net.oauth.OAuthAccessor;
 import net.oauth.OAuthMessage;
 
@@ -46,7 +48,8 @@
 
         // Step 1: Register a service consumer
         m_logService.log(LogService.LOG_DEBUG, "*** Step 1: Register service 
consumer ***");
-        OAuthServiceConsumer consumer = registerTestServiceConsumer();
+        OAuthServiceConsumer consumer = new OAuthTestConsumer();
+        m_consumerRegistry.addConsumer(consumer);
 
         // Step 2: Create an OAuthClient for our Amdatu OAuth server
         m_logService.log(LogService.LOG_DEBUG, "*** Step 2: Create OAuth 
Clients ***");
@@ -59,7 +62,7 @@
 
         // Step 4: Authorize the request token for a user we define
         m_logService.log(LogService.LOG_DEBUG, "*** Step 4: Authorize the 
request token ***");
-        String callback = userClient.authorizeToken(accessor, "ivol");
+        String callback = userClient.authorizeToken(accessor, TEST_USERID);
         
Assert.assertTrue(callback.startsWith(OAuthTestConsumer.DEFAULT_CALLBACK_URL + 
"?oauth_token="));
         m_logService.log(LogService.LOG_DEBUG, "Callback URL received: " + 
callback);
 
@@ -76,10 +79,14 @@
         m_logService.log(LogService.LOG_DEBUG, "*** Step 6: Access protected 
resource ***");
         String url =
             "http://"; + ConfigProvider.HOSTNAME + ":" + ConfigProvider.PORTNR 
+ OAuthProtectedTestServlet.SERVLET_ALIAS;
+        url += "?" + OAUTH_TYPE_PARAM + "=" + OAUTH_TYPE_THREE_LEGGED;
         message = consumerClient.accessResource(accessor, url, "GET");
         String body = message.readBodyAsString();
         m_logService.log(LogService.LOG_DEBUG, "Protected resource returns 
response: '" + body + "'");
-        Assert.assertTrue(body.equals("userid=ivol"));
+        Assert.assertTrue(body.equals("userid=" + TEST_USERID));
+        
+        // Step 7: Remove the consumer
+        m_consumerRegistry.removeConsumer(consumer);
     }
 
     // Step 3: Generate a request token for our service consumer

Added: 
trunk/integration-tests/src/test/java/org/amdatu/test/integration/tests/OAuthTwoLeggedTest.java
==============================================================================
--- (empty file)
+++ 
trunk/integration-tests/src/test/java/org/amdatu/test/integration/tests/OAuthTwoLeggedTest.java
     Mon Dec  6 16:21:52 2010
@@ -0,0 +1,108 @@
+/*
+ Copyright (C) 2010 Amdatu.org
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+package org.amdatu.test.integration.tests;
+
+import static 
org.amdatu.test.integration.mock.OAuthProtectedTestServlet.OAUTH_TYPE_PARAM;
+import static 
org.amdatu.test.integration.mock.OAuthProtectedTestServlet.OAUTH_TYPE_TWO_LEGGED;
+import static 
org.amdatu.test.integration.mock.OAuthProtectedTestServlet.SERVLET_ALIAS;
+import net.oauth.OAuthAccessor;
+import net.oauth.OAuthMessage;
+
+import org.amdatu.authentication.oauth.api.OAuthServiceConsumer;
+import org.amdatu.authentication.oauth.client.OAuthResourceOwnerClient;
+import org.amdatu.authentication.oauth.client.OAuthServiceConsumerClient;
+import org.amdatu.test.integration.base.ConfigProvider;
+import org.amdatu.test.integration.base.OAuthTestBase;
+import org.amdatu.test.integration.mock.OAuthTestConsumer;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.ops4j.pax.exam.junit.JUnit4TestRunner;
+import org.osgi.service.log.LogService;
+
+ at RunWith(JUnit4TestRunner.class)
+public class OAuthTwoLeggedTest extends OAuthTestBase {
+    @Test
+    public void testThreeLeggedOAuth() throws Exception {
+        // First wait for the oAuth servlets to become available
+        waitForOAuthServlets();
+
+        // Step 1: Register a service consumer
+        m_logService.log(LogService.LOG_DEBUG, "*** Step 1a: Register service 
consumer ***");
+        OAuthServiceConsumer consumer = new OAuthTestConsumer();
+        m_consumerRegistry.addConsumer(consumer);
+        
+        // Step 2: validate that the user id has not yet been added to the 
consumer registry
+        Assert.assertFalse(
+            "Userid '" + TEST_USERID + "' already added to allowed userids in 
the service consumer registry",
+            m_consumerRegistry.hasResourceAccess(consumer, TEST_USERID));
+
+        // Step 3: perform a 3-legged oAuth dance for user 'ivol'
+        // Step 3a: Create an OAuthClient for our Amdatu OAuth server
+        m_logService.log(LogService.LOG_DEBUG, "*** Step 3a: Create OAuth 
Clients ***");
+        OAuthServiceConsumerClient consumerClient = new 
OAuthServiceConsumerClient(m_oAuthServiceProvider, consumer);
+        OAuthResourceOwnerClient userClient = new 
OAuthResourceOwnerClient(m_oAuthServiceProvider, consumer);
+
+        // Step 3b: Generate a request token for our service consumer
+        m_logService.log(LogService.LOG_DEBUG, "*** Step 3b: Generate request 
token ***");
+        OAuthAccessor accessor = createRequestToken(consumerClient);
+
+        // Step 3c: Authorize the request token for a user we define
+        m_logService.log(LogService.LOG_DEBUG, "*** Step 3c: Authorize the 
request token ***");
+        userClient.authorizeToken(accessor, TEST_USERID);
+
+        // Step 3d: Exchange our request token for an access token
+        m_logService.log(LogService.LOG_DEBUG, "*** Step 3d: Get access token 
***");
+        OAuthMessage message = consumerClient.getAccessToken(accessor);
+        accessor.accessToken = message.getToken();
+        accessor.tokenSecret = message.getParameter("oauth_token_secret");
+        accessor.requestToken = null;
+
+        // Step 4: validate if the user id has been added to the consumer 
registry
+        Assert.assertTrue(
+            "Userid '" + TEST_USERID + "', not added to allowed userids in the 
service consumer registry",
+            m_consumerRegistry.hasResourceAccess(consumer, TEST_USERID));
+
+        // Step 5: Now access a 2-legged protected resource
+        String url = "http://"; + ConfigProvider.HOSTNAME + ":" + 
ConfigProvider.PORTNR + SERVLET_ALIAS;
+        url += "?" + OAUTH_TYPE_PARAM + "=" + OAUTH_TYPE_TWO_LEGGED;
+        message = consumerClient.accessResource(accessor, url, "GET");
+        String body = message.readBodyAsString();
+        m_logService.log(LogService.LOG_DEBUG, "Protected resource returns 
response: '" + body + "'");
+        Assert.assertTrue(body.equals("userid=" + TEST_USERID));
+        
+        // Step 7: Withdraw the access, then try to access the protected 
resource again
+        m_consumerRegistry.withdrawResourceAccess(consumer, TEST_USERID);
+        message = consumerClient.accessResource(accessor, url, "GET");
+        body = message.readBodyAsString();
+        m_logService.log(LogService.LOG_DEBUG, "Protected resource returns 
response: '" + body + "'");
+        Assert.assertTrue(body.equals("access denied"));
+        
+        // Step 8: Remove the consumer
+        m_consumerRegistry.removeConsumer(consumer);        
+    }
+
+    // Step 1c: Generate a request token for our service consumer
+    private OAuthAccessor createRequestToken(OAuthServiceConsumerClient 
client) throws Exception {
+        OAuthAccessor accessor = client.generateRequestToken();
+        String requestToken = accessor.requestToken;
+        String tokenSecret = accessor.tokenSecret;
+        m_logService.log(LogService.LOG_DEBUG, "Request token received: " + 
requestToken + ", token secret="
+            + tokenSecret);
+        return accessor;
+    }
+}

Reply via email to