aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSamuel Padgett2012-01-17 15:57:19 (EST)
committerMichael Fiedler2012-01-20 08:53:11 (EST)
commita18d8e575b829042d2ea113be0bf43870c8216d7 (patch)
treedd91d9b06be7b0621fbf1857aeedf88598c42f45
parent5f2e7b8e9b0e2dc9fec4d77a0c23a3f12e6df286 (diff)
downloadorg.eclipse.lyo.server-a18d8e575b829042d2ea113be0bf43870c8216d7.zip
org.eclipse.lyo.server-a18d8e575b829042d2ea113be0bf43870c8216d7.tar.gz
org.eclipse.lyo.server-a18d8e575b829042d2ea113be0bf43870c8216d7.tar.bz2
Bug 368872 - Create webapp framework for writing OAuth providers
Add a framework for basic OAuth support: managing tokens, authorizing users, and validating OAuth requests. Does not add support for managing consumers. Only supports OAuth 1.0 currently. (We should add support for OAuth 1.0a minimally.) This framework can be used by other webapp using Maven overlays. See the sample webapp for an example.
-rw-r--r--org.eclipse.lyo.server.oauth.core/.classpath8
-rw-r--r--org.eclipse.lyo.server.oauth.core/.gitignore1
-rw-r--r--org.eclipse.lyo.server.oauth.core/.project23
-rw-r--r--org.eclipse.lyo.server.oauth.core/.settings/org.eclipse.core.resources.prefs5
-rw-r--r--org.eclipse.lyo.server.oauth.core/.settings/org.eclipse.jdt.core.prefs13
-rw-r--r--org.eclipse.lyo.server.oauth.core/.settings/org.eclipse.m2e.core.prefs5
-rw-r--r--org.eclipse.lyo.server.oauth.core/pom.xml70
-rw-r--r--org.eclipse.lyo.server.oauth.core/src/main/java/org/eclipse/lyo/server/oauth/core/Authentication.java49
-rw-r--r--org.eclipse.lyo.server.oauth.core/src/main/java/org/eclipse/lyo/server/oauth/core/AuthenticationException.java42
-rw-r--r--org.eclipse.lyo.server.oauth.core/src/main/java/org/eclipse/lyo/server/oauth/core/OAuthConfiguration.java134
-rw-r--r--org.eclipse.lyo.server.oauth.core/src/main/java/org/eclipse/lyo/server/oauth/core/OAuthRequest.java127
-rw-r--r--org.eclipse.lyo.server.oauth.core/src/main/java/org/eclipse/lyo/server/oauth/core/consumer/ConsumerRegistry.java66
-rw-r--r--org.eclipse.lyo.server.oauth.core/src/main/java/org/eclipse/lyo/server/oauth/core/consumer/ConsumerStore.java28
-rw-r--r--org.eclipse.lyo.server.oauth.core/src/main/java/org/eclipse/lyo/server/oauth/core/consumer/LyoOAuthConsumer.java88
-rw-r--r--org.eclipse.lyo.server.oauth.core/src/main/java/org/eclipse/lyo/server/oauth/core/token/LRUCache.java38
-rw-r--r--org.eclipse.lyo.server.oauth.core/src/main/java/org/eclipse/lyo/server/oauth/core/token/SimpleTokenStrategy.java176
-rw-r--r--org.eclipse.lyo.server.oauth.core/src/main/java/org/eclipse/lyo/server/oauth/core/token/TokenStrategy.java130
-rw-r--r--org.eclipse.lyo.server.oauth.core/src/test/java/org/eclipse/lyo/server/oauth/provider/core/AppTest.java53
-rw-r--r--org.eclipse.lyo.server.oauth.webapp.sample/.classpath8
-rw-r--r--org.eclipse.lyo.server.oauth.webapp.sample/.gitignore1
-rw-r--r--org.eclipse.lyo.server.oauth.webapp.sample/.project23
-rw-r--r--org.eclipse.lyo.server.oauth.webapp.sample/.settings/org.eclipse.jdt.core.prefs9
-rw-r--r--org.eclipse.lyo.server.oauth.webapp.sample/.settings/org.eclipse.m2e.core.prefs5
-rw-r--r--org.eclipse.lyo.server.oauth.webapp.sample/pom.xml104
-rw-r--r--org.eclipse.lyo.server.oauth.webapp.sample/src/main/java/org/eclipse/lyo/server/oauth/webapp/sample/SecureHelloWorld.java125
-rw-r--r--org.eclipse.lyo.server.oauth.webapp.sample/src/main/resources/jetty.xml25
-rw-r--r--org.eclipse.lyo.server.oauth.webapp.sample/src/main/webapp/WEB-INF/application1
-rw-r--r--org.eclipse.lyo.server.oauth.webapp.sample/src/main/webapp/WEB-INF/web.xml24
-rw-r--r--org.eclipse.lyo.server.oauth.webapp/.classpath8
-rw-r--r--org.eclipse.lyo.server.oauth.webapp/.gitignore1
-rw-r--r--org.eclipse.lyo.server.oauth.webapp/.project23
-rw-r--r--org.eclipse.lyo.server.oauth.webapp/.settings/org.eclipse.jdt.core.prefs9
-rw-r--r--org.eclipse.lyo.server.oauth.webapp/.settings/org.eclipse.m2e.core.prefs5
-rw-r--r--org.eclipse.lyo.server.oauth.webapp/pom.xml79
-rw-r--r--org.eclipse.lyo.server.oauth.webapp/src/main/java/org/eclipse/lyo/server/oauth/webapp/services/OAuthService.java240
-rw-r--r--org.eclipse.lyo.server.oauth.webapp/src/main/webapp/WEB-INF/oauth-services1
-rw-r--r--org.eclipse.lyo.server.oauth.webapp/src/main/webapp/WEB-INF/web.xml22
-rw-r--r--org.eclipse.lyo.server.oauth.webapp/src/main/webapp/oauth/login.js68
-rw-r--r--org.eclipse.lyo.server.oauth.webapp/src/main/webapp/oauth/login.jsp61
-rw-r--r--org.eclipse.lyo.server.oauth.webapp/src/main/webapp/oauth/theme.css24
40 files changed, 1922 insertions, 0 deletions
diff --git a/org.eclipse.lyo.server.oauth.core/.classpath b/org.eclipse.lyo.server.oauth.core/.classpath
new file mode 100644
index 0000000..b9dc392
--- /dev/null
+++ b/org.eclipse.lyo.server.oauth.core/.classpath
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" output="target/classes" path="src/main/java"/>
+ <classpathentry kind="src" output="target/test-classes" path="src/test/java"/>
+ <classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
+ <classpathentry kind="output" path="target/classes"/>
+</classpath>
diff --git a/org.eclipse.lyo.server.oauth.core/.gitignore b/org.eclipse.lyo.server.oauth.core/.gitignore
new file mode 100644
index 0000000..eb5a316
--- /dev/null
+++ b/org.eclipse.lyo.server.oauth.core/.gitignore
@@ -0,0 +1 @@
+target
diff --git a/org.eclipse.lyo.server.oauth.core/.project b/org.eclipse.lyo.server.oauth.core/.project
new file mode 100644
index 0000000..76024df
--- /dev/null
+++ b/org.eclipse.lyo.server.oauth.core/.project
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.eclipse.lyo.server.oauth.core</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.m2e.core.maven2Builder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ <nature>org.eclipse.m2e.core.maven2Nature</nature>
+ </natures>
+</projectDescription>
diff --git a/org.eclipse.lyo.server.oauth.core/.settings/org.eclipse.core.resources.prefs b/org.eclipse.lyo.server.oauth.core/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 0000000..9647881
--- /dev/null
+++ b/org.eclipse.lyo.server.oauth.core/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,5 @@
+#Mon Jan 16 14:19:57 EST 2012
+eclipse.preferences.version=1
+encoding//src/main/java=UTF-8
+encoding//src/test/java=UTF-8
+encoding/<project>=UTF-8
diff --git a/org.eclipse.lyo.server.oauth.core/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.lyo.server.oauth.core/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..2e2beb6
--- /dev/null
+++ b/org.eclipse.lyo.server.oauth.core/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,13 @@
+#Mon Jan 16 14:39:09 EST 2012
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.source=1.6
diff --git a/org.eclipse.lyo.server.oauth.core/.settings/org.eclipse.m2e.core.prefs b/org.eclipse.lyo.server.oauth.core/.settings/org.eclipse.m2e.core.prefs
new file mode 100644
index 0000000..f691649
--- /dev/null
+++ b/org.eclipse.lyo.server.oauth.core/.settings/org.eclipse.m2e.core.prefs
@@ -0,0 +1,5 @@
+#Mon Jan 16 14:19:57 EST 2012
+activeProfiles=
+eclipse.preferences.version=1
+resolveWorkspaceProjects=true
+version=1
diff --git a/org.eclipse.lyo.server.oauth.core/pom.xml b/org.eclipse.lyo.server.oauth.core/pom.xml
new file mode 100644
index 0000000..a3676c4
--- /dev/null
+++ b/org.eclipse.lyo.server.oauth.core/pom.xml
@@ -0,0 +1,70 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <groupId>org.eclipse.lyo.server</groupId>
+ <artifactId>oauth-core</artifactId>
+ <version>0.0.1-SNAPSHOT</version>
+ <packaging>jar</packaging>
+
+ <name>oauth.provider.core</name>
+ <url>http://maven.apache.org</url>
+
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ </properties>
+
+ <repositories>
+ <repository>
+ <id>oauth</id>
+ <url>http://oauth.googlecode.com/svn/code/maven</url>
+ </repository>
+ </repositories>
+
+ <dependencies>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>3.8.1</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.geronimo.specs</groupId>
+ <artifactId>geronimo-servlet_2.5_spec</artifactId>
+ <version>1.2</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>net.oauth.core</groupId>
+ <artifactId>oauth</artifactId>
+ <version>20090617</version>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>net.oauth.core</groupId>
+ <artifactId>oauth-provider</artifactId>
+ <version>20100527</version>
+ <scope>compile</scope>
+ </dependency>
+ </dependencies>
+ <build>
+ <finalName>oauth-core</finalName>
+
+ <outputDirectory>target/classes</outputDirectory>
+
+ <plugins>
+
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>2.3.2</version>
+ <configuration>
+ <source>1.6</source>
+ <target>1.6</target>
+ </configuration>
+ </plugin>
+
+ </plugins>
+
+ </build>
+</project>
diff --git a/org.eclipse.lyo.server.oauth.core/src/main/java/org/eclipse/lyo/server/oauth/core/Authentication.java b/org.eclipse.lyo.server.oauth.core/src/main/java/org/eclipse/lyo/server/oauth/core/Authentication.java
new file mode 100644
index 0000000..35ce4a6
--- /dev/null
+++ b/org.eclipse.lyo.server.oauth.core/src/main/java/org/eclipse/lyo/server/oauth/core/Authentication.java
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * Copyright (c) 2012 IBM Corporation.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v. 1.0 which accompanies this distribution.
+ *
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.lyo.server.oauth.core;
+
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * Handles authentication with the backend system.
+ *
+ * @author Samuel Padgett <spadgett@us.ibm.com>
+ * @see OAuthConfiguration#setAuthentication(Authentication)
+ */
+public interface Authentication {
+ /**
+ * Gets the name of the application to show in the login dialog.
+ *
+ * @return the application name
+ */
+ public String getApplicationName();
+
+ /**
+ * Authenticates with the application. On errors, throws an
+ * {@link AuthenticationException}.
+ *
+ * @param request
+ * the servlet request
+ * @param id
+ * the user's ID
+ * @param password
+ * the user's password
+ * @throws AuthenticationException
+ * if authentication fails
+ */
+ public void login(HttpServletRequest request, String id, String password)
+ throws AuthenticationException;
+}
diff --git a/org.eclipse.lyo.server.oauth.core/src/main/java/org/eclipse/lyo/server/oauth/core/AuthenticationException.java b/org.eclipse.lyo.server.oauth.core/src/main/java/org/eclipse/lyo/server/oauth/core/AuthenticationException.java
new file mode 100644
index 0000000..bf09003
--- /dev/null
+++ b/org.eclipse.lyo.server.oauth.core/src/main/java/org/eclipse/lyo/server/oauth/core/AuthenticationException.java
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright (c) 2012 IBM Corporation.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v. 1.0 which accompanies this distribution.
+ *
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.lyo.server.oauth.core;
+
+/**
+ * An exception indicating that authentication failed.
+ *
+ * @author Samuel Padgett <spadgett@us.ibm.com>
+ * @see Authentication#login(String, char[])
+ */
+public class AuthenticationException extends Exception {
+ private static final long serialVersionUID = -7357859796941279773L;
+
+ public AuthenticationException() {
+ super();
+ }
+
+ public AuthenticationException(String message, Throwable t) {
+ super(message, t);
+ }
+
+ public AuthenticationException(String message) {
+ super(message);
+ }
+
+ public AuthenticationException(Throwable t) {
+ super(t);
+ }
+}
diff --git a/org.eclipse.lyo.server.oauth.core/src/main/java/org/eclipse/lyo/server/oauth/core/OAuthConfiguration.java b/org.eclipse.lyo.server.oauth.core/src/main/java/org/eclipse/lyo/server/oauth/core/OAuthConfiguration.java
new file mode 100644
index 0000000..1f59bb0
--- /dev/null
+++ b/org.eclipse.lyo.server.oauth.core/src/main/java/org/eclipse/lyo/server/oauth/core/OAuthConfiguration.java
@@ -0,0 +1,134 @@
+/*******************************************************************************
+ * Copyright (c) 2012 IBM Corporation.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v. 1.0 which accompanies this distribution.
+ *
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.lyo.server.oauth.core;
+
+import java.io.IOException;
+
+import net.oauth.OAuthValidator;
+import net.oauth.SimpleOAuthValidator;
+
+import org.eclipse.lyo.server.oauth.core.consumer.ConsumerRegistry;
+import org.eclipse.lyo.server.oauth.core.consumer.ConsumerStore;
+import org.eclipse.lyo.server.oauth.core.token.SimpleTokenStrategy;
+import org.eclipse.lyo.server.oauth.core.token.TokenStrategy;
+
+/**
+ * Manages the OAuth provider configuration, including the validator, consumer store, and
+ * token strategy.
+ *
+ * @author Samuel Padgett <spadgett@us.ibm.com>
+ */
+public class OAuthConfiguration {
+ private String realm;
+ private OAuthValidator validator;
+ private TokenStrategy tokenStrategy;
+ private ConsumerStore consumerStore = null;
+ private Authentication authentication = null;
+
+ private static final OAuthConfiguration instance = new OAuthConfiguration();
+
+ public static OAuthConfiguration getInstance() {
+ return instance;
+ }
+
+ private OAuthConfiguration() {
+ realm = "Lyo";
+ validator = new SimpleOAuthValidator();
+ tokenStrategy = new SimpleTokenStrategy();
+ }
+
+ /**
+ * Gets the realm to be included in OAuth problem responses.
+ *
+ * @return the realm
+ */
+ public String getRealm() {
+ return realm;
+ }
+
+ /**
+ * Sets the realm to be included in OAuth problem responses.
+ *
+ * @param realm the realm
+ */
+ public void setRealm(String realm) {
+ this.realm = realm;
+ }
+
+ /**
+ * Gets the OAuth validator for validating request signatures.
+ *
+ * @return the validator
+ */
+ public OAuthValidator getValidator() {
+ return validator;
+ }
+
+ /**
+ * Sets the OAuth validator for validating request signatures.
+ *
+ * @param validator the validator
+ */
+ public void setValidator(OAuthValidator validator) {
+ this.validator = validator;
+ }
+
+ /**
+ * Gets the strategy used to generate and verify OAuth tokens.
+ *
+ * @return the token strategy
+ */
+ public TokenStrategy getTokenStrategy() {
+ return tokenStrategy;
+ }
+
+ /**
+ * Sets the strategy used to generate and verify OAuth tokens.
+ *
+ * @param tokenStrategy the strategy
+ */
+ public void setTokenStrategy(TokenStrategy tokenStrategy) {
+ this.tokenStrategy = tokenStrategy;
+ }
+
+ /**
+ * Gets the store used for managing consumers.
+ *
+ * @return the consumer store
+ */
+ public ConsumerStore getConsumerStore() {
+ return consumerStore;
+ }
+
+ /**
+ * Sets the store used for managing consumers.
+ *
+ * @param consumerStore the consumer store
+ * @throws IOException
+ */
+ public void setConsumerStore(ConsumerStore consumerStore) throws IOException {
+ this.consumerStore = consumerStore;
+ ConsumerRegistry.getInstance().init(consumerStore);
+ }
+
+ public Authentication getAuthentication() {
+ return authentication;
+ }
+
+ public void setAuthentication(Authentication authentication) {
+ this.authentication = authentication;
+ }
+}
diff --git a/org.eclipse.lyo.server.oauth.core/src/main/java/org/eclipse/lyo/server/oauth/core/OAuthRequest.java b/org.eclipse.lyo.server.oauth.core/src/main/java/org/eclipse/lyo/server/oauth/core/OAuthRequest.java
new file mode 100644
index 0000000..0504500
--- /dev/null
+++ b/org.eclipse.lyo.server.oauth.core/src/main/java/org/eclipse/lyo/server/oauth/core/OAuthRequest.java
@@ -0,0 +1,127 @@
+/*******************************************************************************
+ * Copyright (c) 2012 IBM Corporation.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v. 1.0 which accompanies this distribution.
+ *
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.lyo.server.oauth.core;
+
+import java.io.IOException;
+import java.net.URISyntaxException;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+
+import net.oauth.OAuth;
+import net.oauth.OAuthAccessor;
+import net.oauth.OAuthException;
+import net.oauth.OAuthMessage;
+import net.oauth.OAuthProblemException;
+import net.oauth.OAuthValidator;
+import net.oauth.server.OAuthServlet;
+
+import org.eclipse.lyo.server.oauth.core.consumer.ConsumerRegistry;
+import org.eclipse.lyo.server.oauth.core.consumer.LyoOAuthConsumer;
+
+/**
+ * Validates that a request is authorized. The request must contain a valid
+ * access token and pass {@link OAuthValidator} tests. To change the validator
+ * used, call {@link OAuthConfiguration#setValidator(OAuthValidator)}.
+ *
+ * <p>
+ * Usage:
+ *
+ * <pre>
+ * try {
+ * OAuthRequest request = new OAuthRequest(httpRequest);
+ * request.validate();
+ * } catch (OAuthException e) {
+ * // Request failed validation. Send an unauthorized response.
+ * OAuthServlet.handleException(httpResponse, e, OAuthConfiguration
+ * .getInstance().getRealm());
+ * }
+ * </pre>
+ *
+ * @author Samuel Padgett <spadgett@us.ibm.com>
+ */
+public class OAuthRequest {
+ private HttpServletRequest httpRequest;
+ private OAuthMessage message;
+ private OAuthAccessor accessor;
+
+ public OAuthRequest(HttpServletRequest request)
+ throws OAuthProblemException, IOException {
+ this.httpRequest = request;
+ this.message = OAuthServlet.getMessage(httpRequest, null);
+
+ LyoOAuthConsumer consumer = ConsumerRegistry.getInstance().getConsumer(
+ message);
+ if (consumer == null) {
+ throw new OAuthProblemException(
+ OAuth.Problems.CONSUMER_KEY_REJECTED);
+ }
+
+ this.accessor = new OAuthAccessor(consumer);
+
+ // Fill in the token secret if it's there.
+ String token = this.message.getToken();
+ if (token != null) {
+ this.accessor.tokenSecret = OAuthConfiguration.getInstance()
+ .getTokenStrategy().getTokenSecret(this.httpRequest, token);
+ }
+ }
+
+ public HttpServletRequest getHttpRequest() {
+ return httpRequest;
+ }
+
+ public void setHttpRequest(HttpServletRequest httpRequest) {
+ this.httpRequest = httpRequest;
+ }
+
+ public OAuthMessage getMessage() {
+ return message;
+ }
+
+ public OAuthAccessor getAccessor() {
+ return accessor;
+ }
+
+ public LyoOAuthConsumer getConsumer() {
+ return (LyoOAuthConsumer) accessor.consumer;
+ }
+
+ /**
+ * Validates that the request is authorized and throws an OAuth exception if
+ * not. The request must contain a valid access token and pass
+ * {@link OAuthValidator#validateMessage(OAuthMessage, OAuthAccessor)}
+ * checks using the validator set in the {@link OAuthConfiguration}.
+ * <p>
+ * If the request fails validation, you can use
+ * {@link OAuthServlet#handleException(javax.servlet.http.HttpServletResponse, Exception, String)}
+ * to send an unauthorized response.
+ *
+ * @throws URISyntaxException
+ * @throws IOException
+ * @throws OAuthException
+ * if the request fails validation
+ */
+ public void validate() throws OAuthException, IOException, ServletException {
+ try {
+ OAuthConfiguration config = OAuthConfiguration.getInstance();
+ config.getValidator().validateMessage(message, accessor);
+ config.getTokenStrategy().validateAccessToken(this);
+ } catch (URISyntaxException e) {
+ throw new ServletException(e);
+ }
+ }
+}
diff --git a/org.eclipse.lyo.server.oauth.core/src/main/java/org/eclipse/lyo/server/oauth/core/consumer/ConsumerRegistry.java b/org.eclipse.lyo.server.oauth.core/src/main/java/org/eclipse/lyo/server/oauth/core/consumer/ConsumerRegistry.java
new file mode 100644
index 0000000..b0541b9
--- /dev/null
+++ b/org.eclipse.lyo.server.oauth.core/src/main/java/org/eclipse/lyo/server/oauth/core/consumer/ConsumerRegistry.java
@@ -0,0 +1,66 @@
+/*******************************************************************************
+ * Copyright (c) 2012 IBM Corporation.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v. 1.0 which accompanies this distribution.
+ *
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.lyo.server.oauth.core.consumer;
+
+import java.io.IOException;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import net.oauth.OAuth;
+import net.oauth.OAuthMessage;
+import net.oauth.OAuthProblemException;
+
+/**
+ * Manages the list of OAuth consumers.
+ *
+ * @author Samuel Padgett <spadgett@us.ibm.com>
+ */
+public class ConsumerRegistry {
+ private Map<String, LyoOAuthConsumer> consumerMap = Collections
+ .synchronizedMap(new HashMap<String, LyoOAuthConsumer>());
+ private static ConsumerRegistry instance = new ConsumerRegistry();
+
+ public static ConsumerRegistry getInstance() {
+ return instance;
+ }
+
+ private ConsumerRegistry() {}
+
+ public void init(ConsumerStore consumerStore) throws IOException {
+ for (LyoOAuthConsumer consumer : consumerStore.load()) {
+ consumerMap.put(consumer.consumerKey, consumer);
+ }
+ }
+
+ public LyoOAuthConsumer getConsumer(OAuthMessage requestMessage)
+ throws OAuthProblemException, IOException {
+ requestMessage.requireParameters(OAuth.OAUTH_CONSUMER_KEY);
+ return getConsumer(requestMessage.getConsumerKey());
+ }
+
+ public LyoOAuthConsumer getConsumer(String consumerKey) {
+ return consumerMap.get(consumerKey);
+ }
+
+// public LyoOAuthConsumer addConsumer(LyoOAuthConsumer consumer) {
+// return consumerMap.put(consumer.consumerKey, consumer);
+// }
+//
+// public LyoOAuthConsumer removeConsumer(LyoOAuthConsumer consumer) {
+// return consumerMap.remove(consumer);
+// }
+}
diff --git a/org.eclipse.lyo.server.oauth.core/src/main/java/org/eclipse/lyo/server/oauth/core/consumer/ConsumerStore.java b/org.eclipse.lyo.server.oauth.core/src/main/java/org/eclipse/lyo/server/oauth/core/consumer/ConsumerStore.java
new file mode 100644
index 0000000..284be5b
--- /dev/null
+++ b/org.eclipse.lyo.server.oauth.core/src/main/java/org/eclipse/lyo/server/oauth/core/consumer/ConsumerStore.java
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * Copyright (c) 2012 IBM Corporation.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v. 1.0 which accompanies this distribution.
+ *
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.lyo.server.oauth.core.consumer;
+
+import java.io.IOException;
+import java.util.Collection;
+
+/**
+ * Manages persistence of OAuth consumers.
+ *
+ * @author Samuel Padgett <spadgett@us.ibm.com>
+ */
+public interface ConsumerStore {
+ public Collection<LyoOAuthConsumer> load() throws IOException;
+}
diff --git a/org.eclipse.lyo.server.oauth.core/src/main/java/org/eclipse/lyo/server/oauth/core/consumer/LyoOAuthConsumer.java b/org.eclipse.lyo.server.oauth.core/src/main/java/org/eclipse/lyo/server/oauth/core/consumer/LyoOAuthConsumer.java
new file mode 100644
index 0000000..f61a3b0
--- /dev/null
+++ b/org.eclipse.lyo.server.oauth.core/src/main/java/org/eclipse/lyo/server/oauth/core/consumer/LyoOAuthConsumer.java
@@ -0,0 +1,88 @@
+/*******************************************************************************
+ * Copyright (c) 2012 IBM Corporation.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v. 1.0 which accompanies this distribution.
+ *
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.lyo.server.oauth.core.consumer;
+
+import net.oauth.OAuthConsumer;
+import net.oauth.OAuthServiceProvider;
+
+/**
+ * An OAuth consumer with extra properties, including a name and a trusted flag.
+ *
+ * @author Samuel Padgett <spadgett@us.ibm.com>
+ */
+public class LyoOAuthConsumer extends OAuthConsumer {
+ private static final long serialVersionUID = 7634987410903334464L;
+
+ private String name;
+ private boolean trusted = false;
+
+ public LyoOAuthConsumer(String consumerKey, String consumerSecret) {
+ super(null, consumerKey, consumerSecret, null);
+ }
+
+ public LyoOAuthConsumer(String callbackURL, String consumerKey,
+ String consumerSecret) {
+ super(callbackURL, consumerKey, consumerSecret, null);
+ }
+
+ public LyoOAuthConsumer(String callbackURL, String consumerKey,
+ String consumerSecret, OAuthServiceProvider serviceProvider) {
+ super(callbackURL, consumerKey, consumerSecret, serviceProvider);
+ }
+
+ /**
+ * Gets the name of the consumer, which might be shown in the login dialog
+ * and other user interfaces.
+ *
+ * @return the name
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Sets the name of the consumer, which might be shown in the login dialog
+ * and other user interfaces.
+ *
+ * @param name
+ * the name
+ */
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ /**
+ * Answers if this consumer is trusted. If a consumer is trusted, a login
+ * prompt might be skipped if the user is already authenticated with this
+ * web page.
+ *
+ * @return true if the consumer is trusted, false otherwise
+ */
+ public boolean isTrusted() {
+ return trusted;
+ }
+
+ /**
+ * Sets if this consumer is trusted. If a consumer is trusted, a login
+ * prompt might be skipped if the user is already authenticated with this
+ * web page.
+ *
+ * @param trusted true if the consumer is trusted, false otherwise
+ */
+ public void setTrusted(boolean trusted) {
+ this.trusted = trusted;
+ }
+}
diff --git a/org.eclipse.lyo.server.oauth.core/src/main/java/org/eclipse/lyo/server/oauth/core/token/LRUCache.java b/org.eclipse.lyo.server.oauth.core/src/main/java/org/eclipse/lyo/server/oauth/core/token/LRUCache.java
new file mode 100644
index 0000000..20ed287
--- /dev/null
+++ b/org.eclipse.lyo.server.oauth.core/src/main/java/org/eclipse/lyo/server/oauth/core/token/LRUCache.java
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright (c) 2012 IBM Corporation.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v. 1.0 which accompanies this distribution.
+ *
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.lyo.server.oauth.core.token;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ * Least recently used cache for storing OAuth tokens.
+ *
+ * @author Samuel Padgett <spadgett@us.ibm.com>
+ */
+public class LRUCache<K, V> extends LinkedHashMap<K, V> {
+ private static final long serialVersionUID = -3846345693980360667L;
+ private final int max;
+
+ public LRUCache(final int max) {
+ this.max = max;
+ }
+
+ @Override
+ protected boolean removeEldestEntry(final Map.Entry<K, V> eldest) {
+ return super.size() > max;
+ }
+}
diff --git a/org.eclipse.lyo.server.oauth.core/src/main/java/org/eclipse/lyo/server/oauth/core/token/SimpleTokenStrategy.java b/org.eclipse.lyo.server.oauth.core/src/main/java/org/eclipse/lyo/server/oauth/core/token/SimpleTokenStrategy.java
new file mode 100644
index 0000000..93064c3
--- /dev/null
+++ b/org.eclipse.lyo.server.oauth.core/src/main/java/org/eclipse/lyo/server/oauth/core/token/SimpleTokenStrategy.java
@@ -0,0 +1,176 @@
+/*******************************************************************************
+ * Copyright (c) 2012 IBM Corporation.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v. 1.0 which accompanies this distribution.
+ *
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.lyo.server.oauth.core.token;
+
+import java.io.IOException;
+import java.util.Map;
+import java.util.UUID;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.eclipse.lyo.server.oauth.core.OAuthRequest;
+
+import net.oauth.OAuth;
+import net.oauth.OAuthAccessor;
+import net.oauth.OAuthException;
+import net.oauth.OAuthProblemException;
+
+/**
+ * A simple strategy for generating and validating tokens. Generates random
+ * tokens and stores them in memory. Tokens are only good for the life of the
+ * process.
+ *
+ * @author Samuel Padgett <spadgett@us.ibm.com>
+ */
+public class SimpleTokenStrategy implements TokenStrategy {
+ private final static int REQUEST_TOKEN_MAX_ENTIRES = 500;
+ private final static int ACCESS_TOKEN_MAX_ENTRIES = 5000;
+
+ // key is request token, value is boolean indicating if the token is
+ // authorized
+ private Map<String, Boolean> requestTokens;
+
+ // key is access token, value is consumer key
+ private Map<String, String> accessTokens;
+
+ // key is token, value is token secret
+ private Map<String, String> tokenSecrets;
+
+ public SimpleTokenStrategy() {
+ this(REQUEST_TOKEN_MAX_ENTIRES, ACCESS_TOKEN_MAX_ENTRIES);
+ }
+
+ public SimpleTokenStrategy(int requestTokenMaxCount, int accessTokenMaxCount) {
+ requestTokens = new LRUCache<String, Boolean>(requestTokenMaxCount);
+ accessTokens = new LRUCache<String, String>(accessTokenMaxCount);
+ tokenSecrets = new LRUCache<String, String>(requestTokenMaxCount
+ + accessTokenMaxCount);
+ }
+
+ @Override
+ public void generateRequestToken(OAuthRequest oAuthRequest) {
+ OAuthAccessor accessor = oAuthRequest.getAccessor();
+ accessor.requestToken = generateTokenString();
+ accessor.tokenSecret = generateTokenString();
+ synchronized (requestTokens) {
+ requestTokens.put(accessor.requestToken, Boolean.FALSE); // not yet authorized
+ }
+ synchronized (tokenSecrets) {
+ tokenSecrets.put(accessor.requestToken, accessor.tokenSecret);
+ }
+ }
+
+ @Override
+ public String validateRequestToken(OAuthRequest oAuthRequest) throws OAuthException, IOException {
+ String requestToken = oAuthRequest.getMessage().getToken();
+ if (!requestTokens.containsKey(requestToken)) {
+ throw new OAuthProblemException(OAuth.Problems.TOKEN_REJECTED);
+ }
+
+ return requestToken;
+ }
+
+ @Override
+ public void markRequestTokenAuthorized(HttpServletRequest httpRequest,
+ String requestToken) {
+ synchronized (requestTokens) {
+ requestTokens.put(requestToken, Boolean.TRUE);
+ }
+ }
+
+ @Override
+ public boolean isRequestTokenAuthorized(HttpServletRequest httpRequest,
+ String requestToken) {
+ synchronized (requestTokens) {
+ Boolean authorized = requestTokens.get(requestToken);
+ if (authorized == null) {
+ return false;
+ }
+
+ return authorized.booleanValue();
+ }
+ }
+
+ @Override
+ public void generateAccessToken(OAuthRequest oAuthRequest) throws OAuthProblemException,
+ IOException {
+ // Remove the old request token.
+ OAuthAccessor accessor = oAuthRequest.getAccessor();
+ String requestToken = oAuthRequest.getMessage().getToken();
+ synchronized (requestTokens) {
+ if (!isRequestTokenAuthorized(oAuthRequest.getHttpRequest(),
+ requestToken)) {
+ throw new OAuthProblemException(
+ OAuth.Problems.ADDITIONAL_AUTHORIZATION_REQUIRED);
+ }
+
+ requestTokens.remove(requestToken);
+ }
+
+ // Generate a new access token.
+ accessor.accessToken = generateTokenString();
+ synchronized (requestTokens) {
+ accessTokens.put(accessor.accessToken,
+ accessor.consumer.consumerKey);
+ }
+
+ // Remove the old token secret and create a new one for this access
+ // token.
+ accessor.tokenSecret = generateTokenString();
+ synchronized (tokenSecrets) {
+ tokenSecrets.remove(requestToken);
+ tokenSecrets.put(accessor.accessToken, accessor.tokenSecret);
+ }
+
+ accessor.requestToken = null;
+ }
+
+ @Override
+ public void validateAccessToken(OAuthRequest oAuthRequest)
+ throws OAuthException, IOException {
+ synchronized (accessTokens) {
+ String actualValue = accessTokens.get(oAuthRequest.getMessage()
+ .getToken());
+ if (!oAuthRequest.getConsumer().consumerKey.equals(actualValue)) {
+ throw new OAuthProblemException(OAuth.Problems.TOKEN_REJECTED);
+ }
+ }
+ }
+
+ @Override
+ public String getTokenSecret(HttpServletRequest httpRequest, String token)
+ throws OAuthProblemException {
+ synchronized (tokenSecrets) {
+ String tokenSecret = tokenSecrets.get(token);
+ if (tokenSecret == null) {
+ // It's possible the token secret was purged from the LRU cache,
+ // or the token is just not recognized. Either way, we can
+ // consider the token rejected.
+ throw new OAuthProblemException(OAuth.Problems.TOKEN_REJECTED);
+ }
+ return tokenSecret;
+ }
+ }
+
+ /**
+ * Creates a unique, random string to use for tokens.
+ *
+ * @return the random string
+ */
+ protected String generateTokenString() {
+ return UUID.randomUUID().toString();
+ }
+}
diff --git a/org.eclipse.lyo.server.oauth.core/src/main/java/org/eclipse/lyo/server/oauth/core/token/TokenStrategy.java b/org.eclipse.lyo.server.oauth.core/src/main/java/org/eclipse/lyo/server/oauth/core/token/TokenStrategy.java
new file mode 100644
index 0000000..3529640
--- /dev/null
+++ b/org.eclipse.lyo.server.oauth.core/src/main/java/org/eclipse/lyo/server/oauth/core/token/TokenStrategy.java
@@ -0,0 +1,130 @@
+/*******************************************************************************
+ * Copyright (c) 2012 IBM Corporation.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v. 1.0 which accompanies this distribution.
+ *
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.lyo.server.oauth.core.token;
+
+import java.io.IOException;
+
+import javax.servlet.http.HttpServletRequest;
+
+import net.oauth.OAuthAccessor;
+import net.oauth.OAuthException;
+import net.oauth.OAuthProblemException;
+
+import org.eclipse.lyo.server.oauth.core.OAuthRequest;
+
+/**
+ * Manages and validates OAuth tokens and token secrets.
+ * {@link SimpleTokenStrategy} is a basic implementation, but you can implement
+ * this interface to generate and validate OAuth tokens your own way.
+ *
+ * @author Samuel Padgett <spadgett@us.ibm.com>
+ */
+public interface TokenStrategy {
+ /**
+ * Generates a request token and token secret and sets it in the accessor.
+ *
+ * @param oAuthRequest
+ * the OAuth request
+ */
+ public void generateRequestToken(OAuthRequest oAuthRequest);
+
+ /**
+ * Validates that the request token and token secret are valid, throwing an
+ * exception if not.
+ *
+ * @param oAuthRequest
+ * the OAuth request
+ *
+ * @return the request token
+ *
+ * @throws OAuthException
+ * if the tokens are not valid
+ * @throws IOException
+ * on I/O errors
+ */
+ public String validateRequestToken(OAuthRequest oAuthRequest)
+ throws OAuthException, IOException;
+
+ /**
+ * Indicates that a user has typed in a valid ID and password, and that the
+ * request token can now be exchanged for an access token.
+ *
+ * @param httpRequest
+ * the servlet request
+ * @param requestToken
+ * the request token string
+ */
+ public void markRequestTokenAuthorized(HttpServletRequest httpRequest,
+ String requestToken);
+
+ /**
+ * Checks with the request token has been authorized by the end user.
+ *
+ * @param httpRequest
+ * the servlet request
+ * @param requestToken
+ * the request token
+ * @return answers if the request token is authorized and can be exchanged
+ * for an access token
+ *
+ * @see #markRequestTokenAuthorized(HttpServletRequest, OAuthAccessor)
+ */
+ public boolean isRequestTokenAuthorized(HttpServletRequest httpRequest,
+ String requestToken);
+
+ /**
+ * Generates an access token and token secret and sets it in the accessor.
+ * Clears any request tokens set.
+ *
+ * @param oAuthRequest
+ * the OAuth request
+ * @throws OAuthProblemException
+ * on OAuth problems
+ * @throws IOException
+ * on I/O errors
+ */
+ public void generateAccessToken(OAuthRequest oAuthRequest)
+ throws OAuthProblemException, IOException;
+
+ /**
+ * Validates that the access token and token secret are valid, throwing an
+ * exception if not.
+ *
+ * @param oAuthRequest
+ * the OAuth request
+ * @throws OAuthException
+ * if the tokens are not valid
+ * @throws IOException
+ * on I/O errors
+ */
+ public void validateAccessToken(OAuthRequest oAuthRequest)
+ throws OAuthException, IOException;
+
+ /**
+ * Gets the token secret for token to validate signatures.
+ *
+ * @param httpRequest
+ * the HTTP request
+ * @param token
+ * the token string, either a request token or access token
+ *
+ * @return the token secret
+ * @throws OAuthProblemException
+ * on OAuth problems (e.g., the token is invalid)
+ */
+ public String getTokenSecret(HttpServletRequest httpRequest, String token)
+ throws OAuthProblemException;
+}
diff --git a/org.eclipse.lyo.server.oauth.core/src/test/java/org/eclipse/lyo/server/oauth/provider/core/AppTest.java b/org.eclipse.lyo.server.oauth.core/src/test/java/org/eclipse/lyo/server/oauth/provider/core/AppTest.java
new file mode 100644
index 0000000..e3484e0
--- /dev/null
+++ b/org.eclipse.lyo.server.oauth.core/src/test/java/org/eclipse/lyo/server/oauth/provider/core/AppTest.java
@@ -0,0 +1,53 @@
+/*******************************************************************************
+ * Copyright (c) 2012 IBM Corporation.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v. 1.0 which accompanies this distribution.
+ *
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.lyo.server.oauth.provider.core;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+/**
+ * Unit test for simple App.
+ */
+public class AppTest
+ extends TestCase
+{
+ /**
+ * Create the test case
+ *
+ * @param testName name of the test case
+ */
+ public AppTest( String testName )
+ {
+ super( testName );
+ }
+
+ /**
+ * @return the suite of tests being tested
+ */
+ public static Test suite()
+ {
+ return new TestSuite( AppTest.class );
+ }
+
+ /**
+ * Rigourous Test :-)
+ */
+ public void testApp()
+ {
+ assertTrue( true );
+ }
+}
diff --git a/org.eclipse.lyo.server.oauth.webapp.sample/.classpath b/org.eclipse.lyo.server.oauth.webapp.sample/.classpath
new file mode 100644
index 0000000..7bce0b3
--- /dev/null
+++ b/org.eclipse.lyo.server.oauth.webapp.sample/.classpath
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources"/>
+ <classpathentry kind="src" path="src/main/java"/>
+ <classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
+ <classpathentry kind="output" path="target/classes"/>
+</classpath>
diff --git a/org.eclipse.lyo.server.oauth.webapp.sample/.gitignore b/org.eclipse.lyo.server.oauth.webapp.sample/.gitignore
new file mode 100644
index 0000000..eb5a316
--- /dev/null
+++ b/org.eclipse.lyo.server.oauth.webapp.sample/.gitignore
@@ -0,0 +1 @@
+target
diff --git a/org.eclipse.lyo.server.oauth.webapp.sample/.project b/org.eclipse.lyo.server.oauth.webapp.sample/.project
new file mode 100644
index 0000000..ad67a27
--- /dev/null
+++ b/org.eclipse.lyo.server.oauth.webapp.sample/.project
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.eclipse.lyo.server.oauth.webapp.sample</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.m2e.core.maven2Builder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ <nature>org.eclipse.m2e.core.maven2Nature</nature>
+ </natures>
+</projectDescription>
diff --git a/org.eclipse.lyo.server.oauth.webapp.sample/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.lyo.server.oauth.webapp.sample/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..f6d43a0
--- /dev/null
+++ b/org.eclipse.lyo.server.oauth.webapp.sample/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,9 @@
+#Sat Jan 14 10:44:41 EST 2012
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.source=1.6
diff --git a/org.eclipse.lyo.server.oauth.webapp.sample/.settings/org.eclipse.m2e.core.prefs b/org.eclipse.lyo.server.oauth.webapp.sample/.settings/org.eclipse.m2e.core.prefs
new file mode 100644
index 0000000..09e1d81
--- /dev/null
+++ b/org.eclipse.lyo.server.oauth.webapp.sample/.settings/org.eclipse.m2e.core.prefs
@@ -0,0 +1,5 @@
+#Fri Jan 13 13:22:10 EST 2012
+activeProfiles=
+eclipse.preferences.version=1
+resolveWorkspaceProjects=true
+version=1
diff --git a/org.eclipse.lyo.server.oauth.webapp.sample/pom.xml b/org.eclipse.lyo.server.oauth.webapp.sample/pom.xml
new file mode 100644
index 0000000..68e5409
--- /dev/null
+++ b/org.eclipse.lyo.server.oauth.webapp.sample/pom.xml
@@ -0,0 +1,104 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.eclipse.lyo.server</groupId>
+ <artifactId>oauth.sample</artifactId>
+ <packaging>war</packaging>
+ <version>0.0.1-SNAPSHOT</version>
+ <name>Eclipse Lyo OAuth Provider Sample</name>
+ <url>http://maven.apache.org</url>
+
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.eclipse.lyo.server</groupId>
+ <artifactId>oauth.provider</artifactId>
+ <version>0.0.1-SNAPSHOT</version>
+ <type>war</type>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.lyo.server</groupId>
+ <artifactId>oauth.core</artifactId>
+ <version>0.0.1-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.wink</groupId>
+ <artifactId>wink-server</artifactId>
+ <version>1.1.3-incubating</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.geronimo.specs</groupId>
+ <artifactId>geronimo-servlet_2.5_spec</artifactId>
+ <version>1.2</version>
+ <scope>provided</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <finalName>oauth-webapp-sample</finalName>
+
+ <outputDirectory>target/classes</outputDirectory>
+
+ <plugins>
+
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>2.3.2</version>
+ <configuration>
+ <source>1.6</source>
+ <target>1.6</target>
+ </configuration>
+ </plugin>
+
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-war-plugin</artifactId>
+ <version>2.0</version>
+ <configuration>
+ <attachClasses>true</attachClasses>
+ </configuration>
+ </plugin>
+
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty-maven-plugin</artifactId>
+ <version>7.3.0.v20110203</version>
+
+ <configuration>
+ <webAppConfig>
+ <contextPath>/sample</contextPath>
+ </webAppConfig>
+
+ <!-- Jetty config adds logging -->
+ <jettyConfig>${project.build.directory}/classes/jetty.xml</jettyConfig>
+
+ <scanIntervalSeconds>10</scanIntervalSeconds>
+
+ <systemProperties>
+ <systemProperty>
+ <name>config.dir</name>
+ <value>${basedir}/src/test/resources</value>
+ </systemProperty>
+
+ <systemProperty>
+ <name>jetty.logs</name>
+ <value>${basedir}/target</value>
+ </systemProperty>
+
+ <systemProperty>
+ <name>jetty.port</name>
+ <value>8080</value>
+ </systemProperty>
+ </systemProperties>
+
+ </configuration>
+ </plugin>
+
+ </plugins>
+
+ </build>
+</project>
diff --git a/org.eclipse.lyo.server.oauth.webapp.sample/src/main/java/org/eclipse/lyo/server/oauth/webapp/sample/SecureHelloWorld.java b/org.eclipse.lyo.server.oauth.webapp.sample/src/main/java/org/eclipse/lyo/server/oauth/webapp/sample/SecureHelloWorld.java
new file mode 100644
index 0000000..e50f0d5
--- /dev/null
+++ b/org.eclipse.lyo.server.oauth.webapp.sample/src/main/java/org/eclipse/lyo/server/oauth/webapp/sample/SecureHelloWorld.java
@@ -0,0 +1,125 @@
+/*******************************************************************************
+ * Copyright (c) 2012 IBM Corporation.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v. 1.0 which accompanies this distribution.
+ *
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.lyo.server.oauth.webapp.sample;
+
+import java.io.IOException;
+import java.util.Collection;
+import java.util.Collections;
+
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+
+import net.oauth.OAuthException;
+import net.oauth.server.OAuthServlet;
+
+import org.eclipse.lyo.server.oauth.core.Authentication;
+import org.eclipse.lyo.server.oauth.core.AuthenticationException;
+import org.eclipse.lyo.server.oauth.core.OAuthConfiguration;
+import org.eclipse.lyo.server.oauth.core.OAuthRequest;
+import org.eclipse.lyo.server.oauth.core.consumer.ConsumerStore;
+import org.eclipse.lyo.server.oauth.core.consumer.LyoOAuthConsumer;
+
+/**
+ * A simple OAuth example using the Lyo OAuth provider framework.
+ *
+ * @author Samuel Padgett <spadgett@us.ibm.com>
+ */
+@Path("/hello")
+public class SecureHelloWorld implements ServletContextListener {
+
+ @Context
+ private HttpServletRequest httpRequest;
+
+ @Context
+ private HttpServletResponse httpResponse;
+
+ /**
+ * Initialize the OAuth provider when the webapp loads.
+ *
+ * @param event
+ * the context event
+ */
+ @Override
+ public void contextInitialized(ServletContextEvent event) {
+ OAuthConfiguration config = OAuthConfiguration.getInstance();
+
+ // The realm used in 401 unauthorized responses.
+ config.setRealm("Hello");
+
+ // Validates a user's ID and password.
+ config.setAuthentication(new Authentication() {
+ @Override
+ public void login(HttpServletRequest request, String id,
+ String password) throws AuthenticationException {
+ // For this example, accept all ID/password combination unless
+ // the password is "bogus."
+ if ("bogus".equals(password)) {
+ throw new AuthenticationException("Invalid ID or password.");
+ }
+ }
+
+ @Override
+ public String getApplicationName() {
+ // Display name for this application.
+ return "Hello World";
+ }
+ });
+
+ try {
+ // The consumers.
+ config.setConsumerStore(new ConsumerStore() {
+ @Override
+ public Collection<LyoOAuthConsumer> load() throws IOException {
+ // Define one consumer with key "key" and secret "secret".
+ LyoOAuthConsumer consumer = new LyoOAuthConsumer("key", "secret");
+ consumer.setName("Hello World Consumer");
+ return Collections.singletonList(consumer);
+ }
+ });
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public void contextDestroyed(ServletContextEvent event) {
+ }
+
+ @GET
+ public Response helloWorld() throws IOException, ServletException {
+ try {
+ OAuthRequest request = new OAuthRequest(httpRequest);
+ request.validate();
+ } catch (OAuthException e) {
+ // Request failed validation. Send an unauthorized response.
+ OAuthServlet.handleException(httpResponse, e, OAuthConfiguration
+ .getInstance().getRealm());
+ return Response.status(Status.UNAUTHORIZED).build();
+ }
+
+ // Validation passed. Respond with the secret message.
+ return Response.ok("Hello World!").type(MediaType.TEXT_PLAIN).build();
+ }
+}
diff --git a/org.eclipse.lyo.server.oauth.webapp.sample/src/main/resources/jetty.xml b/org.eclipse.lyo.server.oauth.webapp.sample/src/main/resources/jetty.xml
new file mode 100644
index 0000000..ab989ec
--- /dev/null
+++ b/org.eclipse.lyo.server.oauth.webapp.sample/src/main/resources/jetty.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0"?>
+<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure.dtd">
+
+<Configure id="Server" class="org.eclipse.jetty.server.Server">
+
+ <!-- see also: http://download.eclipse.org/jetty/stable-7/apidocs/ -->
+
+ <!-- Configure a log -->
+
+ <New id="ServerLog" class="java.io.PrintStream">
+ <Arg>
+ <New class="org.eclipse.jetty.util.RolloverFileOutputStream">
+ <Arg><SystemProperty name="jetty.logs" default="." />/yyyy_mm_dd.stderrout.log</Arg>
+ <Arg type="boolean">false</Arg>
+ <Arg type="int">90</Arg>
+ <Arg><Call class="java.util.TimeZone" name="getTimeZone"><Arg>GMT</Arg></Call></Arg>
+ <Get id="ServerLogName" name="datedFilename"/>
+ </New>
+ </Arg>
+ </New>
+ <Call class="org.eclipse.jetty.util.log.Log" name="info"><Arg>Redirecting stderr/stdout to <Ref id="ServerLogName"/></Arg></Call>
+ <Call class="java.lang.System" name="setErr"><Arg><Ref id="ServerLog"/></Arg></Call>
+ <Call class="java.lang.System" name="setOut"><Arg><Ref id="ServerLog"/></Arg></Call>
+
+</Configure>
diff --git a/org.eclipse.lyo.server.oauth.webapp.sample/src/main/webapp/WEB-INF/application b/org.eclipse.lyo.server.oauth.webapp.sample/src/main/webapp/WEB-INF/application
new file mode 100644
index 0000000..3523483
--- /dev/null
+++ b/org.eclipse.lyo.server.oauth.webapp.sample/src/main/webapp/WEB-INF/application
@@ -0,0 +1 @@
+org.eclipse.lyo.server.oauth.webapp.sample.SecureHelloWorld
diff --git a/org.eclipse.lyo.server.oauth.webapp.sample/src/main/webapp/WEB-INF/web.xml b/org.eclipse.lyo.server.oauth.webapp.sample/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..40474b6
--- /dev/null
+++ b/org.eclipse.lyo.server.oauth.webapp.sample/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,24 @@
+<!DOCTYPE web-app PUBLIC
+ "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
+ "http://java.sun.com/dtd/web-app_2_3.dtd" >
+
+<web-app>
+ <display-name>Eclipse Lyo OAuth Provider Framework</display-name>
+ <servlet>
+ <servlet-name>JAX-RS Services</servlet-name>
+ <servlet-class>
+ org.apache.wink.server.internal.servlet.RestServlet
+ </servlet-class>
+ <init-param>
+ <param-name>applicationConfigLocation</param-name>
+ <param-value>/WEB-INF/oauth-services;/WEB-INF/application</param-value>
+ </init-param>
+ </servlet>
+ <servlet-mapping>
+ <servlet-name>JAX-RS Services</servlet-name>
+ <url-pattern>/rest/*</url-pattern>
+ </servlet-mapping>
+ <listener>
+ <listener-class>org.eclipse.lyo.server.oauth.webapp.sample.SecureHelloWorld</listener-class>
+ </listener>
+</web-app>
diff --git a/org.eclipse.lyo.server.oauth.webapp/.classpath b/org.eclipse.lyo.server.oauth.webapp/.classpath
new file mode 100644
index 0000000..7bce0b3
--- /dev/null
+++ b/org.eclipse.lyo.server.oauth.webapp/.classpath
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources"/>
+ <classpathentry kind="src" path="src/main/java"/>
+ <classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
+ <classpathentry kind="output" path="target/classes"/>
+</classpath>
diff --git a/org.eclipse.lyo.server.oauth.webapp/.gitignore b/org.eclipse.lyo.server.oauth.webapp/.gitignore
new file mode 100644
index 0000000..eb5a316
--- /dev/null
+++ b/org.eclipse.lyo.server.oauth.webapp/.gitignore
@@ -0,0 +1 @@
+target
diff --git a/org.eclipse.lyo.server.oauth.webapp/.project b/org.eclipse.lyo.server.oauth.webapp/.project
new file mode 100644
index 0000000..3b5642d
--- /dev/null
+++ b/org.eclipse.lyo.server.oauth.webapp/.project
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.eclipse.lyo.server.oauth.webapp</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.m2e.core.maven2Builder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ <nature>org.eclipse.m2e.core.maven2Nature</nature>
+ </natures>
+</projectDescription>
diff --git a/org.eclipse.lyo.server.oauth.webapp/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.lyo.server.oauth.webapp/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..f6d43a0
--- /dev/null
+++ b/org.eclipse.lyo.server.oauth.webapp/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,9 @@
+#Sat Jan 14 10:44:41 EST 2012
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.source=1.6
diff --git a/org.eclipse.lyo.server.oauth.webapp/.settings/org.eclipse.m2e.core.prefs b/org.eclipse.lyo.server.oauth.webapp/.settings/org.eclipse.m2e.core.prefs
new file mode 100644
index 0000000..09e1d81
--- /dev/null
+++ b/org.eclipse.lyo.server.oauth.webapp/.settings/org.eclipse.m2e.core.prefs
@@ -0,0 +1,5 @@
+#Fri Jan 13 13:22:10 EST 2012
+activeProfiles=
+eclipse.preferences.version=1
+resolveWorkspaceProjects=true
+version=1
diff --git a/org.eclipse.lyo.server.oauth.webapp/pom.xml b/org.eclipse.lyo.server.oauth.webapp/pom.xml
new file mode 100644
index 0000000..31406bc
--- /dev/null
+++ b/org.eclipse.lyo.server.oauth.webapp/pom.xml
@@ -0,0 +1,79 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.eclipse.lyo.server</groupId>
+ <artifactId>oauth-webapp</artifactId>
+ <packaging>war</packaging>
+ <version>0.0.1-SNAPSHOT</version>
+ <name>Eclipse Lyo OAuth Provider Framework</name>
+ <url>http://maven.apache.org</url>
+
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ </properties>
+
+ <repositories>
+ <repository>
+ <id>oauth</id>
+ <url>http://oauth.googlecode.com/svn/code/maven</url>
+ </repository>
+ </repositories>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.eclipse.lyo.server</groupId>
+ <artifactId>oauth.core</artifactId>
+ <version>0.0.1-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.geronimo.specs</groupId>
+ <artifactId>geronimo-servlet_2.5_spec</artifactId>
+ <version>1.2</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>3.8.1</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>net.oauth.core</groupId>
+ <artifactId>oauth</artifactId>
+ <version>20090617</version>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>net.oauth.core</groupId>
+ <artifactId>oauth-provider</artifactId>
+ <version>20100527</version>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.wink</groupId>
+ <artifactId>wink-server</artifactId>
+ <version>1.1.3-incubating</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <finalName>oauth-webapp</finalName>
+
+ <outputDirectory>target/classes</outputDirectory>
+
+ <plugins>
+
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>2.3.2</version>
+ <configuration>
+ <source>1.6</source>
+ <target>1.6</target>
+ </configuration>
+ </plugin>
+
+ </plugins>
+
+ </build>
+</project>
diff --git a/org.eclipse.lyo.server.oauth.webapp/src/main/java/org/eclipse/lyo/server/oauth/webapp/services/OAuthService.java b/org.eclipse.lyo.server.oauth.webapp/src/main/java/org/eclipse/lyo/server/oauth/webapp/services/OAuthService.java
new file mode 100644
index 0000000..c380cc5
--- /dev/null
+++ b/org.eclipse.lyo.server.oauth.webapp/src/main/java/org/eclipse/lyo/server/oauth/webapp/services/OAuthService.java
@@ -0,0 +1,240 @@
+/*******************************************************************************
+ * Copyright (c) 2012 IBM Corporation.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v. 1.0 which accompanies this distribution.
+ *
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.lyo.server.oauth.webapp.services;
+
+import java.io.IOException;
+import java.net.URISyntaxException;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.ws.rs.FormParam;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+
+import net.oauth.OAuth;
+import net.oauth.OAuthAccessor;
+import net.oauth.OAuthException;
+import net.oauth.OAuthValidator;
+import net.oauth.server.OAuthServlet;
+
+import org.eclipse.lyo.server.oauth.core.Authentication;
+import org.eclipse.lyo.server.oauth.core.AuthenticationException;
+import org.eclipse.lyo.server.oauth.core.OAuthConfiguration;
+import org.eclipse.lyo.server.oauth.core.OAuthRequest;
+import org.eclipse.lyo.server.oauth.core.token.TokenStrategy;
+
+/**
+ * Issues OAuth request tokens, handles authentication, and then exchanges
+ * request tokens for access tokens based on the OAuth configuration set in the
+ * {@link OAuthConfiguration} singleton.
+ *
+ * @author Samuel Padgett <spadgett@us.ibm.com>
+ * @see <a href="http://tools.ietf.org/html/rfc5849">The OAuth 1.0 Protocol</a>
+ */
+@Path("/oauth")
+public class OAuthService {
+
+ @Context
+ protected HttpServletRequest httpRequest;
+
+ @Context
+ protected HttpServletResponse httpResponse;
+
+ /**
+ * Responds with a request token and token secret.
+ *
+ * @return the response
+ * @throws IOException
+ * on I/O errors
+ * @throws ServletException
+ * on servlet errors
+ */
+ @POST
+ @Path("/requestToken")
+ public Response getRequestToken() throws IOException, ServletException {
+ try {
+
+ OAuthRequest oAuthRequest = validateRequest();
+ OAuthConfiguration.getInstance()
+ .getTokenStrategy().generateRequestToken(oAuthRequest);
+
+ OAuthAccessor accessor = oAuthRequest.getAccessor();
+ return respondWithToken(accessor.requestToken, accessor.tokenSecret);
+
+ } catch (OAuthException e) {
+ return respondWithOAuthProblem(e);
+ }
+ }
+
+ /*
+ * TODO: Give providers a way to show their own branded login page.
+ */
+
+ /**
+ * Responds with a web page to log in.
+ *
+ * @return the response
+ * @throws IOException
+ * on I/O errors
+ * @throws ServletException
+ * on internal errors validating the request
+ */
+ @GET
+ @Path("/authorize")
+ public Response authorize() throws ServletException, IOException {
+ try {
+ // Check that the request is valid.
+ OAuthRequest oAuthRequest = validateRequest();
+ OAuthConfiguration config = OAuthConfiguration.getInstance();
+ String requestToken = config.getTokenStrategy()
+ .validateRequestToken(oAuthRequest);
+
+ // Pass some data to the JSP.
+ httpRequest.setAttribute("requestToken", requestToken);
+ httpRequest.setAttribute("consumerName", oAuthRequest.getConsumer()
+ .getName());
+ httpRequest.setAttribute("callback",
+ oAuthRequest.getConsumer().callbackURL);
+
+ Authentication auth = config.getAuthentication();
+ if (auth == null) {
+ return Response.status(Status.SERVICE_UNAVAILABLE)
+ .type(MediaType.TEXT_PLAIN)
+ .entity("OAuth service is not configured.").build();
+ }
+
+ // The application name is displayed on the OAuth login page.
+ httpRequest.setAttribute("applicationName",
+ auth.getApplicationName());
+
+ // Show the login page.
+ httpRequest.getRequestDispatcher("/oauth/login.jsp").forward(
+ httpRequest, httpResponse);
+
+ return null;
+ } catch (OAuthException e) {
+ return respondWithOAuthProblem(e);
+ }
+ }
+
+ /**
+ * Validates the ID and password on the authorization form. This is intended
+ * to be invoked by an XHR on the login page.
+ *
+ * @return the response, 409 if login failed or 204 if successful
+ */
+ @POST
+ @Path("/login")
+ public Response login(@FormParam("id") String id,
+ @FormParam("password") String password,
+ @FormParam("requestToken") String requestToken) {
+ Authentication auth = OAuthConfiguration.getInstance()
+ .getAuthentication();
+
+ try {
+ auth.login(httpRequest, id, password);
+ } catch (AuthenticationException e) {
+ String message = e.getMessage();
+ if (message == null || "".equals(message)) {
+ message = "Incorrect username or password.";
+ }
+ return Response.status(Status.CONFLICT).entity(message)
+ .type(MediaType.TEXT_PLAIN).build();
+ }
+
+ OAuthConfiguration.getInstance().getTokenStrategy()
+ .markRequestTokenAuthorized(httpRequest, requestToken);
+ return Response.noContent().build();
+ }
+
+ /**
+ * Responds with an access token and token secret for valid OAuth requests.
+ * The request must be signed and the request token valid.
+ *
+ * @return the response
+ * @throws IOException
+ * on I/O errors
+ * @throws ServletException
+ * on servlet errors
+ */
+ @POST
+ @Path("/accessToken")
+ public Response getAccessToken() throws IOException, ServletException {
+ try {
+
+ OAuthRequest oAuthRequest = validateRequest();
+
+ TokenStrategy strategy = OAuthConfiguration.getInstance()
+ .getTokenStrategy();
+ strategy.validateRequestToken(oAuthRequest);
+ strategy.generateAccessToken(oAuthRequest);
+
+ OAuthAccessor accessor = oAuthRequest.getAccessor();
+ return respondWithToken(accessor.accessToken, accessor.tokenSecret);
+
+ } catch (OAuthException e) {
+ return respondWithOAuthProblem(e);
+ }
+ }
+
+ /**
+ * Validates this is a known consumer and the request is valid using
+ * {@link OAuthValidator#validateMessage(net.oauth.OAuthMessage, OAuthAccessor)}
+ * . Does <b>not</b> check for any tokens
+ *
+ * @return an OAuthRequest
+ * @throws OAuthException
+ * if the request fails validation
+ * @throws IOException
+ * on I/O errors
+ */
+ protected OAuthRequest validateRequest() throws OAuthException, IOException {
+ OAuthRequest oAuthRequest = new OAuthRequest(httpRequest);
+ try {
+ OAuthValidator validator = OAuthConfiguration.getInstance()
+ .getValidator();
+ validator.validateMessage(oAuthRequest.getMessage(),
+ oAuthRequest.getAccessor());
+ } catch (URISyntaxException e) {
+ throw new WebApplicationException(e, Status.INTERNAL_SERVER_ERROR);
+ }
+
+ return oAuthRequest;
+ }
+
+ protected Response respondWithToken(String token, String tokenSecret)
+ throws IOException {
+ String responseBody = OAuth.formEncode(OAuth.newList(OAuth.OAUTH_TOKEN,
+ token, OAuth.OAUTH_TOKEN_SECRET, tokenSecret));
+
+ return Response.ok(responseBody)
+ .type(MediaType.APPLICATION_FORM_URLENCODED).build();
+ }
+
+ protected Response respondWithOAuthProblem(OAuthException e)
+ throws IOException, ServletException {
+ OAuthServlet.handleException(httpResponse, e, OAuthConfiguration
+ .getInstance().getRealm());
+ return Response.status(Status.UNAUTHORIZED).build();
+ }
+}
diff --git a/org.eclipse.lyo.server.oauth.webapp/src/main/webapp/WEB-INF/oauth-services b/org.eclipse.lyo.server.oauth.webapp/src/main/webapp/WEB-INF/oauth-services
new file mode 100644
index 0000000..f280254
--- /dev/null
+++ b/org.eclipse.lyo.server.oauth.webapp/src/main/webapp/WEB-INF/oauth-services
@@ -0,0 +1 @@
+org.eclipse.lyo.server.oauth.webapp.services.OAuthService
diff --git a/org.eclipse.lyo.server.oauth.webapp/src/main/webapp/WEB-INF/web.xml b/org.eclipse.lyo.server.oauth.webapp/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..708bb58
--- /dev/null
+++ b/org.eclipse.lyo.server.oauth.webapp/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,22 @@
+<!DOCTYPE web-app PUBLIC
+ "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
+ "http://java.sun.com/dtd/web-app_2_3.dtd" >
+
+<web-app>
+ <display-name>Eclipse Lyo Sample OAuth Provider</display-name>
+ <description>An example demonstrating the Lyo OAuth provider framework.</description>
+ <servlet>
+ <servlet-name>JAX-RS Services</servlet-name>
+ <servlet-class>
+ org.apache.wink.server.internal.servlet.RestServlet
+ </servlet-class>
+ <init-param>
+ <param-name>applicationConfigLocation</param-name>
+ <param-value>/WEB-INF/oauth-services</param-value>
+ </init-param>
+ </servlet>
+ <servlet-mapping>
+ <servlet-name>JAX-RS Services</servlet-name>
+ <url-pattern>/rest/*</url-pattern>
+ </servlet-mapping>
+</web-app>
diff --git a/org.eclipse.lyo.server.oauth.webapp/src/main/webapp/oauth/login.js b/org.eclipse.lyo.server.oauth.webapp/src/main/webapp/oauth/login.js
new file mode 100644
index 0000000..dffcb80
--- /dev/null
+++ b/org.eclipse.lyo.server.oauth.webapp/src/main/webapp/oauth/login.js
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ * Copyright (c) 2012 IBM Corporation.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v. 1.0 which accompanies this distribution.
+ *
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+require([ "dojo/dom", "dojo/dom-construct", "dojo/on", "dojo/_base/event",
+ "dojo/_base/xhr", "dojo/ready" ], function(dom, domConstruct, on,
+ event, xhr, ready) {
+ function showError(message) {
+ var errorNode = dom.byId('error');
+ if (message) {
+ domConstruct.empty(errorNode);
+ errorNode.appendChild(document.createTextNode(message));
+ } else {
+ errorNode.innerHTML = 'An error occurred.';
+ }
+ errorNode.style.display = 'block';
+ }
+
+ function returnToConsumer() {
+ var callback = dom.byId('callback').value;
+ if (callback) {
+ window.location = callback;
+ } else {
+ dom.byId('content').innerHTML =
+ '<div class="message">Request authorized. Close the browser window to continue.</div>';
+ }
+ }
+
+ function submit() {
+ xhr.post({
+ url : 'login',
+ form : 'loginForm',
+ load : function() {
+ returnToConsumer();
+ },
+ error : function(error, ioArgs) {
+ showError(ioArgs.xhr.responseText);
+ }
+ });
+ }
+
+ function cancel() {
+ alert('canceled!');
+ }
+
+ ready(function() {
+ on(dom.byId('loginForm'), 'submit', function(e) {
+ event.stop(e);
+ submit();
+ });
+
+ on(dom.byId('cancel'), 'click', function(e) {
+ event.stop(e);
+ cancel();
+ });
+ });
+}); \ No newline at end of file
diff --git a/org.eclipse.lyo.server.oauth.webapp/src/main/webapp/oauth/login.jsp b/org.eclipse.lyo.server.oauth.webapp/src/main/webapp/oauth/login.jsp
new file mode 100644
index 0000000..7ff3a8e
--- /dev/null
+++ b/org.eclipse.lyo.server.oauth.webapp/src/main/webapp/oauth/login.jsp
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+
+<%@ page language="java" contentType="text/html; UTF-8"
+ pageEncoding="UTF-8"%>
+<%@ page isELIgnored ="false" %>
+<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
+
+<html lang="en">
+
+<head>
+<meta charset="utf-8">
+<title>Log In</title>
+<link type="text/css" href="<%=request.getContextPath()%>/oauth/theme.css" rel="stylesheet" ></link>
+<script
+ data-dojo-config="async: true"
+ type="text/javascript"
+ src="http://ajax.googleapis.com/ajax/libs/dojo/1.7.1/dojo/dojo.js">
+</script>
+<script type="text/javascript" src="<%=request.getContextPath()%>/oauth/login.js"></script>
+</head>
+
+<body>
+ <div id="content">
+ <form id="loginForm">
+
+ <div class="message">Another application, <c:out value="${consumerName}">[Unknwon]</c:out>,
+ is requesting access to your <c:out value="${applicationName}">application</c:out> data. Enter your
+ username and password to continue or click cancel to exit.</div>
+
+ <div id="error" class="error" style="display: hidden;"></div>
+ <input type="hidden" name="requestToken" value="<c:out value="${requestToken}"/>">
+ <input type="hidden" id="callback" value="<c:out value="${callback}"/>">
+
+ <div>
+ <label for="id">Username:</label>
+ </div>
+ <div>
+ <input id="id" name="id" type="text" class="textField" required autofocus></input>
+ <script type="text/javascript">
+ // If no native HTML5 autofocus support, focus the ID field using JavaScript.
+ if (!("autofocus" in document.createElement("input"))) {
+ document.getElementById("id").focus();
+ }
+ </script>
+ </div>
+
+ <div>
+ <label for="password">Password:</label>
+ </div>
+ <input id="password" name="password" type="password" class="textField"></input>
+ <div>
+ </div>
+ <div>
+ <input type="submit" value="OK">
+ <button type="button" id="cancel">Cancel</button>
+ </div>
+ </form>
+ </div>
+</body>
+
+</html>
diff --git a/org.eclipse.lyo.server.oauth.webapp/src/main/webapp/oauth/theme.css b/org.eclipse.lyo.server.oauth.webapp/src/main/webapp/oauth/theme.css
new file mode 100644
index 0000000..77bf42a
--- /dev/null
+++ b/org.eclipse.lyo.server.oauth.webapp/src/main/webapp/oauth/theme.css
@@ -0,0 +1,24 @@
+body {
+ font-family: Arial, sans-serif;
+ font-size: 9pt;
+}
+
+label {
+ color: #666666;
+ text-align: right;
+}
+
+.message {
+ font-size: 120t;
+}
+
+.textField {
+ width: 400px;
+ margin-bottom: 1em;
+}
+
+.error {
+ color: red;
+ padding-top: 5px;
+ padding-bottom: 5px;
+}