From 1a0802f4a3d9d10451cb3c7dd1444d82a3da7cb5 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Fri, 26 Feb 2021 13:15:46 -0800 Subject: [PATCH] GUACAMOLE-956: Provide alternative means of deleting the current token that does not specify the token within the URL. --- .../app/auth/service/authenticationService.js | 28 +++++++++----- .../rest/session/SessionRESTService.java | 2 +- .../rest/session/SessionResource.java | 37 ++++++++++++++++++- .../rest/session/SessionResourceFactory.java | 5 ++- 4 files changed, 59 insertions(+), 13 deletions(-) diff --git a/guacamole/src/main/frontend/src/app/auth/service/authenticationService.js b/guacamole/src/main/frontend/src/app/auth/service/authenticationService.js index e237a61e4..944fd4a9a 100644 --- a/guacamole/src/main/frontend/src/app/auth/service/authenticationService.js +++ b/guacamole/src/main/frontend/src/app/auth/service/authenticationService.js @@ -264,10 +264,10 @@ angular.module('auth').factory('authenticationService', ['$injector', * A promise which succeeds only if the token was successfully revoked. */ service.revokeToken = function revokeToken(token) { - return requestService({ + return service.request({ method: 'DELETE', - url: 'api/tokens/' + token - }); + url: 'api/session' + }, token); }; /** @@ -303,7 +303,7 @@ angular.module('auth').factory('authenticationService', ['$injector', * successful. */ service.logout = function logout() { - + // Clear authentication data var token = service.getCurrentToken(); clearAuthenticationResult(); @@ -411,25 +411,33 @@ angular.module('auth').factory('authenticationService', ['$injector', /** * Makes an HTTP request leveraging the requestService(), automatically - * including the user's authentication token using the "Guacamole-Token" - * header. If the user is not logged in, the "Guacamole-Token" header is - * simply omitted. The provided configuration object is not modified by - * this function. + * including the given authentication token using the "Guacamole-Token" + * header. If no token is provided, the user's current authentication token + * is used instead. If the user is not logged in, the "Guacamole-Token" + * header is simply omitted. The provided configuration object is not + * modified by this function. * * @param {Object} object * A configuration object describing the HTTP request to be made by * requestService(). As described by requestService(), this object must * be a configuration object accepted by AngularJS' $http service. * + * @param {string} [token] + * The authentication token to pass with the "Guacamole-Token" header. + * If omitted, and the user is logged in, the user's current + * authentication token will be used. + * * @returns {Promise.} * A promise that will resolve with the data from the HTTP response for * the underlying requestService() call if successful, or reject with * an @link{Error} describing the failure. */ - service.request = function request(object) { + service.request = function request(object, token) { + + // Attempt to use current token if none is provided + token = token || service.getCurrentToken(); // Add "Guacamole-Token" header if an authentication token is available - var token = service.getCurrentToken(); if (token) { object = _.merge({ headers : { 'Guacamole-Token' : token } diff --git a/guacamole/src/main/java/org/apache/guacamole/rest/session/SessionRESTService.java b/guacamole/src/main/java/org/apache/guacamole/rest/session/SessionRESTService.java index 31891b3d4..90974d1ec 100644 --- a/guacamole/src/main/java/org/apache/guacamole/rest/session/SessionRESTService.java +++ b/guacamole/src/main/java/org/apache/guacamole/rest/session/SessionRESTService.java @@ -72,7 +72,7 @@ public class SessionRESTService { // Return a resource exposing the retrieved session GuacamoleSession session = authenticationService.getGuacamoleSession(authToken); - return sessionResourceFactory.create(session); + return sessionResourceFactory.create(authToken, session); } diff --git a/guacamole/src/main/java/org/apache/guacamole/rest/session/SessionResource.java b/guacamole/src/main/java/org/apache/guacamole/rest/session/SessionResource.java index 702ec867d..0c334b068 100644 --- a/guacamole/src/main/java/org/apache/guacamole/rest/session/SessionResource.java +++ b/guacamole/src/main/java/org/apache/guacamole/rest/session/SessionResource.java @@ -23,6 +23,7 @@ import com.google.inject.assistedinject.Assisted; import com.google.inject.assistedinject.AssistedInject; import javax.inject.Inject; import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; @@ -31,6 +32,7 @@ import org.apache.guacamole.GuacamoleException; import org.apache.guacamole.GuacamoleResourceNotFoundException; import org.apache.guacamole.GuacamoleSession; import org.apache.guacamole.net.auth.UserContext; +import org.apache.guacamole.rest.auth.AuthenticationService; import org.apache.guacamole.rest.tunnel.TunnelCollectionResource; import org.apache.guacamole.rest.tunnel.TunnelCollectionResourceFactory; @@ -47,6 +49,18 @@ public class SessionResource { */ private final GuacamoleSession session; + /** + * The authentication token associated with the GuacamoleSession being + * exposed by this SessionResource. + */ + private final String token; + + /** + * Service for authenticating users and managing their Guacamole sessions. + */ + @Inject + private AuthenticationService authenticationService; + /** * Factory for creating UserContextResources which expose a given * UserContext. @@ -65,12 +79,16 @@ public class SessionResource { * Creates a new SessionResource which exposes the data within the given * GuacamoleSession. * + * @param token + * The authentication token associated with the given session. + * * @param session * The GuacamoleSession which should be exposed through this * SessionResource. */ @AssistedInject - public SessionResource(@Assisted GuacamoleSession session) { + public SessionResource(@Assisted String token, @Assisted GuacamoleSession session) { + this.token = token; this.session = session; } @@ -149,4 +167,21 @@ public class SessionResource { return tunnelCollectionResourceFactory.create(session); } + /** + * Invalidates the GuacamoleSession exposed by this SessionResource, + * including the associated authentication token. + * + * @throws GuacamoleException + * If the authentication token originally provided when this + * SessionResource was created no longer exists. + */ + @DELETE + public void invalidate() throws GuacamoleException { + + // Invalidate session, if it exists + if (!authenticationService.destroyGuacamoleSession(token)) + throw new GuacamoleResourceNotFoundException("No such token."); + + } + } diff --git a/guacamole/src/main/java/org/apache/guacamole/rest/session/SessionResourceFactory.java b/guacamole/src/main/java/org/apache/guacamole/rest/session/SessionResourceFactory.java index a166b37b0..462eebe1e 100644 --- a/guacamole/src/main/java/org/apache/guacamole/rest/session/SessionResourceFactory.java +++ b/guacamole/src/main/java/org/apache/guacamole/rest/session/SessionResourceFactory.java @@ -31,6 +31,9 @@ public interface SessionResourceFactory { * Creates a new SessionResource which exposes the contents of the * given GuacamoleSession. * + * @param token + * The authentication token associated with the given session. + * * @param session * The GuacamoleSession whose contents should be exposed. * @@ -38,6 +41,6 @@ public interface SessionResourceFactory { * A new SessionResource which exposes the contents of the given * GuacamoleSession. */ - SessionResource create(GuacamoleSession session); + SessionResource create(String token, GuacamoleSession session); }