GUACAMOLE-715: Merge automatic generation of in-memory skeleton users for JDBC auth.

The database authentication backend relies on the existence of a user object for processing permissions. With the addition of user group support, this is no longer sufficient, as a user may not exist in the database yet still have permissions effectively granted to them via the database due to their group memberships dictated elsewhere. Creating an in-memory skeleton user allows this processing to proceed.
This commit is contained in:
Mike Jumper
2019-04-09 11:10:48 -07:00
committed by GitHub
3 changed files with 60 additions and 12 deletions

View File

@@ -96,6 +96,7 @@ public class JDBCAuthenticationProviderService implements AuthenticationProvider
// Retrieve user account for already-authenticated user // Retrieve user account for already-authenticated user
ModeledUser user = userService.retrieveUser(authenticationProvider, authenticatedUser); ModeledUser user = userService.retrieveUser(authenticationProvider, authenticatedUser);
ModeledUserContext context = userContextProvider.get();
if (user != null && !user.isDisabled()) { if (user != null && !user.isDisabled()) {
// Enforce applicable account restrictions // Enforce applicable account restrictions
@@ -118,24 +119,23 @@ public class JDBCAuthenticationProviderService implements AuthenticationProvider
userService.resetExpiredPassword(user, authenticatedUser.getCredentials()); userService.resetExpiredPassword(user, authenticatedUser.getCredentials());
} }
// Return all data associated with the authenticated user }
ModeledUserContext context = userContextProvider.get();
context.init(user.getCurrentUser()); // If no user account is found, and database-specific account
return context; // restrictions do not apply, get an empty user.
else if (!databaseRestrictionsApplicable) {
user = userService.retrieveSkeletonUser(authenticationProvider, authenticatedUser);
} }
// Veto authentication result only if database-specific account // Veto authentication result only if database-specific account
// restrictions apply in this situation // restrictions apply in this situation
if (databaseRestrictionsApplicable) else
throw new GuacamoleInvalidCredentialsException("Invalid login", throw new GuacamoleInvalidCredentialsException("Invalid login",
CredentialsInfo.USERNAME_PASSWORD); CredentialsInfo.USERNAME_PASSWORD);
// There is no data to be returned for the user, either because they do // Initialize the UserContext with the user account and return it.
// not exist or because restrictions prevent their data from being context.init(user.getCurrentUser());
// retrieved, but no restrictions apply which should prevent the user return context;
// from authenticating entirely
return null;
} }

View File

@@ -127,6 +127,17 @@ public class UserModel extends EntityModel {
public UserModel() { public UserModel() {
super(EntityType.USER); super(EntityType.USER);
} }
/**
* Creates a new user having the provided identifier.
*
* @param identifier
* The identifier of the new user.
*/
public UserModel(String identifier) {
super(EntityType.USER);
super.setIdentifier(identifier);
}
/** /**
* Returns the hash of this user's password and password salt. This may be * Returns the hash of this user's password and password salt. This may be

View File

@@ -423,6 +423,43 @@ public class UserService extends ModeledDirectoryObjectService<ModeledUser, User
return user; return user;
} }
/**
* Generates an empty (skeleton) user corresponding to the given
* AuthenticatedUser. The user will not be stored in the database, and
* will only be available in-memory during the time the session is
* active.
*
* @param authenticationProvider
* The AuthenticationProvider on behalf of which the user is being
* retrieved.
*
* @param authenticatedUser
* The AuthenticatedUser to generate the skeleton account for.
*
* @return
* The empty ModeledUser which corresponds to the given
* AuthenticatedUser.
*
* @throws GuacamoleException
* If a ModeledUser object for the user corresponding to the given
* AuthenticatedUser cannot be created.
*/
public ModeledUser retrieveSkeletonUser(AuthenticationProvider authenticationProvider,
AuthenticatedUser authenticatedUser) throws GuacamoleException {
// Set up an empty user model
ModeledUser user = getObjectInstance(null,
new UserModel(authenticatedUser.getIdentifier()));
// Create user object, and configure cyclic reference
user.setCurrentUser(new ModeledAuthenticatedUser(authenticatedUser,
authenticationProvider, user));
// Return the new user.
return user;
}
/** /**
* Resets the password of the given user to the new password specified via * Resets the password of the given user to the new password specified via