aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSusumu Fukuda2013-04-17 03:27:53 (EDT)
committerSusumu Fukuda2013-04-17 03:27:53 (EDT)
commitd8295ea860cd06e7f0b76140398152331b9e7e62 (patch)
tree6746ed631cf0bb772175a81cc56d039b1e523539
parentfd8f80bafbfa2ad1a812b35c0a825e4952324f09 (diff)
downloadorg.eclipse.lyo.server-d8295ea860cd06e7f0b76140398152331b9e7e62.zip
org.eclipse.lyo.server-d8295ea860cd06e7f0b76140398152331b9e7e62.tar.gz
org.eclipse.lyo.server-d8295ea860cd06e7f0b76140398152331b9e7e62.tar.bz2
Bug 404966: Provide base class of CredentailsFilter in SDKrefs/changes/65/11965/1
Change-Id: I831795d88d88d459f7f2c19de0d7433be5c1dbab Signed-off-by: Susumu Fukuda <fukudas@jp.ibm.com>
-rw-r--r--org.eclipse.lyo.server.oauth.core/src/main/java/org/eclipse/lyo/server/oauth/core/utils/AbstractAdapterCredentialsFilter.java508
-rw-r--r--org.eclipse.lyo.server.oauth.core/src/main/java/org/eclipse/lyo/server/oauth/core/utils/RestException.java59
-rw-r--r--org.eclipse.lyo.server.oauth.core/src/main/java/org/eclipse/lyo/server/oauth/core/utils/UnauthorizedException.java38
3 files changed, 605 insertions, 0 deletions
diff --git a/org.eclipse.lyo.server.oauth.core/src/main/java/org/eclipse/lyo/server/oauth/core/utils/AbstractAdapterCredentialsFilter.java b/org.eclipse.lyo.server.oauth.core/src/main/java/org/eclipse/lyo/server/oauth/core/utils/AbstractAdapterCredentialsFilter.java
new file mode 100644
index 0000000..e6b26ee
--- /dev/null
+++ b/org.eclipse.lyo.server.oauth.core/src/main/java/org/eclipse/lyo/server/oauth/core/utils/AbstractAdapterCredentialsFilter.java
@@ -0,0 +1,508 @@
+/*******************************************************************************
+ * Copyright (c) 2012, 2013 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:
+ *
+ * Michael Fiedler - initial API and implementation for Bugzilla adapter
+ * Susumu Fukuda - extracted this class from Bugzilla adapter CredentialsFilter
+ *
+ *******************************************************************************/
+package org.eclipse.lyo.server.oauth.core.utils;
+
+import java.io.IOException;
+import java.net.URISyntaxException;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import javax.servlet.http.HttpSessionEvent;
+import javax.servlet.http.HttpSessionListener;
+
+import net.oauth.OAuth;
+import net.oauth.OAuthAccessor;
+import net.oauth.OAuthException;
+import net.oauth.OAuthMessage;
+import net.oauth.OAuthProblemException;
+import net.oauth.http.HttpMessage;
+import net.oauth.server.OAuthServlet;
+
+import org.eclipse.lyo.server.oauth.core.Application;
+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;
+import org.eclipse.lyo.server.oauth.core.token.LRUCache;
+import org.eclipse.lyo.server.oauth.core.token.SimpleTokenStrategy;
+
+/**
+ * <h3>Overview</h3>
+ * Purpose: Provide a JEE Servlet filter base implementation for accepting
+ * both HTTP basic and OAuth provider authentication, connecting your tool using the
+ * credentials, and managing the connections.
+ *
+ * <p>With this credentitals filter:<ul>
+ * <li>Your Webapp can accepts HTTP Basic authentication
+ * <li>Your Webapp can works as an OAuth provider
+ * </ul>
+ * <p>Once user entered credentials via HTTP Basic auth or OAuth, it
+ * is passed to a callback method {@link #getCredentialsFromRequest(HttpServletRequest)}
+ * or {@link #getCredentialsForOAuth(String, String)} so that your implementation
+ * can build a Credentials object from the given data.
+ * And then, next callback method {@link #login(Object, HttpServletRequest)} is invoked for
+ * authenticate the credentials and building connection to your back-end tool.
+ * Concrete types of the credentials and the connection can be specified as type
+ * parameters of this class.
+ *
+ * <p>While processing a request, the credentials and the connection are available
+ * as attributes of the request. Your subsequent process such as {@link HttpServlet#service(ServletRequest, ServletResponse)}
+ * can extract and use them for accessing your tool. You can use {@link #getConnector(HttpServletRequest)}
+ * and {@link #getCredentials(HttpServletRequest)} to retrieve them from the request.
+ *
+ * <h3>Usage</h3>
+ * <p>You have to subclass this class and give implementations for the following methods:
+ * <ul>
+ * <li>{@link #login(Object, HttpServletRequest)}
+ * <li>{@link #getCredentialsFromRequest(HttpServletRequest)}
+ * <li>{@link #getCredentialsForOAuth(String, String)}
+ * <li>{@link #isAdminSession(String, Object, HttpServletRequest)}
+ * <li>{@link #createConsumerStore()}
+ * <li>{@link #logout(Object, HttpSession)} (optional)
+ * </ul>
+ * Then, add the follwoing filter-mapping to your web.xml:
+ * <pre>
+ * &lt;filter&gt;
+ * &lt;display-name&gt;[YOUR FILTER CLASS NAME (MyFilter)]&lt;/display-name&gt;
+ * &lt;filter-name&gt;[YOUR FILTER CLASS NAME (MyFilter)]&lt;/filter-name&gt;
+ * &lt;filter-class&gt;[FULLY QUALIFIED YOUR FILTER CLASS NAME (com.example.MyFilter)]&lt;/filter-class&gt;
+ * &lt;/filter&gt;
+ * &lt;filter-mapping&gt;
+ * &lt;filter-name&gt;[YOUR FILTER CLASS NAME (MyFilter)]&lt;/filter-name&gt;
+ * &lt;url-pattern&gt;/services/*&lt;/url-pattern&gt;
+ * &lt;/filter-mapping&gt;
+ * </pre>
+ *
+ * @param <Connection> Type for connection object to your tool
+ * @param <Credentials> Type for credentials for your tool. (e.g. UsernamePasswordCredentials)
+ */
+abstract public class AbstractAdapterCredentialsFilter<Credentials, Connection> implements Filter {
+
+ private static final String ATTRIBUTE_BASE = "org.eclipse.lyo.server.oauth.core.utils.";
+ protected static final String CONNECTOR_ATTRIBUTE = ATTRIBUTE_BASE + "Connector";
+ protected static final String CREDENTIALS_ATTRIBUTE = ATTRIBUTE_BASE + "Credentials";
+ protected static final String ADMIN_SESSION_ATTRIBUTE = ATTRIBUTE_BASE + "AdminSession";
+ protected static final String JAZZ_INVALID_EXPIRED_TOKEN_OAUTH_PROBLEM = "invalid_expired_token";
+ protected static final String OAUTH_EMPTY_TOKEN_KEY = new String("OAUTH_EMPTY_TOKEN_KEY");
+
+ private final LRUCache<String, Connection> keyToConnectorCache = new LRUCache<String, Connection>(200);
+
+ final private String displayName;
+ final private String realm;
+
+ /**
+ * Constructor
+ * @param displayName application name displayed on the login prompt
+ * @param realm realm for this adapter
+ */
+ protected AbstractAdapterCredentialsFilter(String displayName, String realm) {
+ this.displayName = displayName;
+ this.realm = realm;
+ }
+
+ /**
+ * Extract credentials from the request and return it.
+ * @param request {@link HttpServletRequest}
+ * @return credentials
+ * @throws UnauthorizedException iff no login credentials associated to the request.
+ */
+ abstract protected Credentials getCredentialsFromRequest(HttpServletRequest request) throws UnauthorizedException;
+
+ /**
+ * Create a Credentials object from given user id and password.
+ *
+ * <p>For OAuth two-legged request, the <code>id</code> is set to {@link #OAUTH_EMPTY_TOKEN_KEY}
+ * object. Implementor can compare the value using <code>==</code> to identify the request.
+ * In the request the consumer key is set to the <code>password</code>. So you might find a functional
+ * user associated to the consumer key with the value.
+ * @param id user id or {@link #OAUTH_EMPTY_TOKEN_KEY}
+ * @param password password or OAuth consumer key
+ * @return credentials
+ */
+ abstract protected Credentials getCredentialsForOAuth(String id, String password);
+
+ /**
+ * Create connection to your tool using the given credentials, and returns the connection.
+ * @param crdentials credentials for login
+ * @param request {@link HttpServletRequest}
+ * @return connection that represents the successful login session
+ * @throws UnauthorizedException credentials is invalid
+ * @throws ServletException other exceptional situation
+ */
+ abstract protected Connection login(Credentials crdentials, HttpServletRequest request) throws UnauthorizedException, ServletException;
+
+ /**
+ * Logout
+ * @param loginSession
+ * @param session
+ */
+ protected void logout(Connection loginSession, HttpSession session) {
+ // do nothing by default
+ }
+
+ /**
+ * Tell if this is an admin session. For admin session, Lyo provides user-interface to
+ * accept provisional authentication key.
+ * @param id
+ * @param session
+ * @param request
+ * @return
+ */
+ abstract protected boolean isAdminSession(String id, Connection session, HttpServletRequest request);
+
+ /**
+ * Invoked from this class to create {@link ConsumerStore} for OAuth keys.
+ * Typical implementation can be:
+ * <pre>return new FileSystemConsumerStore("YourOAuthStore.xml");
+ * </pre>
+ * @return
+ * @throws Exception
+ */
+ abstract protected ConsumerStore createConsumerStore() throws Exception;
+
+ /**
+ * get Connector assigned to this request
+ *
+ * The connector should be placed in the session by the CredentialsFilter servlet filter
+ *
+ * @param request
+ * @return connector
+ */
+ public static <T> T getConnector(HttpServletRequest request)
+ {
+ //connector should never be null if CredentialsFilter is doing its job
+ @SuppressWarnings("unchecked")
+ T connector = (T) request.getAttribute(CONNECTOR_ATTRIBUTE);
+ return connector;
+ }
+
+ /**
+ * Get Credentials for this session
+ * @param request
+ * @return credentials
+ */
+ public static <T> T getCredentials(HttpServletRequest request)
+ {
+ @SuppressWarnings("unchecked")
+ T credentials = (T) request.getSession().getAttribute(CREDENTIALS_ATTRIBUTE);
+ return credentials;
+ }
+
+ protected String getOAuthRealm() {
+ return realm;
+ }
+ protected String getDisplayName() {
+ return displayName;
+ }
+
+
+ @Override
+ public void destroy() {
+
+ }
+
+ /**
+ * Check for OAuth or BasicAuth credentials and challenge if not found.
+ *
+ * Store the Connector in the HttpSession for retrieval in the REST services.
+ */
+ @SuppressWarnings("unchecked")
+ @Override
+ public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
+ FilterChain chain) throws IOException, ServletException {
+
+ if(servletRequest instanceof HttpServletRequest && servletResponse instanceof HttpServletResponse) {
+ HttpServletRequest request = (HttpServletRequest) servletRequest;
+ HttpServletResponse response = (HttpServletResponse) servletResponse;
+
+ boolean isTwoLeggedOAuthRequest = false;
+ String twoLeggedOAuthConsumerKey = null;
+
+ //Don't protect requests to oauth service. TODO: possibly do this in web.xml
+ if (! request.getPathInfo().startsWith("/oauth"))
+ {
+
+ // First check if this is an OAuth request.
+ try {
+ try {
+ OAuthMessage message = OAuthServlet.getMessage(request, null);
+ // test if this is a valid two-legged oauth request
+ if ("".equals(message.getToken())) {
+ validateTwoLeggedOAuthMessage(message);
+ isTwoLeggedOAuthRequest = true;
+ twoLeggedOAuthConsumerKey = message.getConsumerKey();
+ }
+
+ if (!isTwoLeggedOAuthRequest && message.getToken() != null) {
+ OAuthRequest oAuthRequest = new OAuthRequest(request);
+ oAuthRequest.validate();
+ Connection connector = keyToConnectorCache.get(message.getToken());
+ if (connector == null) {
+ throw new OAuthProblemException(
+ OAuth.Problems.TOKEN_REJECTED);
+ }
+
+ request.getSession().setAttribute(CONNECTOR_ATTRIBUTE, connector);
+ }
+ } catch (OAuthProblemException e) {
+ if (OAuth.Problems.TOKEN_REJECTED.equals(e.getProblem()))
+ throwInvalidExpiredException(e);
+ else
+ throw e;
+ }
+ } catch (OAuthException e) {
+ OAuthServlet.handleException(response, e, getOAuthRealm());
+ return;
+ } catch (URISyntaxException e) {
+ throw new ServletException(e);
+ }
+
+ // This is not an OAuth request. Check for basic access authentication.
+ HttpSession session = request.getSession();
+ Connection connector = (Connection) session.getAttribute(CONNECTOR_ATTRIBUTE);
+ if (connector == null) {
+ try {
+ Credentials credentials;
+ if (isTwoLeggedOAuthRequest) {
+ connector = keyToConnectorCache.get("");
+ if (connector == null) {
+ credentials = getCredentialsForOAuth(OAUTH_EMPTY_TOKEN_KEY, twoLeggedOAuthConsumerKey);
+ connector = login(credentials, request);
+ keyToConnectorCache.put("", connector);
+ }
+ credentials = null; // TODO; Do we need to keep the credentials for this path ??
+ } else {
+ credentials = (Credentials) request.getSession().getAttribute(CREDENTIALS_ATTRIBUTE);
+ if (credentials == null)
+ {
+ credentials = getCredentialsFromRequest(request);
+ if (credentials == null) {
+ throw new UnauthorizedException();
+ }
+ }
+ connector = login(credentials, request);
+ }
+ session.setAttribute(CONNECTOR_ATTRIBUTE, connector);
+ session.setAttribute(CREDENTIALS_ATTRIBUTE, credentials);
+
+ } catch (UnauthorizedException e)
+ {
+ sendUnauthorizedResponse(response, e);
+ System.err.println(e.getMessage());
+ return;
+ } catch (ServletException ce)
+ {
+ throw ce;
+ }
+ }
+
+ if (connector != null) {
+ doChainDoFilterWithConnector(request, response, chain, connector);
+ return;
+ }
+
+ }
+ }
+
+ chain.doFilter(servletRequest, servletResponse);
+ }
+
+ /**
+ * The default implementation is:
+ * <pre>
+ * request.setAttribute(CONNECTOR_ATTRIBUTE, connector);
+ * chain.doFilter(request, response);</pre>
+ *
+ * Subclass may invoke the <code>chain.doFilter()</code> directly instead of invoking super method.
+ *
+ * @param request {@link HttpServletRequest}
+ * @param response {@link HttpServletResponse}
+ * @param chain {@link FilterChain}
+ * @param sessionConnector {@link Connector} to be used for processing rest of the chain (i.e. REST request)
+ * @throws IOException
+ * @throws ServletException
+ */
+ protected void doChainDoFilterWithConnector(HttpServletRequest request,
+ HttpServletResponse response, FilterChain chain, Connection connector) throws IOException, ServletException {
+ request.setAttribute(CONNECTOR_ATTRIBUTE, connector);
+ chain.doFilter(request, response);
+ }
+
+ private void validateTwoLeggedOAuthMessage(OAuthMessage message)
+ throws IOException, OAuthException,
+ URISyntaxException {
+ OAuthConfiguration config = OAuthConfiguration.getInstance();
+ LyoOAuthConsumer consumer = config.getConsumerStore().getConsumer(message.getConsumerKey());
+ if (consumer != null && consumer.isTrusted()) {
+ // The request can be a two-legged oauth request because it's a trusted consumer
+ // Validate the message with an empty token and an empty secret
+ OAuthAccessor accessor = new OAuthAccessor(consumer);
+ accessor.requestToken = "";
+ accessor.tokenSecret = "";
+ config.getValidator().validateMessage(message, accessor);
+ } else {
+ throw new OAuthProblemException(
+ OAuth.Problems.TOKEN_REJECTED);
+ }
+ }
+
+ private HttpSessionListener listener = new HttpSessionListener() {
+ @Override
+ public void sessionDestroyed(HttpSessionEvent se) {
+ HttpSession session = se.getSession();
+ @SuppressWarnings("unchecked")
+ Connection loginSession = (Connection) session.getAttribute(CONNECTOR_ATTRIBUTE);
+ logout(loginSession, session);
+ }
+
+ @Override
+ public void sessionCreated(HttpSessionEvent se) {
+ // nothing
+ }
+ };
+
+ @Override
+ public void init(FilterConfig arg0) throws ServletException {
+ OAuthConfiguration config = OAuthConfiguration.getInstance();
+
+ // Add session listener
+ arg0.getServletContext().addListener(listener);
+
+ // Validates a user's ID and password.
+ config.setApplication(new Application() {
+ @Override
+ public void login(HttpServletRequest request, String id,
+ String password) throws AuthenticationException {
+ try {
+ Credentials creds = getCredentialsForOAuth(id, password);
+ request.getSession().setAttribute(CREDENTIALS_ATTRIBUTE, creds);
+
+ Connection bc = AbstractAdapterCredentialsFilter.this.login(creds, request);
+ request.setAttribute(CONNECTOR_ATTRIBUTE, bc);
+
+ boolean isAdmin = AbstractAdapterCredentialsFilter.this.isAdminSession(id, bc, request);
+ request.getSession().setAttribute(ADMIN_SESSION_ATTRIBUTE, isAdmin);
+ } catch (Exception e) {
+ throw new AuthenticationException(e.getCause().getMessage(), e);
+ }
+ }
+
+ @Override
+ public String getName() {
+ // Display name for this application.
+ return getDisplayName();
+ }
+
+ @Override
+ public boolean isAdminSession(HttpServletRequest request) {
+ return Boolean.TRUE.equals(request.getSession().getAttribute(
+ ADMIN_SESSION_ATTRIBUTE));
+ }
+
+ @Override
+ public String getRealm(HttpServletRequest request) {
+ return getOAuthRealm();
+ }
+
+ @Override
+ public boolean isAuthenticated(HttpServletRequest request) {
+ @SuppressWarnings("unchecked")
+ Connection connector = (Connection) request.getSession().getAttribute(CONNECTOR_ATTRIBUTE);
+ if (connector == null) {
+ return false;
+ }
+ request.setAttribute(CONNECTOR_ATTRIBUTE, connector);
+ return true;
+ }
+ });
+
+ /*
+ * Override some SimpleTokenStrategy methods so that we can keep the
+ * Connector associated with the OAuth tokens.
+ */
+ config.setTokenStrategy(new SimpleTokenStrategy() {
+ @SuppressWarnings("unchecked")
+ @Override
+ public void markRequestTokenAuthorized(
+ HttpServletRequest httpRequest, String requestToken)
+ throws OAuthProblemException {
+ keyToConnectorCache.put(requestToken,
+ (Connection) httpRequest.getAttribute(CONNECTOR_ATTRIBUTE));
+ super.markRequestTokenAuthorized(httpRequest, requestToken);
+ }
+
+ @Override
+ public void generateAccessToken(OAuthRequest oAuthRequest)
+ throws OAuthProblemException, IOException {
+ String requestToken = oAuthRequest.getMessage().getToken();
+ Connection bc = keyToConnectorCache.remove(requestToken);
+ super.generateAccessToken(oAuthRequest);
+ keyToConnectorCache.put(oAuthRequest.getAccessor().accessToken, bc);
+ }
+ });
+
+ try {
+ // For now, hard-code the consumers.
+ config.setConsumerStore(createConsumerStore());
+ } catch (Throwable t) {
+ System.err.println("Error initializing the OAuth consumer store: " + t.getMessage());
+ }
+ }
+
+ /**
+ * Jazz requires a exception with the magic string "invalid_expired_token" to restart
+ * OAuth authentication
+ * @param e
+ * @return
+ * @throws OAuthProblemException
+ */
+ private void throwInvalidExpiredException(OAuthProblemException e) throws OAuthProblemException {
+ OAuthProblemException ope = new OAuthProblemException(JAZZ_INVALID_EXPIRED_TOKEN_OAUTH_PROBLEM);
+ ope.setParameter(HttpMessage.STATUS_CODE, new Integer(
+ HttpServletResponse.SC_UNAUTHORIZED));
+ throw ope;
+ }
+
+ private void sendUnauthorizedResponse(HttpServletResponse response,
+ UnauthorizedException e) throws IOException, ServletException {
+ // Accept basic access or OAuth authentication.
+ final String WWW_AUTHENTICATE_HEADER = "WWW-Authenticate";
+ final String BASIC_AUTHORIZATION_PREFIX = "Basic ";
+ final String BASIC_AUTHENTICATION_CHALLENGE = BASIC_AUTHORIZATION_PREFIX
+ + "realm=\"" + getOAuthRealm() + "\"";
+ final String OAUTH_AUTHORIZATION_PREFIX = "OAuth ";
+ final String OAUTH_AUTHENTICATION_CHALLENGE = OAUTH_AUTHORIZATION_PREFIX
+ + "realm=\"" + getOAuthRealm() + "\"";
+
+ response.addHeader(WWW_AUTHENTICATE_HEADER,
+ OAUTH_AUTHENTICATION_CHALLENGE);
+ response.addHeader(WWW_AUTHENTICATE_HEADER,
+ BASIC_AUTHENTICATION_CHALLENGE);
+ response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
+ }
+
+}
diff --git a/org.eclipse.lyo.server.oauth.core/src/main/java/org/eclipse/lyo/server/oauth/core/utils/RestException.java b/org.eclipse.lyo.server.oauth.core/src/main/java/org/eclipse/lyo/server/oauth/core/utils/RestException.java
new file mode 100644
index 0000000..d4cfb81
--- /dev/null
+++ b/org.eclipse.lyo.server.oauth.core/src/main/java/org/eclipse/lyo/server/oauth/core/utils/RestException.java
@@ -0,0 +1,59 @@
+/*******************************************************************************
+ * Copyright (c) 2011, 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.utils;
+
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * Holds a status code and error message for an error response.
+ *
+ * @author Samuel Padgett <spadgett@us.ibm.com>
+ */
+public class RestException extends Exception {
+ private int statusCode;
+ private String message;
+
+ public RestException(int statusCode, String message) {
+ this.statusCode = statusCode;
+ this.message = message;
+ }
+
+ public RestException(Throwable t) {
+ this(t, HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+ }
+
+ public RestException(Throwable t, int statusCode) {
+ super(t);
+ this.message = t.getMessage();
+ this.statusCode = statusCode;
+ }
+
+ public int getStatusCode() {
+ return statusCode;
+ }
+
+ public void setStatusCode(int statusCode) {
+ this.statusCode = statusCode;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+}
diff --git a/org.eclipse.lyo.server.oauth.core/src/main/java/org/eclipse/lyo/server/oauth/core/utils/UnauthorizedException.java b/org.eclipse.lyo.server.oauth.core/src/main/java/org/eclipse/lyo/server/oauth/core/utils/UnauthorizedException.java
new file mode 100644
index 0000000..32fee23
--- /dev/null
+++ b/org.eclipse.lyo.server.oauth.core/src/main/java/org/eclipse/lyo/server/oauth/core/utils/UnauthorizedException.java
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright (c) 2011, 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.utils;
+
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * Corresponds to an HTTP 401 response.
+ *
+ * @author Samuel Padgett <spadgett@us.ibm.com>
+ */
+public class UnauthorizedException extends RestException {
+ public UnauthorizedException() {
+ super(HttpServletResponse.SC_UNAUTHORIZED,
+ "You must authenticate with Bugzilla for this request.");
+ }
+
+ public UnauthorizedException(String message) {
+ super(HttpServletResponse.SC_UNAUTHORIZED, message);
+ }
+
+ public UnauthorizedException(Throwable t) {
+ super(t, HttpServletResponse.SC_UNAUTHORIZED);
+ }
+}