mirror of
https://github.com/gyurix1968/guacamole-client.git
synced 2025-09-06 13:17:41 +00:00
GUACAMOLE-956: Automatically pull token from HTTP header or query parameter.
This commit is contained in:
@@ -21,7 +21,6 @@ package org.apache.guacamole.rest;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.ws.rs.WebApplicationException;
|
||||
import javax.ws.rs.core.Context;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
@@ -32,6 +31,7 @@ import org.apache.guacamole.GuacamoleClientException;
|
||||
import org.apache.guacamole.GuacamoleException;
|
||||
import org.apache.guacamole.GuacamoleUnauthorizedException;
|
||||
import org.apache.guacamole.rest.auth.AuthenticationService;
|
||||
import org.glassfish.jersey.server.ContainerRequest;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -50,37 +50,20 @@ public class RESTExceptionMapper implements ExceptionMapper<Throwable> {
|
||||
private final Logger logger = LoggerFactory.getLogger(RESTExceptionMapper.class);
|
||||
|
||||
/**
|
||||
* The HttpServletRequest for the Throwable being intercepted. Despite this
|
||||
* class being a Singleton, this object will always be scoped with the
|
||||
* current request for the Throwable that is being processed by this class.
|
||||
* The ContainerRequest for HTTP request that resulted in the Throwable
|
||||
* being intercepted. Despite this class being a Singleton, this object will
|
||||
* always be scoped with the current request for the Throwable that is being
|
||||
* processed by this class.
|
||||
*/
|
||||
@Context
|
||||
private HttpServletRequest request;
|
||||
private ContainerRequest request;
|
||||
|
||||
/**
|
||||
* The authentication service associated with the currently active session.
|
||||
*/
|
||||
@Inject
|
||||
private AuthenticationService authenticationService;
|
||||
|
||||
/**
|
||||
* Returns the authentication token that is in use in the current session,
|
||||
* if present, or null if otherwise.
|
||||
*
|
||||
* @return
|
||||
* The authentication token for the current session, or null if no
|
||||
* token is present.
|
||||
*/
|
||||
private String getAuthenticationToken() {
|
||||
|
||||
String token = request.getParameter("token");
|
||||
if (token != null && !token.isEmpty())
|
||||
return token;
|
||||
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Response toResponse(Throwable t) {
|
||||
|
||||
@@ -90,8 +73,7 @@ public class RESTExceptionMapper implements ExceptionMapper<Throwable> {
|
||||
|
||||
// Ensure any associated session is invalidated if unauthorized
|
||||
if (t instanceof GuacamoleUnauthorizedException) {
|
||||
String token = getAuthenticationToken();
|
||||
|
||||
String token = authenticationService.getAuthenticationToken(request);
|
||||
if (authenticationService.destroyGuacamoleSession(token))
|
||||
logger.debug("Implicitly invalidated session for token \"{}\"", token);
|
||||
}
|
||||
@@ -135,4 +117,4 @@ public class RESTExceptionMapper implements ExceptionMapper<Throwable> {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package org.apache.guacamole.rest;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Annotation which automatically maps the authentication token used by
|
||||
* Guacamole's REST API, regardless of whether that token is received via an
|
||||
* HTTP header or via a query parameter.
|
||||
*/
|
||||
@Target({ElementType.PARAMETER})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface TokenParam {}
|
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package org.apache.guacamole.rest;
|
||||
|
||||
import java.util.function.Function;
|
||||
import javax.inject.Inject;
|
||||
import javax.ws.rs.ext.Provider;
|
||||
import org.apache.guacamole.rest.auth.AuthenticationService;
|
||||
import org.glassfish.jersey.server.ContainerRequest;
|
||||
import org.glassfish.jersey.server.model.Parameter;
|
||||
import org.glassfish.jersey.server.spi.internal.ValueParamProvider;
|
||||
|
||||
/**
|
||||
* Provider which automatically maps Guacamole authentication tokens received
|
||||
* via REST API requests to parameters that have been annotated with the
|
||||
* <code>@TokenParam</code> annotation.
|
||||
*/
|
||||
@Provider
|
||||
public class TokenParamProvider implements ValueParamProvider {
|
||||
|
||||
/**
|
||||
* Service for authenticating users and working with the resulting
|
||||
* authentication tokens.
|
||||
*/
|
||||
@Inject
|
||||
private AuthenticationService authenticationService;
|
||||
|
||||
@Override
|
||||
public Function<ContainerRequest, ?> getValueProvider(Parameter parameter) {
|
||||
|
||||
if (parameter.getAnnotation(TokenParam.class) == null)
|
||||
return null;
|
||||
|
||||
return (request) -> authenticationService.getAuthenticationToken(request);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public PriorityType getPriority() {
|
||||
return Priority.HIGH;
|
||||
}
|
||||
|
||||
}
|
@@ -41,6 +41,7 @@ import org.apache.guacamole.net.auth.credentials.GuacamoleInvalidCredentialsExce
|
||||
import org.apache.guacamole.net.event.AuthenticationFailureEvent;
|
||||
import org.apache.guacamole.net.event.AuthenticationSuccessEvent;
|
||||
import org.apache.guacamole.rest.event.ListenerService;
|
||||
import org.glassfish.jersey.server.ContainerRequest;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -91,6 +92,18 @@ public class AuthenticationService {
|
||||
@Inject
|
||||
private ListenerService listenerService;
|
||||
|
||||
/**
|
||||
* The name of the HTTP header that may contain the authentication token
|
||||
* used by the Guacamole REST API.
|
||||
*/
|
||||
public static final String TOKEN_HEADER_NAME = "Guacamole-Token";
|
||||
|
||||
/**
|
||||
* The name of the query parameter that may contain the authentication
|
||||
* token used by the Guacamole REST API.
|
||||
*/
|
||||
public static final String TOKEN_PARAMETER_NAME = "token";
|
||||
|
||||
/**
|
||||
* Regular expression which matches any IPv4 address.
|
||||
*/
|
||||
@@ -541,4 +554,34 @@ public class AuthenticationService {
|
||||
return getGuacamoleSession(authToken).getUserContexts();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the authentication token sent within the given request, if
|
||||
* present, or null if otherwise. Authentication tokens may be sent via
|
||||
* the "Guacamole-Token" header or the "token" query parameter. If both
|
||||
* the header and a parameter are used, the header is given priority.
|
||||
*
|
||||
* @param request
|
||||
* The HTTP request to retrieve the authentication token from.
|
||||
*
|
||||
* @return
|
||||
* The authentication token within the given request, or null if no
|
||||
* token is present.
|
||||
*/
|
||||
public String getAuthenticationToken(ContainerRequest request) {
|
||||
|
||||
// Give priority to token within HTTP header
|
||||
String token = request.getHeaderString(TOKEN_HEADER_NAME);
|
||||
if (token != null && !token.isEmpty())
|
||||
return token;
|
||||
|
||||
// If no token was provided via HTTP headers, fall back to using
|
||||
// query parameters
|
||||
token = request.getUriInfo().getQueryParameters().getFirst(TOKEN_PARAMETER_NAME);
|
||||
if (token != null && !token.isEmpty())
|
||||
return token;
|
||||
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -23,10 +23,10 @@ import javax.inject.Inject;
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.QueryParam;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import org.apache.guacamole.GuacamoleException;
|
||||
import org.apache.guacamole.GuacamoleSession;
|
||||
import org.apache.guacamole.rest.TokenParam;
|
||||
import org.apache.guacamole.rest.auth.AuthenticationService;
|
||||
|
||||
/**
|
||||
@@ -67,7 +67,7 @@ public class SessionRESTService {
|
||||
* If the authentication token is invalid.
|
||||
*/
|
||||
@Path("/")
|
||||
public SessionResource getSessionResource(@QueryParam("token") String authToken)
|
||||
public SessionResource getSessionResource(@TokenParam String authToken)
|
||||
throws GuacamoleException {
|
||||
|
||||
// Return a resource exposing the retrieved session
|
||||
|
Reference in New Issue
Block a user