mirror of
https://github.com/gyurix1968/guacamole-client.git
synced 2025-09-06 13:17:41 +00:00
GUAC-586: Separate authentication from authorization.
This commit is contained in:
@@ -0,0 +1,73 @@
|
|||||||
|
/*
|
||||||
|
* 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.auth;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Basic implementation of an AuthenticatedUser which uses the username to
|
||||||
|
* determine equality. Username comparison is case-sensitive.
|
||||||
|
*
|
||||||
|
* @author Michael Jumper
|
||||||
|
*/
|
||||||
|
public abstract class AbstractAuthenticatedUser implements AuthenticatedUser {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of this user.
|
||||||
|
*/
|
||||||
|
private String username;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getIdentifier() {
|
||||||
|
return username;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setIdentifier(String username) {
|
||||||
|
this.username = username;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
if (username == null) return 0;
|
||||||
|
return username.hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
|
||||||
|
// Not equal if null or not a User
|
||||||
|
if (obj == null) return false;
|
||||||
|
if (!(obj instanceof AbstractAuthenticatedUser)) return false;
|
||||||
|
|
||||||
|
// Get username
|
||||||
|
String objUsername = ((AbstractAuthenticatedUser) obj).username;
|
||||||
|
|
||||||
|
// If null, equal only if this username is null
|
||||||
|
if (objUsername == null) return username == null;
|
||||||
|
|
||||||
|
// Otherwise, equal only if strings are identical
|
||||||
|
return objUsername.equals(username);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
* 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.auth;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A user of the Guacamole web application who has been authenticated by an
|
||||||
|
* AuthenticationProvider.
|
||||||
|
*
|
||||||
|
* @author Michael Jumper
|
||||||
|
*/
|
||||||
|
public interface AuthenticatedUser extends Identifiable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the AuthenticationProvider that authenticated this user.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* The AuthenticationProvider that authenticated this user.
|
||||||
|
*/
|
||||||
|
AuthenticationProvider getAuthenticationProvider();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the credentials that the user provided when they successfully
|
||||||
|
* authenticated.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* The credentials provided by the user when they authenticated.
|
||||||
|
*/
|
||||||
|
Credentials getCredentials();
|
||||||
|
|
||||||
|
}
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2013 Glyptodon LLC
|
* Copyright (C) 2015 Glyptodon LLC
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -25,46 +25,112 @@ package org.glyptodon.guacamole.net.auth;
|
|||||||
import org.glyptodon.guacamole.GuacamoleException;
|
import org.glyptodon.guacamole.GuacamoleException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides means of accessing and managing the available
|
* Provides means of authorizing users and for accessing and managing data
|
||||||
* GuacamoleConfiguration objects and User objects. Access to each configuration
|
* associated with those users. Access to such data is limited according to the
|
||||||
* and each user is limited by a given Credentials object.
|
* AuthenticationProvider implementation.
|
||||||
*
|
*
|
||||||
* @author Michael Jumper
|
* @author Michael Jumper
|
||||||
*/
|
*/
|
||||||
public interface AuthenticationProvider {
|
public interface AuthenticationProvider {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the UserContext of the user authorized by the given credentials.
|
* Returns an AuthenticatedUser representing the user authenticated by the
|
||||||
|
* given credentials, if any.
|
||||||
*
|
*
|
||||||
* @param credentials The credentials to use to retrieve the environment.
|
* @param credentials
|
||||||
* @return The UserContext of the user authorized by the given credentials,
|
* The credentials to use for authentication.
|
||||||
* or null if the credentials are not authorized.
|
|
||||||
*
|
*
|
||||||
* @throws GuacamoleException If an error occurs while creating the
|
* @return
|
||||||
* UserContext.
|
* An AuthenticatedUser representing the user authenticated by the
|
||||||
|
* given credentials, if any, or null if the credentials are invalid.
|
||||||
|
*
|
||||||
|
* @throws GuacamoleException
|
||||||
|
* If an error occurs while authenticating the user, or if access is
|
||||||
|
* temporarily, permanently, or conditionally denied, such as if the
|
||||||
|
* supplied credentials are insufficient or invalid.
|
||||||
*/
|
*/
|
||||||
UserContext getUserContext(Credentials credentials)
|
AuthenticatedUser authenticateUser(Credentials credentials)
|
||||||
throws GuacamoleException;
|
throws GuacamoleException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a new or updated UserContext for the user authorized by the
|
* Returns a new or updated AuthenticatedUser for the given credentials
|
||||||
* give credentials and having the given existing UserContext. Note that
|
* already having produced the given AuthenticatedUser. Note that because
|
||||||
* because this function will be called for all future requests after
|
* this function will be called for all future requests after initial
|
||||||
* initial authentication, including tunnel requests, care must be taken
|
* authentication, including tunnel requests, care must be taken to avoid
|
||||||
* to avoid using functions of HttpServletRequest which invalidate the
|
* using functions of HttpServletRequest which invalidate the entire request
|
||||||
* entire request body, such as getParameter().
|
* body, such as getParameter(). Doing otherwise may cause the
|
||||||
|
* GuacamoleHTTPTunnelServlet to fail.
|
||||||
*
|
*
|
||||||
* @param context The existing UserContext belonging to the user in
|
* @param credentials
|
||||||
* question.
|
* The credentials to use for authentication.
|
||||||
* @param credentials The credentials to use to retrieve or update the
|
|
||||||
* environment.
|
|
||||||
* @return The updated UserContext, which need not be the same as the
|
|
||||||
* UserContext given, or null if the user is no longer authorized.
|
|
||||||
*
|
*
|
||||||
* @throws GuacamoleException If an error occurs while updating the
|
* @param authenticatedUser
|
||||||
* UserContext.
|
* An AuthenticatedUser object representing the user authenticated by
|
||||||
|
* an arbitrary set of credentials. The AuthenticatedUser may come from
|
||||||
|
* this AuthenticationProvider or any other installed
|
||||||
|
* AuthenticationProvider.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* An updated AuthenticatedUser representing the user authenticated by
|
||||||
|
* the given credentials, if any, or null if the credentials are
|
||||||
|
* invalid.
|
||||||
|
*
|
||||||
|
* @throws GuacamoleException
|
||||||
|
* If an error occurs while updating the AuthenticatedUser.
|
||||||
*/
|
*/
|
||||||
UserContext updateUserContext(UserContext context, Credentials credentials)
|
AuthenticatedUser updateAuthenticatedUser(AuthenticatedUser authenticatedUser,
|
||||||
|
Credentials credentials) throws GuacamoleException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the UserContext of the user authenticated by the given
|
||||||
|
* credentials.
|
||||||
|
*
|
||||||
|
* @param authenticatedUser
|
||||||
|
* An AuthenticatedUser object representing the user authenticated by
|
||||||
|
* an arbitrary set of credentials. The AuthenticatedUser may come from
|
||||||
|
* this AuthenticationProvider or any other installed
|
||||||
|
* AuthenticationProvider.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* A UserContext describing the permissions, connection, connection
|
||||||
|
* groups, etc. accessible or associated with the given authenticated
|
||||||
|
* user, or null if this AuthenticationProvider refuses to provide any
|
||||||
|
* such data.
|
||||||
|
*
|
||||||
|
* @throws GuacamoleException
|
||||||
|
* If an error occurs while creating the UserContext.
|
||||||
|
*/
|
||||||
|
UserContext getUserContext(AuthenticatedUser authenticatedUser)
|
||||||
throws GuacamoleException;
|
throws GuacamoleException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a new or updated UserContext for the given AuthenticatedUser
|
||||||
|
* already having the given UserContext. Note that because this function
|
||||||
|
* will be called for all future requests after initial authentication,
|
||||||
|
* including tunnel requests, care must be taken to avoid using functions
|
||||||
|
* of HttpServletRequest which invalidate the entire request body, such as
|
||||||
|
* getParameter(). Doing otherwise may cause the GuacamoleHTTPTunnelServlet
|
||||||
|
* to fail.
|
||||||
|
*
|
||||||
|
* @param context
|
||||||
|
* The existing UserContext belonging to the user in question.
|
||||||
|
*
|
||||||
|
* @param authenticatedUser
|
||||||
|
* An AuthenticatedUser object representing the user authenticated by
|
||||||
|
* an arbitrary set of credentials. The AuthenticatedUser may come from
|
||||||
|
* this AuthenticationProvider or any other installed
|
||||||
|
* AuthenticationProvider.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* An updated UserContext describing the permissions, connection,
|
||||||
|
* connection groups, etc. accessible or associated with the given
|
||||||
|
* authenticated user, or null if this AuthenticationProvider refuses
|
||||||
|
* to provide any such data.
|
||||||
|
*
|
||||||
|
* @throws GuacamoleException
|
||||||
|
* If an error occurs while updating the UserContext.
|
||||||
|
*/
|
||||||
|
UserContext updateUserContext(UserContext context,
|
||||||
|
AuthenticatedUser authenticatedUser) throws GuacamoleException;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -23,8 +23,11 @@
|
|||||||
package org.glyptodon.guacamole.net.auth.simple;
|
package org.glyptodon.guacamole.net.auth.simple;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
import org.glyptodon.guacamole.GuacamoleException;
|
import org.glyptodon.guacamole.GuacamoleException;
|
||||||
|
import org.glyptodon.guacamole.net.auth.AbstractAuthenticatedUser;
|
||||||
import org.glyptodon.guacamole.net.auth.AuthenticationProvider;
|
import org.glyptodon.guacamole.net.auth.AuthenticationProvider;
|
||||||
|
import org.glyptodon.guacamole.net.auth.AuthenticatedUser;
|
||||||
import org.glyptodon.guacamole.net.auth.Credentials;
|
import org.glyptodon.guacamole.net.auth.Credentials;
|
||||||
import org.glyptodon.guacamole.net.auth.UserContext;
|
import org.glyptodon.guacamole.net.auth.UserContext;
|
||||||
import org.glyptodon.guacamole.protocol.GuacamoleConfiguration;
|
import org.glyptodon.guacamole.protocol.GuacamoleConfiguration;
|
||||||
@@ -62,12 +65,100 @@ public abstract class SimpleAuthenticationProvider
|
|||||||
getAuthorizedConfigurations(Credentials credentials)
|
getAuthorizedConfigurations(Credentials credentials)
|
||||||
throws GuacamoleException;
|
throws GuacamoleException;
|
||||||
|
|
||||||
@Override
|
/**
|
||||||
public UserContext getUserContext(Credentials credentials)
|
* AuthenticatedUser which contains its own predefined set of authorized
|
||||||
throws GuacamoleException {
|
* configurations.
|
||||||
|
*
|
||||||
|
* @author Michael Jumper
|
||||||
|
*/
|
||||||
|
private class SimpleAuthenticatedUser extends AbstractAuthenticatedUser {
|
||||||
|
|
||||||
// Get username, if any
|
/**
|
||||||
|
* The credentials provided when this AuthenticatedUser was
|
||||||
|
* authenticated.
|
||||||
|
*/
|
||||||
|
private final Credentials credentials;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The GuacamoleConfigurations that this AuthenticatedUser is
|
||||||
|
* authorized to use.
|
||||||
|
*/
|
||||||
|
private final Map<String, GuacamoleConfiguration> configs;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new SimpleAuthenticatedUser associated with the given
|
||||||
|
* credentials and having access to the given Map of
|
||||||
|
* GuacamoleConfigurations.
|
||||||
|
*
|
||||||
|
* @param credentials
|
||||||
|
* The credentials provided by the user when they authenticated.
|
||||||
|
*
|
||||||
|
* @param configs
|
||||||
|
* A Map of all GuacamoleConfigurations for which this user has
|
||||||
|
* access. The keys of this Map are Strings which uniquely identify
|
||||||
|
* each configuration.
|
||||||
|
*/
|
||||||
|
public SimpleAuthenticatedUser(Credentials credentials, Map<String, GuacamoleConfiguration> configs) {
|
||||||
|
|
||||||
|
// Store credentials and configurations
|
||||||
|
this.credentials = credentials;
|
||||||
|
this.configs = configs;
|
||||||
|
|
||||||
|
// Pull username from credentials if it exists
|
||||||
String username = credentials.getUsername();
|
String username = credentials.getUsername();
|
||||||
|
if (username != null && !username.isEmpty())
|
||||||
|
setIdentifier(username);
|
||||||
|
|
||||||
|
// Otherwise generate a random username
|
||||||
|
else
|
||||||
|
setIdentifier(UUID.randomUUID().toString());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a Map containing all GuacamoleConfigurations that this user
|
||||||
|
* is authorized to use. The keys of this Map are Strings which
|
||||||
|
* uniquely identify each configuration.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* A Map of all configurations for which this user is authorized.
|
||||||
|
*/
|
||||||
|
public Map<String, GuacamoleConfiguration> getAuthorizedConfigurations() {
|
||||||
|
return configs;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AuthenticationProvider getAuthenticationProvider() {
|
||||||
|
return SimpleAuthenticationProvider.this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Credentials getCredentials() {
|
||||||
|
return credentials;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given an arbitrary credentials object, returns a Map containing all
|
||||||
|
* configurations authorized by those credentials, filtering those
|
||||||
|
* configurations using a TokenFilter and the standard credential tokens
|
||||||
|
* (like ${GUAC_USERNAME} and ${GUAC_PASSWORD}). The keys of this Map
|
||||||
|
* are Strings which uniquely identify each configuration.
|
||||||
|
*
|
||||||
|
* @param credentials
|
||||||
|
* The credentials to use to retrieve authorized configurations.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* A Map of all configurations authorized by the given credentials, or
|
||||||
|
* null if the credentials given are not authorized.
|
||||||
|
*
|
||||||
|
* @throws GuacamoleException
|
||||||
|
* If an error occurs while retrieving configurations.
|
||||||
|
*/
|
||||||
|
private Map<String, GuacamoleConfiguration>
|
||||||
|
getFilteredAuthorizedConfigurations(Credentials credentials)
|
||||||
|
throws GuacamoleException {
|
||||||
|
|
||||||
// Get configurations
|
// Get configurations
|
||||||
Map<String, GuacamoleConfiguration> configs =
|
Map<String, GuacamoleConfiguration> configs =
|
||||||
@@ -85,19 +176,85 @@ public abstract class SimpleAuthenticationProvider
|
|||||||
for (GuacamoleConfiguration config : configs.values())
|
for (GuacamoleConfiguration config : configs.values())
|
||||||
tokenFilter.filterValues(config.getParameters());
|
tokenFilter.filterValues(config.getParameters());
|
||||||
|
|
||||||
// Return user context restricted to authorized configs
|
return configs;
|
||||||
if (username != null && !username.isEmpty())
|
|
||||||
return new SimpleUserContext(username, configs);
|
|
||||||
|
|
||||||
// If there is no associated username, let SimpleUserContext generate one
|
}
|
||||||
else
|
|
||||||
return new SimpleUserContext(configs);
|
/**
|
||||||
|
* Given a user who has already been authenticated, returns a Map
|
||||||
|
* containing all configurations for which that user is authorized,
|
||||||
|
* filtering those configurations using a TokenFilter and the standard
|
||||||
|
* credential tokens (like ${GUAC_USERNAME} and ${GUAC_PASSWORD}). The keys
|
||||||
|
* of this Map are Strings which uniquely identify each configuration.
|
||||||
|
*
|
||||||
|
* @param authenticatedUser
|
||||||
|
* The user whose authorized configurations are to be retrieved.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* A Map of all configurations authorized for use by the given user, or
|
||||||
|
* null if the user is not authorized to use any configurations.
|
||||||
|
*
|
||||||
|
* @throws GuacamoleException
|
||||||
|
* If an error occurs while retrieving configurations.
|
||||||
|
*/
|
||||||
|
private Map<String, GuacamoleConfiguration>
|
||||||
|
getFilteredAuthorizedConfigurations(AuthenticatedUser authenticatedUser)
|
||||||
|
throws GuacamoleException {
|
||||||
|
|
||||||
|
// Pull cached configurations, if any
|
||||||
|
if (authenticatedUser instanceof SimpleAuthenticatedUser)
|
||||||
|
return ((SimpleAuthenticatedUser) authenticatedUser).getAuthorizedConfigurations();
|
||||||
|
|
||||||
|
// Otherwise, pull using credentials
|
||||||
|
return getFilteredAuthorizedConfigurations(authenticatedUser.getCredentials());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AuthenticatedUser authenticateUser(final Credentials credentials)
|
||||||
|
throws GuacamoleException {
|
||||||
|
|
||||||
|
// Get configurations
|
||||||
|
Map<String, GuacamoleConfiguration> configs =
|
||||||
|
getFilteredAuthorizedConfigurations(credentials);
|
||||||
|
|
||||||
|
// Return as unauthorized if not authorized to retrieve configs
|
||||||
|
if (configs == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return new SimpleAuthenticatedUser(credentials, configs);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public UserContext getUserContext(AuthenticatedUser authenticatedUser)
|
||||||
|
throws GuacamoleException {
|
||||||
|
|
||||||
|
// Get configurations
|
||||||
|
Map<String, GuacamoleConfiguration> configs =
|
||||||
|
getFilteredAuthorizedConfigurations(authenticatedUser);
|
||||||
|
|
||||||
|
// Return as unauthorized if not authorized to retrieve configs
|
||||||
|
if (configs == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
// Return user context restricted to authorized configs
|
||||||
|
return new SimpleUserContext(authenticatedUser.getIdentifier(), configs);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AuthenticatedUser updateAuthenticatedUser(AuthenticatedUser authenticatedUser,
|
||||||
|
Credentials credentials) throws GuacamoleException {
|
||||||
|
|
||||||
|
// Simply return the given user, updating nothing
|
||||||
|
return authenticatedUser;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public UserContext updateUserContext(UserContext context,
|
public UserContext updateUserContext(UserContext context,
|
||||||
Credentials credentials) throws GuacamoleException {
|
AuthenticatedUser authorizedUser) throws GuacamoleException {
|
||||||
|
|
||||||
// Simply return the given context, updating nothing
|
// Simply return the given context, updating nothing
|
||||||
return context;
|
return context;
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2014 Glyptodon LLC
|
* Copyright (C) 2015 Glyptodon LLC
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -27,7 +27,7 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||||||
import org.glyptodon.guacamole.GuacamoleException;
|
import org.glyptodon.guacamole.GuacamoleException;
|
||||||
import org.glyptodon.guacamole.environment.Environment;
|
import org.glyptodon.guacamole.environment.Environment;
|
||||||
import org.glyptodon.guacamole.net.GuacamoleTunnel;
|
import org.glyptodon.guacamole.net.GuacamoleTunnel;
|
||||||
import org.glyptodon.guacamole.net.auth.Credentials;
|
import org.glyptodon.guacamole.net.auth.AuthenticatedUser;
|
||||||
import org.glyptodon.guacamole.net.auth.UserContext;
|
import org.glyptodon.guacamole.net.auth.UserContext;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@@ -46,9 +46,9 @@ public class GuacamoleSession {
|
|||||||
private static final Logger logger = LoggerFactory.getLogger(GuacamoleSession.class);
|
private static final Logger logger = LoggerFactory.getLogger(GuacamoleSession.class);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The credentials provided when the user authenticated.
|
* The user associated with this session.
|
||||||
*/
|
*/
|
||||||
private Credentials credentials;
|
private AuthenticatedUser authenticatedUser;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The user context associated with this session.
|
* The user context associated with this session.
|
||||||
@@ -72,8 +72,8 @@ public class GuacamoleSession {
|
|||||||
* The environment of the Guacamole server associated with this new
|
* The environment of the Guacamole server associated with this new
|
||||||
* session.
|
* session.
|
||||||
*
|
*
|
||||||
* @param credentials
|
* @param authenticatedUser
|
||||||
* The credentials provided by the user during login.
|
* The authenticated user to associate this session with.
|
||||||
*
|
*
|
||||||
* @param userContext
|
* @param userContext
|
||||||
* The user context to associate this session with.
|
* The user context to associate this session with.
|
||||||
@@ -81,34 +81,33 @@ public class GuacamoleSession {
|
|||||||
* @throws GuacamoleException
|
* @throws GuacamoleException
|
||||||
* If an error prevents the session from being created.
|
* If an error prevents the session from being created.
|
||||||
*/
|
*/
|
||||||
public GuacamoleSession(Environment environment, Credentials credentials,
|
public GuacamoleSession(Environment environment,
|
||||||
UserContext userContext) throws GuacamoleException {
|
AuthenticatedUser authenticatedUser, UserContext userContext)
|
||||||
|
throws GuacamoleException {
|
||||||
this.lastAccessedTime = System.currentTimeMillis();
|
this.lastAccessedTime = System.currentTimeMillis();
|
||||||
this.credentials = credentials;
|
this.authenticatedUser = authenticatedUser;
|
||||||
this.userContext = userContext;
|
this.userContext = userContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the credentials used when the user associated with this session
|
* Returns the authenticated user associated with this session.
|
||||||
* authenticated.
|
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
* The credentials used when the user associated with this session
|
* The authenticated user associated with this session.
|
||||||
* authenticated.
|
|
||||||
*/
|
*/
|
||||||
public Credentials getCredentials() {
|
public AuthenticatedUser getAuthenticatedUser() {
|
||||||
return credentials;
|
return authenticatedUser;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Replaces the credentials associated with this session with the given
|
* Replaces the authenticated user associated with this session with the
|
||||||
* credentials.
|
* given authenticated user.
|
||||||
*
|
*
|
||||||
* @param credentials
|
* @param authenticatedUser
|
||||||
* The credentials to associate with this session.
|
* The authenticated user to associated with this session.
|
||||||
*/
|
*/
|
||||||
public void setCredentials(Credentials credentials) {
|
public void setAuthenticatedUser(AuthenticatedUser authenticatedUser) {
|
||||||
this.credentials = credentials;
|
this.authenticatedUser = authenticatedUser;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -24,6 +24,7 @@ package org.glyptodon.guacamole.net.basic.extension;
|
|||||||
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import org.glyptodon.guacamole.GuacamoleException;
|
import org.glyptodon.guacamole.GuacamoleException;
|
||||||
|
import org.glyptodon.guacamole.net.auth.AuthenticatedUser;
|
||||||
import org.glyptodon.guacamole.net.auth.AuthenticationProvider;
|
import org.glyptodon.guacamole.net.auth.AuthenticationProvider;
|
||||||
import org.glyptodon.guacamole.net.auth.Credentials;
|
import org.glyptodon.guacamole.net.auth.Credentials;
|
||||||
import org.glyptodon.guacamole.net.auth.UserContext;
|
import org.glyptodon.guacamole.net.auth.UserContext;
|
||||||
@@ -118,7 +119,7 @@ public class AuthenticationProviderFacade implements AuthenticationProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public UserContext getUserContext(Credentials credentials)
|
public AuthenticatedUser authenticateUser(Credentials credentials)
|
||||||
throws GuacamoleException {
|
throws GuacamoleException {
|
||||||
|
|
||||||
// Ignore auth attempts if no auth provider could be loaded
|
// Ignore auth attempts if no auth provider could be loaded
|
||||||
@@ -128,13 +129,13 @@ public class AuthenticationProviderFacade implements AuthenticationProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Delegate to underlying auth provider
|
// Delegate to underlying auth provider
|
||||||
return authProvider.getUserContext(credentials);
|
return authProvider.authenticateUser(credentials);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public UserContext updateUserContext(UserContext context, Credentials credentials)
|
public AuthenticatedUser updateAuthenticatedUser(AuthenticatedUser authenticatedUser,
|
||||||
throws GuacamoleException {
|
Credentials credentials) throws GuacamoleException {
|
||||||
|
|
||||||
// Ignore auth attempts if no auth provider could be loaded
|
// Ignore auth attempts if no auth provider could be loaded
|
||||||
if (authProvider == null) {
|
if (authProvider == null) {
|
||||||
@@ -143,7 +144,38 @@ public class AuthenticationProviderFacade implements AuthenticationProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Delegate to underlying auth provider
|
// Delegate to underlying auth provider
|
||||||
return authProvider.updateUserContext(context, credentials);
|
return authProvider.updateAuthenticatedUser(authenticatedUser, credentials);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public UserContext getUserContext(AuthenticatedUser authenticatedUser)
|
||||||
|
throws GuacamoleException {
|
||||||
|
|
||||||
|
// Ignore auth attempts if no auth provider could be loaded
|
||||||
|
if (authProvider == null) {
|
||||||
|
logger.warn("User data retrieval attempt denied because the authentication system could not be loaded. Please check for errors earlier in the logs.");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delegate to underlying auth provider
|
||||||
|
return authProvider.getUserContext(authenticatedUser);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public UserContext updateUserContext(UserContext context,
|
||||||
|
AuthenticatedUser authenticatedUser)
|
||||||
|
throws GuacamoleException {
|
||||||
|
|
||||||
|
// Ignore auth attempts if no auth provider could be loaded
|
||||||
|
if (authProvider == null) {
|
||||||
|
logger.warn("User data refresh attempt denied because the authentication system could not be loaded. Please check for errors earlier in the logs.");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delegate to underlying auth provider
|
||||||
|
return authProvider.updateUserContext(context, authenticatedUser);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -38,6 +38,7 @@ import javax.ws.rs.core.MultivaluedMap;
|
|||||||
import javax.xml.bind.DatatypeConverter;
|
import javax.xml.bind.DatatypeConverter;
|
||||||
import org.glyptodon.guacamole.GuacamoleException;
|
import org.glyptodon.guacamole.GuacamoleException;
|
||||||
import org.glyptodon.guacamole.environment.Environment;
|
import org.glyptodon.guacamole.environment.Environment;
|
||||||
|
import org.glyptodon.guacamole.net.auth.AuthenticatedUser;
|
||||||
import org.glyptodon.guacamole.net.auth.AuthenticationProvider;
|
import org.glyptodon.guacamole.net.auth.AuthenticationProvider;
|
||||||
import org.glyptodon.guacamole.net.auth.Credentials;
|
import org.glyptodon.guacamole.net.auth.Credentials;
|
||||||
import org.glyptodon.guacamole.net.auth.UserContext;
|
import org.glyptodon.guacamole.net.auth.UserContext;
|
||||||
@@ -223,27 +224,27 @@ public class TokenRESTService {
|
|||||||
credentials.setRequest(request);
|
credentials.setRequest(request);
|
||||||
credentials.setSession(request.getSession(true));
|
credentials.setSession(request.getSession(true));
|
||||||
|
|
||||||
UserContext userContext;
|
AuthenticatedUser authenticatedUser;
|
||||||
try {
|
try {
|
||||||
|
|
||||||
// Update existing user context if session already exists
|
// Re-authenticate user if session exists
|
||||||
if (existingSession != null)
|
if (existingSession != null)
|
||||||
userContext = authProvider.updateUserContext(existingSession.getUserContext(), credentials);
|
authenticatedUser = authProvider.updateAuthenticatedUser(existingSession.getAuthenticatedUser(), credentials);
|
||||||
|
|
||||||
/// Otherwise, generate a new user context
|
/// Otherwise, authenticate as a new user
|
||||||
else {
|
else {
|
||||||
|
|
||||||
userContext = authProvider.getUserContext(credentials);
|
authenticatedUser = authProvider.authenticateUser(credentials);
|
||||||
|
|
||||||
// Log successful authentication
|
// Log successful authentication
|
||||||
if (userContext != null && logger.isInfoEnabled())
|
if (authenticatedUser != null && logger.isInfoEnabled())
|
||||||
logger.info("User \"{}\" successfully authenticated from {}.",
|
logger.info("User \"{}\" successfully authenticated from {}.",
|
||||||
userContext.self().getIdentifier(), getLoggableAddress(request));
|
authenticatedUser.getIdentifier(), getLoggableAddress(request));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Request standard username/password if no user context was produced
|
// Request standard username/password if no user was produced
|
||||||
if (userContext == null)
|
if (authenticatedUser == null)
|
||||||
throw new GuacamoleInvalidCredentialsException("Permission Denied.",
|
throw new GuacamoleInvalidCredentialsException("Permission Denied.",
|
||||||
CredentialsInfo.USERNAME_PASSWORD);
|
CredentialsInfo.USERNAME_PASSWORD);
|
||||||
|
|
||||||
@@ -265,22 +266,34 @@ public class TokenRESTService {
|
|||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Generate or update user context
|
||||||
|
UserContext userContext;
|
||||||
|
if (existingSession != null)
|
||||||
|
userContext = authProvider.updateUserContext(existingSession.getUserContext(), authenticatedUser);
|
||||||
|
else
|
||||||
|
userContext = authProvider.getUserContext(authenticatedUser);
|
||||||
|
|
||||||
|
// STUB: Request standard username/password if no user context was produced
|
||||||
|
if (userContext == null)
|
||||||
|
throw new GuacamoleInvalidCredentialsException("Permission Denied.",
|
||||||
|
CredentialsInfo.USERNAME_PASSWORD);
|
||||||
|
|
||||||
// Update existing session, if it exists
|
// Update existing session, if it exists
|
||||||
String authToken;
|
String authToken;
|
||||||
if (existingSession != null) {
|
if (existingSession != null) {
|
||||||
authToken = token;
|
authToken = token;
|
||||||
existingSession.setCredentials(credentials);
|
existingSession.setAuthenticatedUser(authenticatedUser);
|
||||||
existingSession.setUserContext(userContext);
|
existingSession.setUserContext(userContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If no existing session, generate a new token/session pair
|
// If no existing session, generate a new token/session pair
|
||||||
else {
|
else {
|
||||||
authToken = authTokenGenerator.getToken();
|
authToken = authTokenGenerator.getToken();
|
||||||
tokenSessionMap.put(authToken, new GuacamoleSession(environment, credentials, userContext));
|
tokenSessionMap.put(authToken, new GuacamoleSession(environment, authenticatedUser, userContext));
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.debug("Login was successful for user \"{}\".", userContext.self().getIdentifier());
|
logger.debug("Login was successful for user \"{}\".", authenticatedUser.getIdentifier());
|
||||||
return new APIAuthToken(authToken, userContext.self().getIdentifier());
|
return new APIAuthToken(authToken, authenticatedUser.getIdentifier());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -46,6 +46,7 @@ import org.glyptodon.guacamole.net.auth.Credentials;
|
|||||||
import org.glyptodon.guacamole.net.auth.Directory;
|
import org.glyptodon.guacamole.net.auth.Directory;
|
||||||
import org.glyptodon.guacamole.net.auth.User;
|
import org.glyptodon.guacamole.net.auth.User;
|
||||||
import org.glyptodon.guacamole.net.auth.UserContext;
|
import org.glyptodon.guacamole.net.auth.UserContext;
|
||||||
|
import org.glyptodon.guacamole.net.auth.credentials.GuacamoleCredentialsException;
|
||||||
import org.glyptodon.guacamole.net.auth.permission.ObjectPermission;
|
import org.glyptodon.guacamole.net.auth.permission.ObjectPermission;
|
||||||
import org.glyptodon.guacamole.net.auth.permission.ObjectPermissionSet;
|
import org.glyptodon.guacamole.net.auth.permission.ObjectPermissionSet;
|
||||||
import org.glyptodon.guacamole.net.auth.permission.Permission;
|
import org.glyptodon.guacamole.net.auth.permission.Permission;
|
||||||
@@ -338,7 +339,15 @@ public class UserRESTService {
|
|||||||
credentials.setSession(request.getSession(true));
|
credentials.setSession(request.getSession(true));
|
||||||
|
|
||||||
// Verify that the old password was correct
|
// Verify that the old password was correct
|
||||||
if (authProvider.getUserContext(credentials) == null) {
|
try {
|
||||||
|
if (authProvider.authenticateUser(credentials) == null) {
|
||||||
|
throw new APIException(APIError.Type.PERMISSION_DENIED,
|
||||||
|
"Permission denied.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pass through any credentials exceptions as simple permission denied
|
||||||
|
catch (GuacamoleCredentialsException e) {
|
||||||
throw new APIException(APIError.Type.PERMISSION_DENIED,
|
throw new APIException(APIError.Type.PERMISSION_DENIED,
|
||||||
"Permission denied.");
|
"Permission denied.");
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user