diff --git a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/BasicServletContextListener.java b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/BasicServletContextListener.java index 60eeffdbb..d9962fef9 100644 --- a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/BasicServletContextListener.java +++ b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/BasicServletContextListener.java @@ -32,8 +32,7 @@ import org.glyptodon.guacamole.environment.Environment; import org.glyptodon.guacamole.environment.LocalEnvironment; import org.glyptodon.guacamole.net.basic.extension.ExtensionModule; import org.glyptodon.guacamole.net.basic.log.LogModule; -import org.glyptodon.guacamole.net.basic.rest.RESTAuthModule; -import org.glyptodon.guacamole.net.basic.rest.RESTServletModule; +import org.glyptodon.guacamole.net.basic.rest.RESTServiceModule; import org.glyptodon.guacamole.net.basic.rest.auth.BasicTokenSessionMap; import org.glyptodon.guacamole.net.basic.rest.auth.TokenSessionMap; import org.slf4j.Logger; @@ -85,8 +84,7 @@ public class BasicServletContextListener extends GuiceServletContextListener { new EnvironmentModule(environment), new LogModule(environment), new ExtensionModule(environment), - new RESTAuthModule(sessionMap), - new RESTServletModule(), + new RESTServiceModule(sessionMap), new TunnelModule() ); } diff --git a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/RESTAuthModule.java b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/RESTAuthModule.java deleted file mode 100644 index ddc5fff78..000000000 --- a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/RESTAuthModule.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (C) 2015 Glyptodon LLC - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -package org.glyptodon.guacamole.net.basic.rest; - -import com.google.inject.AbstractModule; -import org.glyptodon.guacamole.net.basic.rest.auth.AuthTokenGenerator; -import org.glyptodon.guacamole.net.basic.rest.auth.AuthenticationService; -import org.glyptodon.guacamole.net.basic.rest.auth.SecureRandomAuthTokenGenerator; -import org.glyptodon.guacamole.net.basic.rest.auth.TokenSessionMap; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * A Guice Module for setting up authentication-specific dependency injection. - * - * @author James Muehlner - * @author Michael Jumper - */ -public class RESTAuthModule extends AbstractModule { - - /** - * Logger for this class. - */ - private final Logger logger = LoggerFactory.getLogger(RESTAuthModule.class); - - /** - * Singleton instance of TokenSessionMap. - */ - private final TokenSessionMap tokenSessionMap; - - /** - * Creates a module which handles binding of authentication-related - * objects, including the singleton TokenSessionMap. - * - * @param tokenSessionMap - * An instance of TokenSessionMap to inject as a singleton wherever - * needed. - */ - public RESTAuthModule(TokenSessionMap tokenSessionMap) { - this.tokenSessionMap = tokenSessionMap; - } - - @Override - protected void configure() { - - // Bind session map - bind(TokenSessionMap.class).toInstance(tokenSessionMap); - - // Bind low-level services - bind(AuthenticationService.class); - bind(AuthTokenGenerator.class).to(SecureRandomAuthTokenGenerator.class); - - } - -} diff --git a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/RESTExceptionWrapper.java b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/RESTExceptionWrapper.java index 758e40e3a..14de30c92 100644 --- a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/RESTExceptionWrapper.java +++ b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/RESTExceptionWrapper.java @@ -35,6 +35,7 @@ import org.glyptodon.guacamole.GuacamoleSecurityException; import org.glyptodon.guacamole.GuacamoleUnauthorizedException; import org.glyptodon.guacamole.net.auth.credentials.GuacamoleInsufficientCredentialsException; import org.glyptodon.guacamole.net.auth.credentials.GuacamoleInvalidCredentialsException; +import org.glyptodon.guacamole.net.basic.rest.auth.TokenSessionMap; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -55,6 +56,24 @@ public class RESTExceptionWrapper implements MethodInterceptor { */ private final Logger logger = LoggerFactory.getLogger(RESTExceptionWrapper.class); + /** + * Singleton instance of TokenSessionMap. + */ + private final TokenSessionMap tokenSessionMap; + + /** + * Creates an interceptor which automatically handles GuacamoleExceptions + * within the REST services, including implicit invalidation of + * authentication tokens. + * + * @param tokenSessionMap + * The singleton instance of TokenSessionMap to use if management of + * authentication tokens is required to handle a particular error. + */ + public RESTExceptionWrapper(TokenSessionMap tokenSessionMap) { + this.tokenSessionMap = tokenSessionMap; + } + /** * Determines whether the given set of annotations describes an HTTP * request parameter of the given name. For a parameter to be associated @@ -158,10 +177,8 @@ public class RESTExceptionWrapper implements MethodInterceptor { String token = getAuthenticationToken(invocation); // If there is an associated auth token, invalidate it - if (token != null) { - logger.debug("Implicitly invalidating token \"{}\" due to GuacamoleUnauthorizedException.", token); - // STUB - Does not actually invalidate anything at the moment - } + if (token != null && tokenSessionMap.remove(token) != null) + logger.debug("Implicitly invalidated token \"{}\" due to GuacamoleUnauthorizedException.", token); // Continue with exception processing throw e; diff --git a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/RESTServletModule.java b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/RESTServiceModule.java similarity index 68% rename from guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/RESTServletModule.java rename to guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/RESTServiceModule.java index 044fa5ae9..c194495c5 100644 --- a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/RESTServletModule.java +++ b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/RESTServiceModule.java @@ -31,26 +31,56 @@ import org.glyptodon.guacamole.net.basic.rest.auth.TokenRESTService; import org.glyptodon.guacamole.net.basic.rest.connection.ConnectionRESTService; import org.glyptodon.guacamole.net.basic.rest.connectiongroup.ConnectionGroupRESTService; import org.glyptodon.guacamole.net.basic.rest.activeconnection.ActiveConnectionRESTService; +import org.glyptodon.guacamole.net.basic.rest.auth.AuthTokenGenerator; +import org.glyptodon.guacamole.net.basic.rest.auth.AuthenticationService; +import org.glyptodon.guacamole.net.basic.rest.auth.SecureRandomAuthTokenGenerator; +import org.glyptodon.guacamole.net.basic.rest.auth.TokenSessionMap; import org.glyptodon.guacamole.net.basic.rest.history.HistoryRESTService; import org.glyptodon.guacamole.net.basic.rest.language.LanguageRESTService; import org.glyptodon.guacamole.net.basic.rest.schema.SchemaRESTService; import org.glyptodon.guacamole.net.basic.rest.user.UserRESTService; /** - * A Guice Module to set up the servlet mappings for the Guacamole REST API. + * A Guice Module to set up the servlet mappings and authentication-specific + * dependency injection for the Guacamole REST API. * * @author James Muehlner + * @author Michael Jumper */ -public class RESTServletModule extends ServletModule { +public class RESTServiceModule extends ServletModule { + + /** + * Singleton instance of TokenSessionMap. + */ + private final TokenSessionMap tokenSessionMap; + + /** + * Creates a module which handles binding of REST services and related + * authentication objects, including the singleton TokenSessionMap. + * + * @param tokenSessionMap + * An instance of TokenSessionMap to inject as a singleton wherever + * needed. + */ + public RESTServiceModule(TokenSessionMap tokenSessionMap) { + this.tokenSessionMap = tokenSessionMap; + } @Override protected void configureServlets() { + // Bind session map + bind(TokenSessionMap.class).toInstance(tokenSessionMap); + + // Bind low-level services + bind(AuthenticationService.class); + bind(AuthTokenGenerator.class).to(SecureRandomAuthTokenGenerator.class); + // Automatically translate GuacamoleExceptions for REST methods bindInterceptor( Matchers.any(), new RESTMethodMatcher(), - new RESTExceptionWrapper() + new RESTExceptionWrapper(tokenSessionMap) ); // Bind convenience services used by the REST API