Author: ivol37 at gmail.com
Date: Thu Dec 2 15:47:28 2010
New Revision: 471
Log:
[AMDATU-181] Added oAuth to the reactor build. This implementation now provides
a basic implementation of an oAuth server and API. Stuff that remains to be
done but covered by other issues:
- The service consumer registry is not yet persistent. For the moment it stores
the service consumers in memory. (AMDATU-201)
- The authorization token part of the process is currently a micky mouse
example. By simply posting a form holding the userid, a request token can be
authorized for that user id. This needs to be connected to the Amdatu login
service, or even to a pluggable login service. (AMDATU-202)
- Provide external REST service to validate OAuth messages and retrieve context
information like userid and consumer key (AMDATU-203)
- Finalize REST API for CRUD operations on service consumers (add HTTP caching
headers and authorization)(AMDATU-204)
- Support two-legged oAuth (AMDATU-182)
- Explore the possibilities to add additional information to the oAuth tokens,
like a tenant id.
Added:
trunk/amdatu-core/config-filebased/src/main/resources/conf/org.amdatu.authentication.oauth.server.cfg
trunk/integration-tests/src/test/java/org/amdatu/test/integration/mock/OAuthProtectedTestServlet.java
trunk/integration-tests/src/test/java/org/amdatu/test/integration/mock/OAuthTestConsumer.java
trunk/integration-tests/src/test/java/org/amdatu/test/integration/tests/OAuthClientTest.java
trunk/integration-tests/src/test/java/org/amdatu/test/integration/tests/OAuthServiceConsumerRegistryTest.java
Modified:
trunk/amdatu-authentication/oauth-client/src/main/java/org/amdatu/authentication/oauth/client/OAuthResourceOwnerClient.java
trunk/amdatu-authentication/oauth-client/src/main/java/org/amdatu/authentication/oauth/client/OAuthServiceConsumerClient.java
trunk/amdatu-authentication/oauth-client/src/main/java/org/amdatu/authentication/oauth/client/internal/OAuthClientBase.java
trunk/amdatu-authentication/oauth-client/src/main/java/org/amdatu/authentication/oauth/client/osgi/Activator.java
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/OAuthAccessTokenServlet.java
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/OAuthAuthorizeTokenServlet.java
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/OAuthRequestTokenServlet.java
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/OAuthServerConfig.java
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/OAuthServiceConsumerRegistry.java
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/OAuthTokenProvider.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/OAuthAccessTokenServletImpl.java
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/service/OAuthAuthorizeTokenServletImpl.java
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/service/OAuthServiceConsumerBean.java
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/service/OAuthServiceConsumerRegistryImpl.java
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/service/OAuthServiceConsumerRegistryREST.java
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/service/OAuthServiceProviderImpl.java
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/service/OAuthTokenProviderImpl.java
trunk/amdatu-release/pom.xml
trunk/amdatu-release/src/main/assembly/bin-component.xml
trunk/integration-tests/pom.xml
trunk/integration-tests/src/test/java/org/amdatu/test/integration/base/ConfigProvider.java
trunk/integration-tests/src/test/java/org/amdatu/test/integration/base/IntegrationTestBase.java
trunk/pom.xml
trunk/src/main/resources/conf/felix-config.properties
Modified:
trunk/amdatu-authentication/oauth-client/src/main/java/org/amdatu/authentication/oauth/client/OAuthResourceOwnerClient.java
==============================================================================
---
trunk/amdatu-authentication/oauth-client/src/main/java/org/amdatu/authentication/oauth/client/OAuthResourceOwnerClient.java
(original)
+++
trunk/amdatu-authentication/oauth-client/src/main/java/org/amdatu/authentication/oauth/client/OAuthResourceOwnerClient.java
Thu Dec 2 15:47:28 2010
@@ -33,61 +33,82 @@
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.methods.PostMethod;
+/**
+ * This class provides a client API to be used by resource owners for invoking
a OAuth server.
+ * Note that the only actual task of a resource owner (in other words: user)
is authorizing
+ * the request token in a three-legged oAuth dance. Therefore this client API
only provides
+ * one method, which can be used to authorize a request token for a specific
user id.
+ *
+ * @author ivol
+ */
public class OAuthResourceOwnerClient extends OAuthClientBase {
/**
- * Create a new oAuth consumer client for the specified service consumer
and service provider.
+ * Create a new oAuth resource owner client for the specified service
consumer and service provider.
+ * Once created, using this API only tokens can be authorized for this
specified service consumer
+ * and service provider. If you need to authorize different tokens, you
will need to construct a
+ * new resource client.
*
- * @param provider The oAuth service provider
- * @param consumer The oAuth service consumer
+ * @param provider The oAuth service provider that provides the request
token to be authorized by
+ * this client
+ * @param consumer The oAuth service consumer for which tokens are
authorized such that the
+ * service consumer can retrieve an access token from the service
provider
*/
public OAuthResourceOwnerClient(OAuthServiceProvider provider,
OAuthServiceConsumer consumer) {
super(provider, consumer);
}
/**
- * Authorizes a request token with the specified userId without user
interaction.
- * @param accessor
- * @param userId
- * @return
- * @throws IOException
- * @throws URISyntaxException
- * @throws OAuthException
- * @return The callback url, if the service consumer provided it
- */
- public String authorizeToken(OAuthAccessor accessor, String userId)
throws IOException, URISyntaxException, OAuthException {
- Map<String, String> paramProps = new HashMap<String, String>();
- paramProps.put("oauth_token", accessor.requestToken);
- OAuthMessage response = sendRequest(accessor, paramProps,
getProvider().getAuthorizeTokenURL());
+ * Authorizes a request token with the specified userId. Note that using
this client no user
+ * interaction is required to be able to authorize a token.
+ *
+ * @param accessor The OAuth accessor which contains the request token to
be authorized. The
+ * accessor is returned when the request token is received using
the service consumer client API.
+ * @param userId The id of the user to authorize the token with. The
userid will become part of
+ * the access token such that the service provider can retrieve the
userid and perform
+ * authorization checks.
+ * @return The callback URL of the service consumer.
+ * @throws IOException In case a I/O exception occurred
+ * @throws URISyntaxException In case some URL could not be parsed
+ * @throws OAuthException If the received request token is invalid
+ * @return The callback url, if the service consumer provided it
+ */
+ public String authorizeToken(OAuthAccessor accessor, String userId) throws
IOException, URISyntaxException,
+ OAuthException {
+ Map<String, String> paramProps = new HashMap<String, String>();
+ paramProps.put("oauth_token", accessor.requestToken);
+ OAuthMessage response = sendRequest(accessor, paramProps,
getProvider().getAuthorizeTokenURL());
- // Now the result is an authorization page containing an HTML
form we are supposed to submit
- // First read the token and callback from this form
- String sResponseBody = response.readBodyAsString();
- String tokenStart = "<input type=\"hidden\"
name=\"oauth_token\" value=\"";
- String token =
sResponseBody.substring(sResponseBody.indexOf(tokenStart) +
tokenStart.length());
- token = token.substring(0, token.indexOf("\""));
+ // Now the result is an authorization page containing an HTML form we
are supposed to submit
+ // First read the token and callback from this form
+ String sResponseBody = response.readBodyAsString();
+ String tokenStart = "<input type=\"hidden\" name=\"oauth_token\"
value=\"";
+ String token =
sResponseBody.substring(sResponseBody.indexOf(tokenStart) +
tokenStart.length());
+ token = token.substring(0, token.indexOf("\""));
- String callbackStart = "<input type=\"hidden\"
name=\"oauth_callback\" value=\"";
- String callback =
sResponseBody.substring(sResponseBody.indexOf(callbackStart) +
callbackStart.length());
- callback = callback.substring(0, callback.indexOf("\""));
+ String callbackStart = "<input type=\"hidden\" name=\"oauth_callback\"
value=\"";
+ String callback =
sResponseBody.substring(sResponseBody.indexOf(callbackStart) +
callbackStart.length());
+ callback = callback.substring(0, callback.indexOf("\""));
- // Now build the post request
- HttpClient httpClient = new HttpClient();
- NameValuePair[] data = {
- new NameValuePair("userId", userId),
- new NameValuePair("oauth_token", token),
- new NameValuePair("oauth_callback", callback)
- };
- PostMethod postMethod = new
PostMethod(getProvider().getAuthorizeTokenURL());
- postMethod.setRequestBody(data);
- int status = httpClient.executeMethod(postMethod);
- if (status == HttpStatus.SC_OK) {
- // Status 200 means authorize token went OK, but service
consumer did not specify a callback URL
- return null;
- } else if (status == HttpStatus.SC_MOVED_TEMPORARILY) {
- // Status 302 means that we are being redirected to the
callback url provided by the service consumer
- return postMethod.getResponseHeader("Location").getValue();
- } else {
- throw new OAuthException("Authorize token form returned
" + status);
- }
- }
+ // Now build the post request
+ HttpClient httpClient = new HttpClient();
+ NameValuePair[] data = {
+ new NameValuePair("userId", userId),
+ new NameValuePair("oauth_token", token),
+ new NameValuePair("oauth_callback", callback)
+ };
+ PostMethod postMethod = new
PostMethod(getProvider().getAuthorizeTokenURL());
+ postMethod.setRequestBody(data);
+ int status = httpClient.executeMethod(postMethod);
+ if (status == HttpStatus.SC_OK) {
+ // Status 200 means authorize token went OK, but service consumer
did not specify a callback URL
+ return null;
+ }
+ else if (status == HttpStatus.SC_MOVED_TEMPORARILY) {
+ // Status 302 means that we are being redirected to the callback
url provided by the service consumer
+ return postMethod.getResponseHeader("Location").getValue();
+ }
+ else {
+ throw new OAuthException("Authorize token form returned " +
status);
+ }
+ }
}
Modified:
trunk/amdatu-authentication/oauth-client/src/main/java/org/amdatu/authentication/oauth/client/OAuthServiceConsumerClient.java
==============================================================================
---
trunk/amdatu-authentication/oauth-client/src/main/java/org/amdatu/authentication/oauth/client/OAuthServiceConsumerClient.java
(original)
+++
trunk/amdatu-authentication/oauth-client/src/main/java/org/amdatu/authentication/oauth/client/OAuthServiceConsumerClient.java
Thu Dec 2 15:47:28 2010
@@ -20,7 +20,6 @@
import java.net.URISyntaxException;
import java.util.HashMap;
import java.util.Map;
-import java.util.Properties;
import net.oauth.OAuth;
import net.oauth.OAuthAccessor;
@@ -43,25 +42,24 @@
public class OAuthServiceConsumerClient extends OAuthClientBase {
/**
* Create a new oAuth consumer client for the specified service consumer
and service provider.
- *
- * @param provider The oAuth service provider
- * @param consumer The oAuth service consumer
+ * Once created, using this API only tokens can be generated for this
specified service consumer
+ * and service provider. If you need to authorize different tokens, you
will need to construct a
+ * new consumer client.
+ * @param provider The oAuth service provider to invoke to receive the
request and access tokens
+ * @param consumer The oAuth service consumer for which to generate the
request and access tokens.
*/
public OAuthServiceConsumerClient(OAuthServiceProvider provider,
OAuthServiceConsumer consumer) {
super(provider, consumer);
}
/**
- * Generates a request token and returns an OAuthAccessor which contains
the generated token. To create a
- * request token
- *
- * @param consumerKey The key that identifies the service consumer
- * @param consumerSecret The secret that belongs to the consumer key
- * @param callbackUrl The URL
- * @return
- * @throws IOException
- * @throws OAuthException
- * @throws URISyntaxException
+ * Generates a new request token and returns an OAuthAccessor which
contains the generated token.
+ * The request token will be available in accessor.requestToken and the
corresponding token secret
+ * in accessor.tokenSecret.
+ * @return The OAuth accessor containing the request token and associated
token secret.
+ * @throws IOException In case a I/O exception occurred
+ * @throws OAuthException In case the request token could not be generated.
+ * @throws URISyntaxException In case some URL could not be parsed
*/
public OAuthAccessor generateRequestToken() throws IOException,
OAuthException, URISyntaxException {
OAuthAccessor accessor = createAccessor();
@@ -71,27 +69,47 @@
}
/**
- * Exchanges the request token for an access token.
+ * Exchanges the request token for an access token. Note that the request
token must be authorized
+ * (for example by using the resource owner client) before this method is
invoked. If the token
+ * is not yet authorized, an OAuthException will be thrown.
*
- * @param accessor
- * @return
- * @throws IOException
- * @throws URISyntaxException
- * @throws OAuthException
+ * @param accessor The OAuth accessor containing the request token and
associated token secret.
+ * @return The result OAut message, containing the access token
(message.getToken() and associated
+ * token secret (message.getParameter("oauth_token_secret"))
+ * @throws IOException In case a I/O exception occurred
+ * @throws URISyntaxException In case some URL could not be parsed
+ * @throws OAuthException In case the request token in the accessor is
invalid or not yet authorized
*/
- public OAuthMessage getAccessToken(OAuthAccessor accessor ) throws
IOException, URISyntaxException, OAuthException {
+ public OAuthMessage getAccessToken(OAuthAccessor accessor) throws
IOException, URISyntaxException, OAuthException {
Map<String, String> paramProps = new HashMap<String, String>();
paramProps.put("oauth_token", accessor.requestToken);
OAuthMessage response = sendRequest(accessor, paramProps,
getProvider().getAccessTokenURL());
return response;
}
+ /**
+ * Access a protected resource which is hosted by the specified URL. The
accessor passed must
+ * provide the access token and associated token secret received before by
performing an
+ * oAuth negotiation (request token, authorize token and access token).
This method
+ * @param accessor The OAuth accessor holding the access token and
associated token secret to
+ * use for invoking the protected resource.
+ * @param url The URL to invoke (currently only a GET to this URL is
supported)
+ * @return An OAuth message encapsulating the result of the http method
call.
+ * @throws IOException In case a I/O exception occurred
+ * @throws URISyntaxException In case some URL could not be parsed
+ * @throws OAuthException In case the request token in the accessor is
invalid or not yet authorized
+ */
public OAuthMessage accessResource(OAuthAccessor accessor, String url)
throws IOException, URISyntaxException, OAuthException {
Map<String, String> paramProps = new HashMap<String, String>();
paramProps.put("oauth_token", accessor.accessToken);
return sendRequest(accessor, paramProps, url);
}
+ /**
+ * Converts accessor attributes to a String.
+ * @param accessor The OAuth accessor to convert
+ * @return Attributes of the OAuth accessor represented as a single String
+ */
public String toString(OAuthAccessor accessor) {
String result = "";
result += OAuth.OAUTH_TOKEN + "=" +
accessor.getProperty(OAuth.OAUTH_TOKEN) + " ";
Modified:
trunk/amdatu-authentication/oauth-client/src/main/java/org/amdatu/authentication/oauth/client/internal/OAuthClientBase.java
==============================================================================
---
trunk/amdatu-authentication/oauth-client/src/main/java/org/amdatu/authentication/oauth/client/internal/OAuthClientBase.java
(original)
+++
trunk/amdatu-authentication/oauth-client/src/main/java/org/amdatu/authentication/oauth/client/internal/OAuthClientBase.java
Thu Dec 2 15:47:28 2010
@@ -33,6 +33,11 @@
import org.amdatu.authentication.oauth.api.OAuthServiceConsumer;
import org.amdatu.authentication.oauth.api.OAuthServiceProvider;
+/**
+ * This is the base class for OAuth clients.
+ *
+ * @author ivol
+ */
public class OAuthClientBase {
private OAuthServiceProvider m_oAuthServiceProvider;
private OAuthServiceConsumer m_oAuthServiceConsumer;
Modified:
trunk/amdatu-authentication/oauth-client/src/main/java/org/amdatu/authentication/oauth/client/osgi/Activator.java
==============================================================================
---
trunk/amdatu-authentication/oauth-client/src/main/java/org/amdatu/authentication/oauth/client/osgi/Activator.java
(original)
+++
trunk/amdatu-authentication/oauth-client/src/main/java/org/amdatu/authentication/oauth/client/osgi/Activator.java
Thu Dec 2 15:47:28 2010
@@ -21,18 +21,14 @@
import org.osgi.framework.BundleContext;
/**
- * This is the activator for the authorization bundle
+ * This is the activator for the authentication bundle.
+ *
* @author ivol
*/
public class Activator extends DependencyActivatorBase {
-
-
- @Override
public void init(BundleContext context, DependencyManager manager) throws
Exception {
}
-
- @Override
public void destroy(BundleContext context, DependencyManager manager)
throws Exception {
}
}
Modified:
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/OAuthAccessTokenServlet.java
==============================================================================
---
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/OAuthAccessTokenServlet.java
(original)
+++
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/OAuthAccessTokenServlet.java
Thu Dec 2 15:47:28 2010
@@ -18,6 +18,11 @@
import
org.amdatu.authentication.oauth.server.service.OAuthResourceProviderImpl;
+/**
+ * Represents the servlet that is responsible for generating OAuth access
tokens.
+ *
+ * @author ivol
+ */
public interface OAuthAccessTokenServlet {
/**
* The servlet alias of the access token servlet.
Modified:
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/OAuthAuthorizeTokenServlet.java
==============================================================================
---
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/OAuthAuthorizeTokenServlet.java
(original)
+++
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/OAuthAuthorizeTokenServlet.java
Thu Dec 2 15:47:28 2010
@@ -18,9 +18,14 @@
import
org.amdatu.authentication.oauth.server.service.OAuthResourceProviderImpl;
+/**
+ * Represents the servlet that is responsible for authorizing OAuth request
tokens.
+ *
+ * @author ivol
+ */
public interface OAuthAuthorizeTokenServlet {
/**
- * The servlet alias of the request token servlet.
+ * The servlet alias of the authorize token servlet.
*/
final static String SERVLET_ALIAS = "/" +
OAuthResourceProviderImpl.RESOURCE_ID + "/authorizetoken";
}
Modified:
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/OAuthRequestTokenServlet.java
==============================================================================
---
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/OAuthRequestTokenServlet.java
(original)
+++
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/OAuthRequestTokenServlet.java
Thu Dec 2 15:47:28 2010
@@ -18,6 +18,11 @@
import
org.amdatu.authentication.oauth.server.service.OAuthResourceProviderImpl;
+/**
+ * Represents the servlet that is responsible for generating OAuth request
tokens.
+ *
+ * @author ivol
+ */
public interface OAuthRequestTokenServlet {
/**
* The servlet alias of the request token servlet.
Modified:
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/OAuthServerConfig.java
==============================================================================
---
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/OAuthServerConfig.java
(original)
+++
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/OAuthServerConfig.java
Thu Dec 2 15:47:28 2010
@@ -16,6 +16,11 @@
*/
package org.amdatu.authentication.oauth.server;
+/**
+ * Holds the PID and property names of the configuration properties stored in
Config Admin.
+ *
+ * @author ivol
+ */
public class OAuthServerConfig {
/**
* The PID of the configuration of this service.
Modified:
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/OAuthServiceConsumerRegistry.java
==============================================================================
---
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/OAuthServiceConsumerRegistry.java
(original)
+++
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/OAuthServiceConsumerRegistry.java
Thu Dec 2 15:47:28 2010
@@ -22,7 +22,10 @@
* The oAuth server uses a service consumer registry to identify from which
consumers
* token requests are received. Each token request holds the consumer key such
that the
* oAuth server knows which consumer is asking for access. Tokens will only be
distributed
- * to service conusmers that are known in this registry.
+ * to service consumers that are known in this registry. It is up to the
resource itself (or service
+ * that manipulates the resource) to do something (i.e. authorization checks)
with this information.
+ * Based on the consumer key and user id stored in the OAuth request the
resource can decide to
+ * allow or disallow to apply a certain operation for a specific consumer and
user.
*
* @author ivol
*/
@@ -32,7 +35,7 @@
* a ConsumerNotFoundException is thrown.
* @param consumerKey Key of the consumer to find
* @return The consumer if found
- * @throws ConsumerNotFoundException If tno consumer could be found
matching the specified consumer key
+ * @throws ConsumerNotFoundException If no consumer could be found
matching the specified consumer key
*/
OAuthServiceConsumer getConsumer(String consumerKey) throws
ConsumerNotFoundException;
Modified:
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/OAuthTokenProvider.java
==============================================================================
---
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/OAuthTokenProvider.java
(original)
+++
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/OAuthTokenProvider.java
Thu Dec 2 15:47:28 2010
@@ -31,74 +31,83 @@
/**
* Interface of an oAuth token provider. A oAuth token provider provides
request and access tokens and facilitates
- * marking access token as authorized.
+ * marking access token as authorized. The token provider therefore contacts
its consumer registry, tokens are only
+ * distributed for service consumers known in this registry.
+ *
* @author ivol
- *
*/
public interface OAuthTokenProvider {
/**
- * Returns an oAtuth consumer that matched the consumer key as defined in
the oAuth message. The oAuth message
- * is generated from a normal http request, but contains only the oAuth
headers that are relevant to oAuth.
+ * Returns an oAuth consumer that matches the consumer key as defined in
the oAuth message. The oAuth message
+ * is generated from a normal HTTP request, but contains only the oAuth
headers that are relevant to oAuth.
+ *
* @param requestMessage The oAuth request message
* @return The consumer that matches the consumer key in the oAuth message
- * @throws IOException
- * @throws OAuthProblemException
+ * @throws IOException In case a I/O exception occurred
+ * @throws OAuthProblemException In case validation of the OAuth message
failed
*/
OAuthConsumer getConsumer(OAuthMessage requestMessage) throws IOException,
OAuthProblemException;
-
+
/**
- * Returns the oAuth validator. The validator facilitates validating
received oAuth messages. Validation includes
+ * Returns the oAuth validator. The validator facilitates validating
received oAuth messages. Validation includes
* checking if the token is expired, if the nonce is valid and if the
provided (encrypted) consumer secret is correct.
- * @return The OAuthValidator
+ *
+ * @return The OAuth validator class which can be used to validate OAuth
messages.
*/
OAuthValidator getOAuthValidator();
-
+
/**
* Generates a new fresh request token for the given accessor. An accessor
holds the service consumer and
- * adds the request token, token secret and access token.
- * @param accessor
- * @throws OAuthException
+ * service provider, this method sets the request token and corresponding
token secret in the accessor.
+ *
+ * @param accessor The OAuth accessor holding information about the
service consumer.
+ * @throws OAuthException In case information in the provided accessor is
invalid.
*/
void generateRequestToken(OAuthAccessor accessor) throws OAuthException;
-
+
/**
- * An accessor contains provided tokens for a specific service consumer.
When a request token is generated, an
- * accessor is added for the service consumer holding the request token
and token secret. So an accessor is a
- * kind of 'oAuth session'. When the request token is authorized, the
access token is added to the accessor.
+ * An accessor contains provided tokens for a specific service consumer.
When a request token is generated, the
+ * request token and token secret are added tp the accessor. When a
request token is exchanged for an access token,
+ * the request token is removed from the accessor and the access token and
associated token secret are added.
+ * So an accessor is a kind of 'oAuth session'.
* This method returns the accessor from the given oAuth message, which
holds the relevant oAuth headers
* posted in the oAuth request.
+ *
* @return The accessor, holding the distributed tokens for a particular
oAuth session for a service consumer
*/
OAuthAccessor getAccessor(OAuthMessage requestMessage) throws IOException,
OAuthProblemException;
-
+
/**
* Handles an exception thrown by any token servlet.
- * @param e
- * @param request
- * @param response
- * @param sendBody
- * @throws IOException
- * @throws ServletException
+ *
+ * @param e The exception thrown
+ * @param request The HTTP servlet request
+ * @param response The HTTP servlet responde
+ * @param sendBody Whether information about the cause of the exception
must be set in the
+ * mesasge body or not
+ * @throws IOException In case of a I/O exception
+ * @throws ServletException In case of a servlet exception
*/
void handleException(Exception e, HttpServletRequest request,
HttpServletResponse response,
boolean sendBody) throws IOException, ServletException;
-
+
/**
- * Marks the request token as authorized. The accessor represents the
generated tokens for the service
- * consumer and the userId
- * @param accessor
- * @param userId
- * @throws OAuthException
+ * Marks the request token in the accessor as authorized. Request tokens
are marked as authorized after
+ * authorizing the token, for which usually the user first needs to login
and explicitly grant access to
+ * the service consumer.
+ *
+ * @param accessor The OAuth accessor
+ * @param userId the user id that authorized the token
+ * @throws OAuthException In case the provided oAuth tokens in the
accessor are invalid
*/
void markAsAuthorized(OAuthAccessor accessor, String userId) throws
OAuthException;
-
/**
* Exchange the request token for an access token. This call is typically
invoked after a request token
* has been authorized, however this method does not validate that. The
token servlets are supposed to
* perform all token validations.
*
- * @throws OAuthException
+ * @throws OAuthException In case the oAuth token stored in the accessor
is invalid.
*/
void generateAccessToken(OAuthAccessor accessor) throws OAuthException;
}
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
Thu Dec 2 15:47:28 2010
@@ -28,6 +28,7 @@
import org.amdatu.authentication.oauth.server.OAuthRequestTokenServlet;
import org.amdatu.authentication.oauth.server.OAuthServiceConsumerRegistry;
import org.amdatu.authentication.oauth.server.OAuthTokenProvider;
+import org.amdatu.authentication.oauth.server.OAuthServerConfig;
import
org.amdatu.authentication.oauth.server.service.OAuthAccessTokenServletImpl;
import
org.amdatu.authentication.oauth.server.service.OAuthAuthorizeTokenServletImpl;
import
org.amdatu.authentication.oauth.server.service.OAuthRequestTokenServletImpl;
@@ -60,42 +61,42 @@
.setImplementation(OAuthTokenProviderImpl.class)
.add(createServiceDependency().setService(LogService.class).setRequired(true))
.add(createServiceDependency().setService(OAuthServiceConsumer.class).setCallbacks("onAdded",
"onRemoved")));
-
+
// Create and register the resource provider
manager.add(
createComponent()
.setInterface(ResourceProvider.class.getName(), null)
.setImplementation(OAuthResourceProviderImpl.class)
-
.add(createServiceDependency().setService(HttpContextServiceFactory.class).setRequired(true)));
-
+
.add(createServiceDependency().setService(HttpContextServiceFactory.class).setRequired(true)));
+
// Create and register the OAuth service provider
manager.add(
createComponent()
.setInterface(new String[]{OAuthServiceProvider.class.getName(),
ManagedService.class.getName()}, null)
.setImplementation(OAuthServiceProviderImpl.class)
-
.add(createConfigurationDependency().setPid(OAuthServiceProviderImpl.PID)));
-
+
.add(createConfigurationDependency().setPid(OAuthServerConfig.PID)));
+
// Create and register the oAuth service consumer registry service
manager.add(
createComponent()
.setInterface(OAuthServiceConsumerRegistry.class.getName(), null)
.setImplementation(OAuthServiceConsumerRegistryImpl.class)
-
.add(createServiceDependency().setService(LogService.class).setRequired(true)));
-
+
.add(createServiceDependency().setService(LogService.class).setRequired(true)));
+
// Create and register the oAuth service consumer registry REST service
manager.add(
createComponent()
.setInterface(ResourceProvider.class.getName(), null)
.setImplementation(OAuthServiceConsumerRegistryREST.class)
.add(createServiceDependency().setService(LogService.class).setRequired(true))
-
.add(createServiceDependency().setService(OAuthServiceConsumerRegistry.class).setRequired(true)));
-
+
.add(createServiceDependency().setService(OAuthServiceConsumerRegistry.class).setRequired(true)));
+
// Create and register the OAuth servlet components.
manager.add(createComponent(OAuthRequestTokenServlet.SERVLET_ALIAS,
OAuthRequestTokenServlet.class, OAuthRequestTokenServletImpl.class));
manager.add(createComponent(OAuthAuthorizeTokenServlet.SERVLET_ALIAS,
OAuthAuthorizeTokenServlet.class, OAuthAuthorizeTokenServletImpl.class));
manager.add(createComponent(OAuthAccessTokenServlet.SERVLET_ALIAS,
OAuthAccessTokenServlet.class, OAuthAccessTokenServletImpl.class));
}
-
+
private Component createComponent(String alias, Class<?> servletInterface,
Class<?> servletClass) {
Dictionary<String, String> servletProperties = new Hashtable<String,
String>();
servletProperties.put("alias", alias);
Modified:
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/service/OAuthAccessTokenServletImpl.java
==============================================================================
---
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/service/OAuthAccessTokenServletImpl.java
(original)
+++
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/service/OAuthAccessTokenServletImpl.java
Thu Dec 2 15:47:28 2010
@@ -68,11 +68,12 @@
}
// generate access token and secret
m_tokenProvider.generateAccessToken(accessor);
- m_logService.log(LogService.LOG_DEBUG, "Generated access token " +
accessor.accessToken);
+ m_logService.log(LogService.LOG_DEBUG, "Generated access token " +
accessor.accessToken + ", with token secret " + accessor.tokenSecret);
response.setContentType("text/plain");
OutputStream out = null;
try {
+ // TODO: We need to explore the possibilities to add
additional information to the oAuth tokens, like a tenant id.
out = response.getOutputStream();
OAuth.formEncode(OAuth.newList("oauth_token",
accessor.accessToken, "oauth_token_secret",
accessor.tokenSecret), out);
Modified:
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/service/OAuthAuthorizeTokenServletImpl.java
==============================================================================
---
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/service/OAuthAuthorizeTokenServletImpl.java
(original)
+++
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/service/OAuthAuthorizeTokenServletImpl.java
Thu Dec 2 15:47:28 2010
@@ -101,6 +101,9 @@
// Create a request wrapper returning the path of the JSP servlet
instead of this servlet
HttpServletRequestWrapper wrapper = new
HttpServletRequestWrapper(request) {
public String getPathInfo() {
+ // TODO: This JSP is currently a Micky Mouse example. By
simply posting a form holding
+ // the userid, a request token can be authorized for that user
id. This needs to be
+ // connected to the Amdatu login service, or even to a
pluggable login service.
return "/" + OAuthResourceProviderImpl.RESOURCE_ID +
"/jsp/authorize.jsp";
}
};
Modified:
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/service/OAuthServiceConsumerBean.java
==============================================================================
---
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/service/OAuthServiceConsumerBean.java
(original)
+++
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/service/OAuthServiceConsumerBean.java
Thu Dec 2 15:47:28 2010
@@ -1,3 +1,19 @@
+/*
+ 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.server.service;
import java.lang.reflect.InvocationTargetException;
@@ -15,6 +31,10 @@
@SuppressWarnings("restriction")
@XmlRootElement(name = "consumer")
@XmlAccessorType(XmlAccessType.PUBLIC_MEMBER)
+
+/**
+ * Implementation of JAXB bean used by the oAuth service consumer registry
REST service.
+ */
public class OAuthServiceConsumerBean implements OAuthServiceConsumer {
private String m_consumerKey;
@@ -79,6 +99,4 @@
bean.addLink(thisLink, "alternate");
return bean;
}
-
-
}
Modified:
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/service/OAuthServiceConsumerRegistryImpl.java
==============================================================================
---
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/service/OAuthServiceConsumerRegistryImpl.java
(original)
+++
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/service/OAuthServiceConsumerRegistryImpl.java
Thu Dec 2 15:47:28 2010
@@ -26,6 +26,8 @@
import org.osgi.service.log.LogService;
public class OAuthServiceConsumerRegistryImpl implements
OAuthServiceConsumerRegistry {
+ // TODO: for now this simple implementation stores consumer in memory,
this must be replaced
+ // by a persistent storage.
Map<String, OAuthServiceConsumer> m_consumers = new HashMap<String,
OAuthServiceConsumer>();
private LogService m_logService;
Modified:
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/service/OAuthServiceConsumerRegistryREST.java
==============================================================================
---
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/service/OAuthServiceConsumerRegistryREST.java
(original)
+++
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/service/OAuthServiceConsumerRegistryREST.java
Thu Dec 2 15:47:28 2010
@@ -41,28 +41,31 @@
/**
* This class provides a REST interface on top of the oAuth service consumer
registry
+ * TODO: This REST API needs to be finalized by adding HTTP caching headers,
authorization checks and
+ * possibly additional methods.
+ *
* @author ivol
- *
*/
@Path("oauth/consumers")
public class OAuthServiceConsumerRegistryREST implements ResourceProvider {
// The oAuth service consumer registry
private volatile OAuthServiceConsumerRegistry m_registry;
private volatile LogService m_logService;
-
+
public void start() {
m_logService.log(LogService.LOG_DEBUG, "OAuth Service Consumer
registry REST service started.");
}
-
+
/**
* REST interface: GET
/rest/services/oauth/consumers/oauth/consumers/{consumerKey}
* Returns the requested consumer in application/xml or application/json
format.
+ *
* @param consumerKey The key of the consumer to retrieve.
* @return The consumer matching the key in xml or json format
*/
@GET
- @Path("{consumerKey}")
- @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
+ @Path("{consumerKey}")
+ @Produces( { MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
public OAuthServiceConsumer getConsumer(@PathParam("consumerKey") final
String consumerKey, @Context UriInfo uriInfo) {
try {
return
OAuthServiceConsumerBean.copy(m_registry.getConsumer(consumerKey), uriInfo);
@@ -77,14 +80,15 @@
throw new WebApplicationException(e,
Response.Status.INTERNAL_SERVER_ERROR);
}
}
-
+
/**
* REST interface: PUT /rest/services/oauth/consumers/oauth/consumers
* Adds a new consumer with the properties of the posted values in
application/xml or application/json format.
+ *
* @return The http response object
*/
@PUT
- @Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
+ @Consumes( { MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
public Response addConsumer(OAuthServiceConsumerBean consumer) {
try {
m_registry.addConsumer(consumer);
@@ -94,16 +98,17 @@
throw new WebApplicationException(Response.Status.NOT_MODIFIED);
}
}
-
+
/**
* REST interface: PUT
/rest/services/oauth/consumers/oauth/consumers/{consumerKey}
* Updates an existing consumer with the properties of the posted values
in application/xml or application/json format.
+ *
* @param consumerKey The key of the consumer to update.
* @return The http response object
*/
@PUT
- @Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
- @Path("{consumerKey}")
+ @Consumes( { MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+ @Path("{consumerKey}")
public Response updateConsumer(@PathParam("consumerKey") final String
consumerKey, OAuthServiceConsumerBean consumer) {
try {
m_registry.updateConsumer(consumer);
@@ -113,14 +118,15 @@
throw new WebApplicationException(Response.Status.NOT_FOUND);
}
}
-
-
+
/**
* REST interface: PUT /rest/services/oauth/consumers/oauth/consumers
* Adds a new consumer with the properties of the posted values in
application/xml or application/json format.
+ *
* @return The http response object
*/
@DELETE
+ @Path("{consumerKey}")
public Response deleteConsumer(@PathParam("consumerKey") final String
consumerKey) {
try {
m_registry.removeConsumer(m_registry.getConsumer(consumerKey));
Modified:
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/service/OAuthServiceProviderImpl.java
==============================================================================
---
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/service/OAuthServiceProviderImpl.java
(original)
+++
trunk/amdatu-authentication/oauth-server/src/main/java/org/amdatu/authentication/oauth/server/service/OAuthServiceProviderImpl.java
Thu Dec 2 15:47:28 2010
@@ -21,6 +21,7 @@
import org.amdatu.authentication.oauth.api.OAuthServiceProvider;
import org.amdatu.authentication.oauth.server.OAuthAccessTokenServlet;
import org.amdatu.authentication.oauth.server.OAuthAuthorizeTokenServlet;
+import static org.amdatu.authentication.oauth.server.OAuthServerConfig.*;
import org.osgi.service.cm.ConfigurationException;
import org.osgi.service.cm.ManagedService;
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
Thu Dec 2 15:47:28 2010
@@ -89,6 +89,8 @@
}
public OAuthValidator getOAuthValidator() {
+ // 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;
}
Added:
trunk/amdatu-core/config-filebased/src/main/resources/conf/org.amdatu.authentication.oauth.server.cfg
==============================================================================
--- (empty file)
+++
trunk/amdatu-core/config-filebased/src/main/resources/conf/org.amdatu.authentication.oauth.server.cfg
Thu Dec 2 15:47:28 2010
@@ -0,0 +1,3 @@
+# The hostname and portnr
+hostname=${server.hostname}
+portnr=${server.port}
\ No newline at end of file
Modified: trunk/amdatu-release/pom.xml
==============================================================================
--- trunk/amdatu-release/pom.xml (original)
+++ trunk/amdatu-release/pom.xml Thu Dec 2 15:47:28 2010
@@ -11,6 +11,29 @@
<name>Amdatu Release</name>
<dependencies>
+ <!-- Authentication bundles -->
+ <dependency>
+ <groupId>org.amdatu.authentication.oauth</groupId>
+ <artifactId>api</artifactId>
+ <version>${platform.version}</version>
+ <scope>compile</scope>
+ <type>bundle</type>
+ </dependency>
+ <dependency>
+ <groupId>org.amdatu.authentication.oauth</groupId>
+ <artifactId>server</artifactId>
+ <version>${platform.version}</version>
+ <scope>compile</scope>
+ <type>bundle</type>
+ </dependency>
+ <dependency>
+ <groupId>org.amdatu.authentication.oauth</groupId>
+ <artifactId>client</artifactId>
+ <version>${platform.version}</version>
+ <scope>compile</scope>
+ <type>bundle</type>
+ </dependency>
+
<!-- Authorization bundles -->
<dependency>
<groupId>org.amdatu.authorization.login</groupId>
Modified: trunk/amdatu-release/src/main/assembly/bin-component.xml
==============================================================================
--- trunk/amdatu-release/src/main/assembly/bin-component.xml (original)
+++ trunk/amdatu-release/src/main/assembly/bin-component.xml Thu Dec 2
15:47:28 2010
@@ -13,6 +13,8 @@
<outputFileNameMapping>${artifact.groupId}.${artifact.artifactId}-${artifact.version}.${artifact.extension}
</outputFileNameMapping>
<includes>
+ <include>org.amdatu.authentication:*</include>
+ <include>org.amdatu.authentication.*:*</include>
<include>org.amdatu.authorization:*</include>
<include>org.amdatu.authorization.*:*</include>
<include>org.amdatu.cassandra:*</include>
Modified: trunk/integration-tests/pom.xml
==============================================================================
--- trunk/integration-tests/pom.xml (original)
+++ trunk/integration-tests/pom.xml Thu Dec 2 15:47:28 2010
@@ -175,6 +175,27 @@
<scope>test</scope>
<type>bundle</type>
</dependency>
+ <dependency>
+ <groupId>org.amdatu.authentication.oauth</groupId>
+ <artifactId>api</artifactId>
+ <version>${platform.version}</version>
+ <scope>test</scope>
+ <type>bundle</type>
+ </dependency>
+ <dependency>
+ <groupId>org.amdatu.authentication.oauth</groupId>
+ <artifactId>server</artifactId>
+ <version>${platform.version}</version>
+ <scope>test</scope>
+ <type>bundle</type>
+ </dependency>
+ <dependency>
+ <groupId>org.amdatu.authentication.oauth</groupId>
+ <artifactId>client</artifactId>
+ <version>${platform.version}</version>
+ <scope>test</scope>
+ <type>bundle</type>
+ </dependency>
<dependency>
<groupId>org.apache.felix</groupId>
@@ -242,7 +263,12 @@
<version>${org.apache.sling.commons.osgi.version}</version>
<scope>test</scope>
</dependency>
-
+ <dependency>
+ <groupId>org.json</groupId>
+ <artifactId>json</artifactId>
+ <version>20090211</version>
+ <scope>test</scope>
+ </dependency>
</dependencies>
<build>
Modified:
trunk/integration-tests/src/test/java/org/amdatu/test/integration/base/ConfigProvider.java
==============================================================================
---
trunk/integration-tests/src/test/java/org/amdatu/test/integration/base/ConfigProvider.java
(original)
+++
trunk/integration-tests/src/test/java/org/amdatu/test/integration/base/ConfigProvider.java
Thu Dec 2 15:47:28 2010
@@ -21,6 +21,7 @@
import java.net.URL;
import java.util.Properties;
+import org.amdatu.authentication.oauth.server.OAuthServerConfig;
import org.amdatu.cassandra.application.CassandraConfigurationService;
import org.amdatu.core.config.templates.ConfigTemplateManager;
import org.amdatu.core.tenant.TenantStorageProvider;
@@ -39,6 +40,13 @@
public final static String PORTNR = "3737";
public final static String SECURE_PORTNR = "3738";
+ public void addLogConfig(ConfigurationAdmin configAdmin) throws
IOException {
+ Configuration config =
configAdmin.getConfiguration("org.amdatu.core.loghandler", null);
+ Properties properties = new Properties();
+ properties.put("console.mininum.loglevel", "DEBUG");
+ config.update(properties);
+ }
+
public void addCassandraConfig(ConfigurationAdmin configAdmin) throws
IOException {
Configuration config =
configAdmin.getConfiguration(CassandraConfigurationService.PID, null);
Properties properties = new Properties();
@@ -141,6 +149,14 @@
properties.put(TenantStorageProvider.DATA_DIRECTORY,
"work/useradminstore");
config.update(properties);
}
+
+ public void addOAuthConfig(ConfigurationAdmin configAdmin) throws
IOException {
+ Configuration config =
configAdmin.getConfiguration(OAuthServerConfig.PID, null);
+ Properties properties = new Properties();
+ properties.put(OAuthServerConfig.HOSTNAME, ConfigProvider.HOSTNAME);
+ properties.put(OAuthServerConfig.PORTNR, ConfigProvider.PORTNR);
+ config.update(properties);
+ }
/**
* Wait until the service at the specified URL returns the specified
response code with a timeout as specified.
Modified:
trunk/integration-tests/src/test/java/org/amdatu/test/integration/base/IntegrationTestBase.java
==============================================================================
---
trunk/integration-tests/src/test/java/org/amdatu/test/integration/base/IntegrationTestBase.java
(original)
+++
trunk/integration-tests/src/test/java/org/amdatu/test/integration/base/IntegrationTestBase.java
Thu Dec 2 15:47:28 2010
@@ -28,12 +28,15 @@
import java.io.File;
import java.io.FileFilter;
+import java.io.IOException;
+import java.util.List;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import org.apache.felix.dm.Component;
import org.apache.felix.dm.ComponentStateListener;
import org.apache.felix.dm.DependencyManager;
+import org.apache.felix.dm.ServiceDependency;
import org.apache.felix.dm.tracker.ServiceTracker;
import org.junit.Assert;
import org.junit.Before;
@@ -121,7 +124,7 @@
* Gets a list of Component objects which should be started before
* the test can start. You can include the test class in this too, so
* you can get the services you depend on injected.
- *
+ *
* Note that you <em>can</em> add components to the dependency manager
directly,
* but the test will only wait for them if you return them in this method.
If you do,
* you should not add them to the dependency manager yourself.
@@ -131,7 +134,9 @@
}
@Before
- public void setupTest() {
+ public void setupTest() throws Exception {
+ initConfiguration();
+
m_manager = new DependencyManager(m_bundleContext);
Component[] components = getDependencies(m_manager);
@@ -152,14 +157,36 @@
// And wait for all the services to become active.
try {
if (!semaphore.tryAcquire(SERVICE_TIMEOUT, TimeUnit.SECONDS)) {
+ // Generate more background information about the exact
services that were missing.
+ String moreInfo = "";
+ for (Component component : components) {
+ if (component.getService() == null) {
+ moreInfo = "\nComponent that failed to start: " +
component;
+ List<ServiceDependency> dependencies =
component.getDependencies();
+ for (ServiceDependency dependency : dependencies) {
+ if (dependency.getState() ==
ServiceDependency.STATE_UNAVAILABLE_REQUIRED) {
+ moreInfo += "\nThe component depends on the
following unavailable service: " + dependency.getName();
+ }
+ }
+ }
+ }
+
Assert.fail("Timed out waiting for all services to get
started, still "
- + (1 - semaphore.availablePermits()) + " to go.");
+ + (1 - semaphore.availablePermits()) + " to go." +
moreInfo);
}
}
catch (InterruptedException e) {
Assert.fail("Interrupted while waiting for services to get
started.");
}
}
+
+ /**
+ * Override to provide the initial configuration. Configuration must be
provided before
+ * service dependencies are provided since some managed services can only
start when their
+ * config has been provided.
+ */
+ protected void initConfiguration() throws IOException {
+ }
/**
* Helper class that releases the given semaphore when each service it is
@@ -300,6 +327,18 @@
return
mavenBundle().groupId("org.amdatu.web").artifactId("httpcontext").versionAsInProject();
}
+ protected static MavenArtifactProvisionOption amdatuOAuthAPI() {
+ return
mavenBundle().groupId("org.amdatu.authentication.oauth").artifactId("api").versionAsInProject();
+ }
+
+ protected static MavenArtifactProvisionOption amdatuOAuthClient() {
+ return
mavenBundle().groupId("org.amdatu.authentication.oauth").artifactId("client").versionAsInProject();
+ }
+
+ protected static MavenArtifactProvisionOption amdatuOAuthServer() {
+ return
mavenBundle().groupId("org.amdatu.authentication.oauth").artifactId("server").versionAsInProject();
+ }
+
protected static MavenArtifactProvisionOption fileBasedConfiguration() {
return
mavenBundle().groupId("org.amdatu.core.config").artifactId("filebased").versionAsInProject();
}
@@ -387,6 +426,10 @@
return
wrappedBundle(mavenBundle().groupId("commons-codec").artifactId("commons-codec"));
}
+ protected static WrappedUrlProvisionOption json() {
+ return
wrappedBundle(mavenBundle().groupId("org.json").artifactId("json").versionAsInProject());
+ }
+
protected static WrappedUrlProvisionOption javaxServlet() {
// We need to create a bundle holding the 2.3 servlet API (required by
SLF4J used by Cassandra) if the http service
// is not deployed. Since the org.osgi.compendium_4 and other bundles
include javax.servlet with explicit version
Added:
trunk/integration-tests/src/test/java/org/amdatu/test/integration/mock/OAuthProtectedTestServlet.java
==============================================================================
--- (empty file)
+++
trunk/integration-tests/src/test/java/org/amdatu/test/integration/mock/OAuthProtectedTestServlet.java
Thu Dec 2 15:47:28 2010
@@ -0,0 +1,87 @@
+/*
+ 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.mock;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.net.URISyntaxException;
+
+import javax.servlet.Servlet;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import net.oauth.OAuthAccessor;
+import net.oauth.OAuthException;
+import net.oauth.OAuthMessage;
+import net.oauth.OAuthProblemException;
+import net.oauth.server.OAuthServlet;
+
+import org.amdatu.authentication.oauth.server.OAuthTokenProvider;
+import org.osgi.service.log.LogService;
+
+public class OAuthProtectedTestServlet extends HttpServlet implements Servlet {
+ // The serial version UID of thi servlet
+ private static final long serialVersionUID = 8834974378869705614L;
+
+ public static final String SERVLET_ALIAS = "/test/oauth/protectedresource";
+
+ private volatile LogService m_logService;
+ private volatile OAuthTokenProvider m_tokenProvider;
+
+ public void doGet(HttpServletRequest request, HttpServletResponse response)
+ throws IOException, ServletException {
+ processRequest(request, response);
+ }
+
+ public void doPost(HttpServletRequest request, HttpServletResponse
response)
+ throws IOException, ServletException {
+ processRequest(request, response);
+ }
+
+ public void processRequest(HttpServletRequest request, HttpServletResponse
response)
+ throws IOException, ServletException {
+ m_logService.log(LogService.LOG_DEBUG, "Protected resource test
servlet received incoming request, validating token");
+
+ try {
+ // Validate the token
+ OAuthMessage requestMessage = OAuthServlet.getMessage(request,
null);
+ OAuthAccessor accessor =
m_tokenProvider.getAccessor(requestMessage);
+
m_tokenProvider.getOAuthValidator().validateMessage(requestMessage, accessor);
+ String userId = (String) accessor.getProperty("user");
+
+ response.setContentType("text/plain");
+ PrintWriter out = null;
+ try {
+ out = response.getWriter();
+ out.print("userid=" + userId);
+ } finally {
+ out.close();
+ }
+ }
+ catch (OAuthProblemException e) {
+ throw new ServletException(e);
+ }
+ catch (OAuthException e) {
+ throw new ServletException(e);
+ }
+ catch (URISyntaxException e) {
+ throw new ServletException(e);
+ }
+ }
+}
Added:
trunk/integration-tests/src/test/java/org/amdatu/test/integration/mock/OAuthTestConsumer.java
==============================================================================
--- (empty file)
+++
trunk/integration-tests/src/test/java/org/amdatu/test/integration/mock/OAuthTestConsumer.java
Thu Dec 2 15:47:28 2010
@@ -0,0 +1,113 @@
+/*
+ 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.mock;
+
+import org.amdatu.authentication.oauth.api.OAuthServiceConsumer;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.json.XML;
+
+public class OAuthTestConsumer implements OAuthServiceConsumer {
+ // Defaults
+ public final static String DEFAULT_CONSUMER_NAME = "Integration Test
Consumer inc.";
+ public final static String DEFAULT_CONSUMER_KEY =
"IntegrationTestConsumerKey";
+ public final static String DEFAULT_CONSUMER_SECRET =
"IntegrationTestConsumerSecret";
+ public final static String DEFAULT_CALLBACK_URL =
"http://localhost/dummy/callback/url";
+
+ // Instance variables
+ private String m_name = DEFAULT_CONSUMER_NAME;
+ private String m_consumerKey = DEFAULT_CONSUMER_KEY;
+ private String m_consumerSecret = DEFAULT_CONSUMER_SECRET;
+ private String m_callbackUrl = DEFAULT_CALLBACK_URL;
+
+ public void setName(String name) {
+ m_name = name;
+ }
+ public String getName() {
+ return m_name;
+ }
+
+ public void setCallbackUrl(String callbackUrl) {
+ m_callbackUrl = callbackUrl;
+ }
+
+ public String getCallbackUrl() {
+ return m_callbackUrl;
+ }
+
+ public void setConsumerKey(String consumerKey) {
+ m_consumerKey = consumerKey;
+ }
+
+ public String getConsumerKey() {
+ return m_consumerKey;
+ }
+
+ public void setConsumerSecret(String consumerSecret) {
+ m_consumerSecret = consumerSecret;
+ }
+
+ public String getConsumerSecret() {
+ return m_consumerSecret;
+ }
+
+ public JSONObject toJson() throws JSONException {
+ JSONObject consumer = new JSONObject();
+ consumer.put("name", getName());
+ consumer.put("callbackUrl", getCallbackUrl());
+ consumer.put("consumerKey", getConsumerKey());
+ consumer.put("consumerSecret", getConsumerSecret());
+ return new JSONObject().put("consumer", consumer);
+ }
+
+ public String toXML() throws JSONException {
+ JSONObject consumer = toJson();
+ return XML.toString(consumer);
+ }
+
+ public static OAuthTestConsumer fromJson(String json) throws JSONException
{
+ JSONObject jsonObject = new JSONObject(json).getJSONObject("consumer");
+ OAuthTestConsumer consumer = new OAuthTestConsumer();
+ consumer.setName(jsonObject.getString("name"));
+ consumer.setConsumerKey(jsonObject.getString("consumerKey"));
+ consumer.setConsumerSecret(jsonObject.getString("consumerSecret"));
+ consumer.setCallbackUrl(jsonObject.getString("callbackUrl"));
+ return consumer;
+ }
+
+ public static OAuthTestConsumer fromXML(String xml) throws JSONException {
+ return fromJson(XML.toJSONObject(xml).toString());
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof OAuthTestConsumer)) {
+ return false;
+ }
+ OAuthTestConsumer consumer = (OAuthTestConsumer) obj;
+ return consumer.getName().equals(getName())
+ && consumer.getConsumerKey().equals(getConsumerKey())
+ && consumer.getConsumerSecret().equals(getConsumerSecret())
+ && consumer.getCallbackUrl().equals(getCallbackUrl());
+ }
+
+ @Override
+ public String toString() {
+ return "Test consumer: name=" + getName() + ", key=" +
getConsumerKey() + ", secret="
+ + getConsumerSecret() + ", callbackurl=" + getCallbackUrl();
+ }
+}
Added:
trunk/integration-tests/src/test/java/org/amdatu/test/integration/tests/OAuthClientTest.java
==============================================================================
--- (empty file)
+++
trunk/integration-tests/src/test/java/org/amdatu/test/integration/tests/OAuthClientTest.java
Thu Dec 2 15:47:28 2010
@@ -0,0 +1,206 @@
+/*
+ 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.ops4j.pax.exam.CoreOptions.provision;
+
+import java.io.IOException;
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+import javax.servlet.Servlet;
+
+import net.oauth.OAuth;
+import net.oauth.OAuthAccessor;
+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.OAuthServiceProvider;
+import org.amdatu.authentication.oauth.client.OAuthResourceOwnerClient;
+import org.amdatu.authentication.oauth.client.OAuthServiceConsumerClient;
+import org.amdatu.authentication.oauth.server.OAuthRequestTokenServlet;
+import org.amdatu.authentication.oauth.server.OAuthTokenProvider;
+import org.amdatu.test.integration.base.ConfigProvider;
+import org.amdatu.test.integration.base.IntegrationTestBase;
+import org.amdatu.test.integration.mock.OAuthProtectedTestServlet;
+import org.amdatu.test.integration.mock.OAuthTestConsumer;
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.DependencyManager;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.junit.Configuration;
+import org.ops4j.pax.exam.junit.JUnit4TestRunner;
+import org.osgi.service.cm.ConfigurationAdmin;
+import org.osgi.service.log.LogService;
+
+ at RunWith(JUnit4TestRunner.class)
+public class OAuthClientTest extends IntegrationTestBase {
+ private volatile DependencyManager m_dependencyManager;
+ private volatile LogService m_logService;
+ private volatile OAuthTokenProvider m_tokenProvider;
+ private volatile OAuthServiceProvider m_oAuthServiceProvider;
+ private volatile ConfigurationAdmin m_configAdmin;
+
+ @Configuration
+ public Option[] configure() {
+ return super.configure();
+ }
+
+ protected void initConfiguration() throws IOException {
+ m_configAdmin = getService(ConfigurationAdmin.class);
+
+ // Add cassandra and templates configs
+ ConfigProvider configProvider = new ConfigProvider();
+ configProvider.addHttpServiceConfig(m_configAdmin);
+ configProvider.addOAuthConfig(m_configAdmin);
+ configProvider.addLogConfig(m_configAdmin);
+ }
+
+ protected Component[] getDependencies(DependencyManager manager) {
+ // Now register a test servlet
+ OAuthProtectedTestServlet m_testServlet = new
OAuthProtectedTestServlet();
+ Dictionary<String, String> servletProperties = new Hashtable<String,
String>();
+ servletProperties.put("alias",
OAuthProtectedTestServlet.SERVLET_ALIAS);
+ servletProperties.put("contextId",
OAuthProtectedTestServlet.SERVLET_ALIAS);
+ Component servletComponent = manager.createComponent()
+ .setImplementation(m_testServlet)
+ .setInterface(new String[] { Servlet.class.getName() },
servletProperties)
+
.add(manager.createServiceDependency().setService(LogService.class).setRequired(true))
+
.add(manager.createServiceDependency().setService(OAuthTokenProvider.class).setRequired(true));
+
+ Component testComponent = manager.createComponent()
+ .setImplementation(this)
+
.add(manager.createServiceDependency().setService(OAuthRequestTokenServlet.class).setRequired(true))
+
.add(manager.createServiceDependency().setService(OAuthTokenProvider.class).setRequired(true))
+
.add(manager.createServiceDependency().setService(OAuthServiceProvider.class).setRequired(true))
+
.add(manager.createServiceDependency().setService(ConfigurationAdmin.class).setRequired(true))
+
.add(manager.createServiceDependency().setService(LogService.class).setRequired(true));
+
+ return new Component[] { servletComponent, testComponent };
+ }
+
+ protected Option provisionBundles() {
+ return provision(
+ felixHttpServiceJetty(),
+ felixHttpServiceWhiteboard(),
+ slingMime(),
+ slingCommons(),
+ commonsCodec(),
+ commonsLogging(),
+ commonsHttpClient(),
+ paxSwissbox(),
+ ops4jBaseLang(),
+ json(),
+ amdatuHttpContext(),
+ amdatuJaxRs(),
+ amdatuOAuthAPI(),
+ amdatuOAuthClient(),
+ amdatuOAuthServer(),
+ amdatuJspSupport());
+ }
+
+ @Test
+ // Test the three-legged oAuth dance
+ public void testThreeLeggedOAuth() throws Exception {
+ // Step 1: Register a service consumer
+ m_logService.log(LogService.LOG_DEBUG, "*** Step 1: Register service
consumer ***");
+ OAuthServiceConsumer consumer = registerServiceConsumer();
+
+ // Step 2: Create an OAuthClient for our Amdatu OAuth server
+ m_logService.log(LogService.LOG_DEBUG, "*** Step 2: Create OAuth
Clients ***");
+ OAuthServiceConsumerClient consumerClient = new
OAuthServiceConsumerClient(m_oAuthServiceProvider, consumer);
+ OAuthResourceOwnerClient userClient = new
OAuthResourceOwnerClient(m_oAuthServiceProvider, consumer);
+
+ // Step 3: Generate a request token for our service consumer
+ m_logService.log(LogService.LOG_DEBUG, "*** Step 3: Generate request
token ***");
+ OAuthAccessor accessor = createRequestToken(consumerClient);
+
+ // 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");
+
Assert.assertTrue(callback.startsWith(OAuthTestConsumer.DEFAULT_CALLBACK_URL +
"?oauth_token="));
+ m_logService.log(LogService.LOG_DEBUG, "Callback URL received: " +
callback);
+
+ // Step 5: Exchange our request token for an access token
+ m_logService.log(LogService.LOG_DEBUG, "*** Step 5: Get access token
***");
+ OAuthMessage message = consumerClient.getAccessToken(accessor);
+ accessor.accessToken = message.getToken();
+ accessor.tokenSecret = message.getParameter("oauth_token_secret");
+ accessor.requestToken = null;
+ m_logService.log(LogService.LOG_DEBUG, "Access token received: " +
accessor.accessToken + ", with secret " + accessor.tokenSecret);
+
+ // Step 6: Access a protected resource
+ m_logService.log(LogService.LOG_DEBUG, "*** Step 6: Access protected
resource ***");
+ String url = "http://" + ConfigProvider.HOSTNAME + ":" +
ConfigProvider.PORTNR + OAuthProtectedTestServlet.SERVLET_ALIAS;
+ message = consumerClient.accessResource(accessor, url);
+ String body = message.readBodyAsString();
+ m_logService.log(LogService.LOG_DEBUG, "Protected resource returns
response: '" + body + "'");
+ Assert.assertTrue(body.equals("userid=ivol"));
+ }
+
+ // Step 1: Register a service consumer
+ private OAuthServiceConsumer registerServiceConsumer() 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;
+ }
+
+ // Step 3: 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;
+ }
+}
\ No newline at end of file
Added:
trunk/integration-tests/src/test/java/org/amdatu/test/integration/tests/OAuthServiceConsumerRegistryTest.java
==============================================================================
--- (empty file)
+++
trunk/integration-tests/src/test/java/org/amdatu/test/integration/tests/OAuthServiceConsumerRegistryTest.java
Thu Dec 2 15:47:28 2010
@@ -0,0 +1,220 @@
+/*
+ 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.ops4j.pax.exam.CoreOptions.provision;
+
+import java.io.IOException;
+
+import org.amdatu.authentication.oauth.server.OAuthServiceConsumerRegistry;
+import org.amdatu.test.integration.base.ConfigProvider;
+import org.amdatu.test.integration.base.IntegrationTestBase;
+import org.amdatu.test.integration.mock.OAuthTestConsumer;
+import org.apache.commons.httpclient.HttpClient;
+import org.apache.commons.httpclient.HttpException;
+import org.apache.commons.httpclient.methods.DeleteMethod;
+import org.apache.commons.httpclient.methods.GetMethod;
+import org.apache.commons.httpclient.methods.PutMethod;
+import org.apache.commons.httpclient.methods.RequestEntity;
+import org.apache.commons.httpclient.methods.StringRequestEntity;
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.DependencyManager;
+import org.apache.http.HttpStatus;
+import org.json.JSONException;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.junit.Configuration;
+import org.ops4j.pax.exam.junit.JUnit4TestRunner;
+import org.osgi.service.cm.ConfigurationAdmin;
+import org.osgi.service.log.LogService;
+
+ at RunWith(JUnit4TestRunner.class)
+public class OAuthServiceConsumerRegistryTest extends IntegrationTestBase {
+ private final static String CONSUMERS_REST_RESOURCE =
"/rest/services/oauth/consumers/oauth/consumers";
+
+ private volatile LogService m_logService;
+ private volatile ConfigurationAdmin m_configAdmin;
+
+ private String m_baseUrl;
+
+ @Configuration
+ public Option[] configure() {
+ return super.configure();
+ }
+
+ protected void initConfiguration() throws IOException {
+ m_configAdmin = getService(ConfigurationAdmin.class);
+
+ // Add cassandra and templates configs
+ ConfigProvider configProvider = new ConfigProvider();
+ configProvider.addHttpServiceConfig(m_configAdmin);
+ configProvider.addOAuthConfig(m_configAdmin);
+ configProvider.addLogConfig(m_configAdmin);
+ }
+
+ protected Component[] getDependencies(DependencyManager manager) {
+ Component testComponent = manager.createComponent()
+ .setImplementation(this)
+
.add(manager.createServiceDependency().setService(ConfigurationAdmin.class).setRequired(true))
+
.add(manager.createServiceDependency().setService(OAuthServiceConsumerRegistry.class).setRequired(true))
+
.add(manager.createServiceDependency().setService(LogService.class).setRequired(true));
+
+ return new Component[] { testComponent };
+ }
+
+ protected Option provisionBundles() {
+ return provision(
+ felixHttpServiceJetty(),
+ felixHttpServiceWhiteboard(),
+ slingMime(),
+ slingCommons(),
+ json(),
+ commonsCodec(),
+ commonsLogging(),
+ commonsHttpClient(),
+ paxSwissbox(),
+ ops4jBaseLang(),
+ amdatuWink(),
+ amdatuHttpContext(),
+ amdatuJaxRs(),
+ amdatuOAuthAPI(),
+ amdatuOAuthClient(),
+ amdatuOAuthServer(),
+ amdatuJspSupport());
+ }
+
+ @Test
+ // Test the REST service that provides CRUD operations on the consumer
registry of the oAuth server
+ public void testRestService() throws Exception {
+ m_baseUrl = "http://" + ConfigProvider.HOSTNAME + ":" +
ConfigProvider.PORTNR;
+ m_logService.log(LogService.LOG_DEBUG, "Base URL = " + m_baseUrl);
+
+ HttpClient httpClient = new HttpClient();
+
+ // First add a new consumer using the JSON format
+ OAuthTestConsumer consumer = new OAuthTestConsumer();
+ int statusCode = putConsumer(httpClient, "application/json", consumer,
false);
+ Assert.assertTrue("OAuth Service Consumer registry REST service
returns " + statusCode + " on addConsumer",
+ statusCode == HttpStatus.SC_OK);
+
+ // Retrieve the new consumer in XML and JSON format
+ OAuthTestConsumer testConsumer = getConsumer(httpClient,
"application/json", consumer.getConsumerKey());
+ Assert.assertTrue("Returned JSON consumer is incorrect: " +
testConsumer.toString(),
+ consumer.equals(testConsumer));
+ testConsumer = getConsumer(httpClient, "application/xml",
consumer.getConsumerKey());
+ Assert.assertTrue("Returned XML consumer is incorrect",
+ consumer.equals(testConsumer));
+
+ // Now try to add another consumer using the Atom XML format, this
should result in a 304 since the consumer
+ // already exists
+ statusCode = putConsumer(httpClient, "application/json", consumer,
false);
+ Assert.assertTrue("OAuth Service Consumer registry REST service
returns " + statusCode + " on addConsumer",
+ statusCode == HttpStatus.SC_NOT_MODIFIED);
+
+ // Now update the test consumer
+ consumer.setConsumerSecret("new " +
OAuthTestConsumer.DEFAULT_CONSUMER_SECRET);
+ consumer.setCallbackUrl("new " +
OAuthTestConsumer.DEFAULT_CALLBACK_URL);
+ consumer.setName("new " + OAuthTestConsumer.DEFAULT_CONSUMER_NAME);
+ statusCode = putConsumer(httpClient, "application/json", consumer,
true);
+ Assert.assertTrue("OAuth Service Consumer registry REST service
returns " + statusCode + " on updateConsumer",
+ statusCode == HttpStatus.SC_OK);
+
+ // And check if the update was handled properly
+ testConsumer = getConsumer(httpClient, "application/json",
consumer.getConsumerKey());
+ Assert.assertTrue("Returned JSON consumer is incorrect: " +
testConsumer.toString(),
+ consumer.equals(testConsumer));
+ testConsumer = getConsumer(httpClient, "application/xml",
consumer.getConsumerKey());
+ Assert.assertTrue("Returned XML consumer is incorrect",
+ consumer.equals(testConsumer));
+
+ // Now delete our test consumer
+ statusCode = deleteConsumer(httpClient, "application/json",
consumer.getConsumerKey());
+ Assert.assertTrue("OAuth Service Consumer registry REST service
returns " + statusCode + " on deleteConsumer",
+ statusCode == HttpStatus.SC_OK);
+ }
+
+ private OAuthTestConsumer getConsumer(HttpClient httpClient, String
mimeType, String consumerKey) throws HttpException, IOException, JSONException {
+ String url = m_baseUrl + CONSUMERS_REST_RESOURCE;
+ GetMethod getMethod = new GetMethod(url + "/" + consumerKey);
+ try {
+ // We want JSON!
+ getMethod.setRequestHeader("Accept", mimeType);
+ int statusCode = httpClient.executeMethod(getMethod);
+ Assert.assertTrue("OAuth Service Consumer registry REST service
returns " + statusCode + " on getConsumer",
+ statusCode == HttpStatus.SC_OK);
+ String body = new String(getMethod.getResponseBody(), "UTF-8");
+ m_logService.log(LogService.LOG_DEBUG, "Returned content for
getConsumer in format " + mimeType + ": " + body);
+ if ("application/json".equals(mimeType)) {
+ return OAuthTestConsumer.fromJson(body);
+ } else if ("application/xml".equals(mimeType)) {
+ return OAuthTestConsumer.fromXML(body);
+ } else {
+ return null;
+ }
+ }
+ finally {
+ // Release the connection.
+ getMethod.releaseConnection();
+ }
+ }
+
+ private int putConsumer(HttpClient httpClient, String mimeType,
OAuthTestConsumer consumer, boolean update) throws JSONException,
HttpException, IOException {
+ String url = m_baseUrl + CONSUMERS_REST_RESOURCE;
+ PutMethod method;
+ if (update) {
+ method = new PutMethod(url + "/" + consumer.getConsumerKey());
+ } else {
+ method = new PutMethod(url);
+ }
+ String body = null;
+ if ("application/xml".equals(mimeType)) {
+ body = consumer.toXML();
+ } else if ("application/json".equals(mimeType)) {
+ body = consumer.toJson().toString();
+ }
+ m_logService.log(LogService.LOG_DEBUG, "Adding consumer for " +
mimeType + ", input=" + body);
+ RequestEntity requestEntity = new StringRequestEntity(body, mimeType,
"UTF-8");
+ method.setRequestEntity(requestEntity);
+
+ // Execute the method, this should return a 200
+ try {
+ method.setRequestHeader("Content-type", mimeType);
+ return httpClient.executeMethod(method);
+ }
+ finally {
+ // Release the connection.
+ method.releaseConnection();
+ }
+ }
+
+ private int deleteConsumer(HttpClient httpClient, String mimeType, String
consumerKey) throws JSONException, HttpException, IOException {
+ String url = m_baseUrl + CONSUMERS_REST_RESOURCE;
+ DeleteMethod method = new DeleteMethod(url + "/" + consumerKey);
+ m_logService.log(LogService.LOG_DEBUG, "Deleting consumer for " +
mimeType + ", input=" + consumerKey);
+
+ // Execute the method, this should return a 200
+ try {
+ return httpClient.executeMethod(method);
+ }
+ finally {
+ // Release the connection.
+ method.releaseConnection();
+ }
+ }
+}
Modified: trunk/pom.xml
==============================================================================
--- trunk/pom.xml (original)
+++ trunk/pom.xml Thu Dec 2 15:47:28 2010
@@ -346,6 +346,7 @@
<modules>
<!-- AMDATU-157 buildsupport must be first in reactor -->
<module>amdatu-buildsupport</module>
+ <module>amdatu-authentication</module>
<module>amdatu-authorization</module>
<module>amdatu-cassandra</module>
<module>amdatu-core</module>
Modified: trunk/src/main/resources/conf/felix-config.properties
==============================================================================
--- trunk/src/main/resources/conf/felix-config.properties (original)
+++ trunk/src/main/resources/conf/felix-config.properties Thu Dec 2
15:47:28 2010
@@ -77,49 +77,52 @@
# component is the target start level. Any number of these properties
# may be specified for different start levels.
felix.auto.start.1=reference:file:amdatu-system/org.apache.felix.configadmin-1.2.4.jar
\
-
reference:file:amdatu-system/org.apache.felix.dependencymanager-3.0.0-SNAPSHOT.jar
\
-
reference:file:amdatu-system/org.apache.felix.eventadmin-1.2.2.jar \
-
reference:file:amdatu-system/org.apache.felix.fileinstall-3.0.0.jar \
-
reference:file:amdatu-system/org.apache.felix.log-1.0.0.jar \
-
reference:file:amdatu-system/org.apache.felix.main-2.0.5.jar \
-
reference:file:amdatu-system/org.apache.felix.metatype-1.0.4.jar \
-
reference:file:amdatu-system/org.apache.felix.shell.tui-1.4.1.jar \
-
reference:file:amdatu-system/org.apache.felix.shell-1.4.2.jar \
-
reference:file:amdatu-system/org.apache.felix.webconsole-3.1.2.jar \
-
reference:file:amdatu-system/org.apache.sling.commons.mime-2.1.4.jar \
-
reference:file:amdatu-system/org.apache.sling.commons.osgi-2.0.6.jar \
-
reference:file:amdatu-system/org.osgi.compendium-${org.osgi.version}.jar \
-
reference:file:amdatu-system/org.osgi.core-${org.osgi.version}.jar \
-
reference:file:amdatu-system/pax-useradmin-service-0.0.1-SNAPSHOT.jar \
-
reference:file:amdatu-system/org.apache.felix.http.jetty-${org.apache.felix.http.version}.jar
\
-
reference:file:amdatu-system/org.apache.felix.http.whiteboard-${org.apache.felix.http.version}.jar
\
-
reference:file:amdatu-system/pax-swissbox-core-${pax.swissbox.version}.jar \
-
reference:file:amdatu-system/ops4j-base-lang-1.2.2.jar \
-
reference:file:amdatu-system/org.apache.felix.scr-1.6.0.jar
+
reference:file:amdatu-system/org.apache.felix.dependencymanager-3.0.0-SNAPSHOT.jar
\
+ reference:file:amdatu-system/org.apache.felix.eventadmin-1.2.2.jar \
+ reference:file:amdatu-system/org.apache.felix.fileinstall-3.0.0.jar \
+ reference:file:amdatu-system/org.apache.felix.log-1.0.0.jar \
+ reference:file:amdatu-system/org.apache.felix.main-2.0.5.jar \
+ reference:file:amdatu-system/org.apache.felix.metatype-1.0.4.jar \
+ reference:file:amdatu-system/org.apache.felix.shell.tui-1.4.1.jar \
+ reference:file:amdatu-system/org.apache.felix.shell-1.4.2.jar \
+ reference:file:amdatu-system/org.apache.felix.webconsole-3.1.2.jar \
+ reference:file:amdatu-system/org.apache.sling.commons.mime-2.1.4.jar
\
+ reference:file:amdatu-system/org.apache.sling.commons.osgi-2.0.6.jar
\
+
reference:file:amdatu-system/org.osgi.compendium-${org.osgi.version}.jar \
+ reference:file:amdatu-system/org.osgi.core-${org.osgi.version}.jar \
+
reference:file:amdatu-system/pax-useradmin-service-0.0.1-SNAPSHOT.jar \
+
reference:file:amdatu-system/org.apache.felix.http.jetty-${org.apache.felix.http.version}.jar
\
+
reference:file:amdatu-system/org.apache.felix.http.whiteboard-${org.apache.felix.http.version}.jar
\
+
reference:file:amdatu-system/pax-swissbox-core-${pax.swissbox.version}.jar \
+ reference:file:amdatu-system/ops4j-base-lang-1.2.2.jar \
+ reference:file:amdatu-system/org.apache.felix.scr-1.6.0.jar
felix.auto.start.2=reference:file:amdatu-core/org.amdatu.core.config.filebased-${platform.version}.jar
\
-
reference:file:amdatu-application/org.amdatu.cassandra.application-${platform.version}.jar
\
-
reference:file:amdatu-application/org.amdatu.cassandra.listener-${platform.version}.jar
\
-
reference:file:amdatu-application/org.amdatu.cassandra.persistencemanager-${platform.version}.jar
\
-
reference:file:amdatu-core/org.amdatu.core.loghandler-${platform.version}.jar \
-
reference:file:amdatu-core/org.amdatu.core.tenant-${platform.version}.jar \
-
reference:file:amdatu-core/org.amdatu.core.config.templates-${platform.version}.jar
\
-
reference:file:amdatu-application/org.amdatu.cassandra.tenantstore-${platform.version}.jar
\
-
reference:file:amdatu-application/org.amdatu.cassandra.useradminstore-${platform.version}.jar
\
-
reference:file:amdatu-application/org.amdatu.web.rest.jaxrs-${platform.version}.jar
\
-
reference:file:amdatu-application/org.amdatu.web.rest.wink-${platform.version}.jar
+
reference:file:amdatu-application/org.amdatu.cassandra.application-${platform.version}.jar
\
+
reference:file:amdatu-application/org.amdatu.cassandra.listener-${platform.version}.jar
\
+
reference:file:amdatu-application/org.amdatu.cassandra.persistencemanager-${platform.version}.jar
\
+
reference:file:amdatu-core/org.amdatu.core.loghandler-${platform.version}.jar \
+
reference:file:amdatu-core/org.amdatu.core.tenant-${platform.version}.jar \
+
reference:file:amdatu-core/org.amdatu.core.config.templates-${platform.version}.jar
\
+
reference:file:amdatu-application/org.amdatu.cassandra.tenantstore-${platform.version}.jar
\
+
reference:file:amdatu-application/org.amdatu.cassandra.useradminstore-${platform.version}.jar
\
+
reference:file:amdatu-application/org.amdatu.web.rest.jaxrs-${platform.version}.jar
\
+
reference:file:amdatu-application/org.amdatu.web.rest.wink-${platform.version}.jar
felix.auto.start.10=reference:file:amdatu-application/org.amdatu.opensocial.shindig-${platform.version}.jar
\
-
reference:file:amdatu-application/org.amdatu.opensocial.profile-${platform.version}.jar
\
-
reference:file:amdatu-application/org.amdatu.authorization.login.service-${platform.version}.jar
\
-
reference:file:amdatu-application/org.amdatu.web.httpcontext-${platform.version}.jar
\
-
reference:file:amdatu-application/org.amdatu.semanticweb.sesame-${platform.version}.jar
\
-
reference:file:amdatu-application/org.amdatu.opensocial.dashboard-${platform.version}.jar
\
-
reference:file:amdatu-application/org.amdatu.opensocial.gadgetmanagement-${platform.version}.jar
\
-
reference:file:amdatu-application/org.amdatu.web.jsp-${platform.version}.jar \
-
reference:file:amdatu-application/org.amdatu.semanticweb.sparqlendpoint-${platform.version}.jar
\
-
reference:file:amdatu-application/org.amdatu.authorization.login.gadget-${platform.version}.jar
+
reference:file:amdatu-application/org.amdatu.opensocial.profile-${platform.version}.jar
\
+
reference:file:amdatu-application/org.amdatu.authorization.login.service-${platform.version}.jar
\
+
reference:file:amdatu-application/org.amdatu.web.httpcontext-${platform.version}.jar
\
+
reference:file:amdatu-application/org.amdatu.semanticweb.sesame-${platform.version}.jar
\
+
reference:file:amdatu-application/org.amdatu.opensocial.dashboard-${platform.version}.jar
\
+
reference:file:amdatu-application/org.amdatu.opensocial.gadgetmanagement-${platform.version}.jar
\
+
reference:file:amdatu-application/org.amdatu.web.jsp-${platform.version}.jar \
+
reference:file:amdatu-application/org.amdatu.semanticweb.sparqlendpoint-${platform.version}.jar
\
+
reference:file:amdatu-application/org.amdatu.authorization.login.gadget-${platform.version}.jar
\
+
reference:file:amdatu-application/org.amdatu.authentication.oauth.api-${platform.version}.jar
\
+
reference:file:amdatu-application/org.amdatu.authentication.oauth.client-${platform.version}.jar
\
+
reference:file:amdatu-application/org.amdatu.authentication.oauth.server-${platform.version}.jar
felix.auto.start.20=reference:file:amdatu-examples/org.amdatu.example.friends.gadget-${platform.version}.jar
\
-
reference:file:amdatu-examples/org.amdatu.example.course.gadget-${platform.version}.jar
\
-
reference:file:amdatu-examples/org.amdatu.example.course.service-${platform.version}.jar
+
reference:file:amdatu-examples/org.amdatu.example.course.gadget-${platform.version}.jar
\
+
reference:file:amdatu-examples/org.amdatu.example.course.service-${platform.version}.jar
# Sets the initial start level of the framework upon startup.
org.osgi.framework.startlevel.beginning=30