mirror of
				https://github.com/gyurix1968/guacamole-client.git
				synced 2025-10-31 09:03:21 +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 | ||||
|  * 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; | ||||
|  | ||||
| /** | ||||
|  * Provides means of accessing and managing the available | ||||
|  * GuacamoleConfiguration objects and User objects. Access to each configuration | ||||
|  * and each user is limited by a given Credentials object. | ||||
|  * Provides means of authorizing users and for accessing and managing data | ||||
|  * associated with those users. Access to such data is limited according to the | ||||
|  * AuthenticationProvider implementation. | ||||
|  * | ||||
|  * @author Michael Jumper | ||||
|  */ | ||||
| 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. | ||||
|      * @return The UserContext of the user authorized by the given credentials, | ||||
|      *         or null if the credentials are not authorized. | ||||
|      * @param credentials | ||||
|      *     The credentials to use for authentication. | ||||
|      * | ||||
|      * @throws GuacamoleException If an error occurs while creating the | ||||
|      *                            UserContext. | ||||
|      * @return | ||||
|      *     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; | ||||
|  | ||||
|     /** | ||||
|      * Returns a new or updated UserContext for the user authorized by the | ||||
|      * give credentials and having the given existing 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(). | ||||
|      *  | ||||
|      * @param context The existing UserContext belonging to the user in | ||||
|      *                question. | ||||
|      * @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 | ||||
|      *                            UserContext. | ||||
|      * Returns a new or updated AuthenticatedUser for the given credentials | ||||
|      * already having produced the given AuthenticatedUser. 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 credentials | ||||
|      *     The credentials to use for authentication. | ||||
|      * | ||||
|      * @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 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; | ||||
|  | ||||
|     /** | ||||
|      * 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; | ||||
|  | ||||
| import java.util.Map; | ||||
| import java.util.UUID; | ||||
| 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.AuthenticatedUser; | ||||
| import org.glyptodon.guacamole.net.auth.Credentials; | ||||
| import org.glyptodon.guacamole.net.auth.UserContext; | ||||
| import org.glyptodon.guacamole.protocol.GuacamoleConfiguration; | ||||
| @@ -62,12 +65,100 @@ public abstract class SimpleAuthenticationProvider | ||||
|             getAuthorizedConfigurations(Credentials credentials) | ||||
|             throws GuacamoleException; | ||||
|  | ||||
|     @Override | ||||
|     public UserContext getUserContext(Credentials credentials) | ||||
|             throws GuacamoleException { | ||||
|     /** | ||||
|      * AuthenticatedUser which contains its own predefined set of authorized | ||||
|      * configurations. | ||||
|      * | ||||
|      * @author Michael Jumper | ||||
|      */ | ||||
|     private class SimpleAuthenticatedUser extends AbstractAuthenticatedUser { | ||||
|  | ||||
|         // Get username, if any | ||||
|         String username = credentials.getUsername(); | ||||
|         /** | ||||
|          * 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(); | ||||
|             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 | ||||
|         Map<String, GuacamoleConfiguration> configs = | ||||
| @@ -80,24 +171,90 @@ public abstract class SimpleAuthenticationProvider | ||||
|         // Build credential TokenFilter | ||||
|         TokenFilter tokenFilter = new TokenFilter(); | ||||
|         StandardTokens.addStandardTokens(tokenFilter, credentials); | ||||
|          | ||||
|  | ||||
|         // Filter each configuration | ||||
|         for (GuacamoleConfiguration config : configs.values()) | ||||
|             tokenFilter.filterValues(config.getParameters()); | ||||
|          | ||||
|         // Return user context restricted to authorized 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); | ||||
|         return 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 | ||||
|     public UserContext updateUserContext(UserContext context, | ||||
|         Credentials credentials) throws GuacamoleException { | ||||
|         AuthenticatedUser authorizedUser) throws GuacamoleException { | ||||
|  | ||||
|         // Simply return the given context, updating nothing | ||||
|         return context; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user