mirror of
https://github.com/gyurix1968/guacamole-client.git
synced 2025-09-06 13:17:41 +00:00
GUAC-586: Implement AuthenticatedUser. Refactor to support authenticateUser(), etc. within the database AuthenticationProvider implementations.
This commit is contained in:
@@ -25,6 +25,7 @@ package org.glyptodon.guacamole.auth.jdbc.user;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import org.glyptodon.guacamole.net.auth.AuthenticationProvider;
|
||||
import org.glyptodon.guacamole.net.auth.Credentials;
|
||||
|
||||
/**
|
||||
@@ -32,7 +33,7 @@ import org.glyptodon.guacamole.net.auth.Credentials;
|
||||
*
|
||||
* @author Michael Jumper
|
||||
*/
|
||||
public class AuthenticatedUser {
|
||||
public class AuthenticatedUser implements org.glyptodon.guacamole.net.auth.AuthenticatedUser {
|
||||
|
||||
/**
|
||||
* The user that authenticated.
|
||||
@@ -44,6 +45,11 @@ public class AuthenticatedUser {
|
||||
*/
|
||||
private final Credentials credentials;
|
||||
|
||||
/**
|
||||
* The AuthenticationProvider that authenticated this user.
|
||||
*/
|
||||
private final AuthenticationProvider authenticationProvider;
|
||||
|
||||
/**
|
||||
* The host from which this user authenticated.
|
||||
*/
|
||||
@@ -106,13 +112,18 @@ public class AuthenticatedUser {
|
||||
* Creates a new AuthenticatedUser associating the given user with their
|
||||
* corresponding credentials.
|
||||
*
|
||||
* @param authenticationProvider
|
||||
* The AuthenticationProvider that has authenticated the given user.
|
||||
*
|
||||
* @param user
|
||||
* The user this object should represent.
|
||||
*
|
||||
* @param credentials
|
||||
* The credentials given by the user when they authenticated.
|
||||
*/
|
||||
public AuthenticatedUser(ModeledUser user, Credentials credentials) {
|
||||
public AuthenticatedUser(AuthenticationProvider authenticationProvider,
|
||||
ModeledUser user, Credentials credentials) {
|
||||
this.authenticationProvider = authenticationProvider;
|
||||
this.user = user;
|
||||
this.credentials = credentials;
|
||||
this.remoteHost = getRemoteHost(credentials);
|
||||
@@ -134,6 +145,7 @@ public class AuthenticatedUser {
|
||||
* @return
|
||||
* The credentials given during authentication by this user.
|
||||
*/
|
||||
@Override
|
||||
public Credentials getCredentials() {
|
||||
return credentials;
|
||||
}
|
||||
@@ -148,4 +160,19 @@ public class AuthenticatedUser {
|
||||
return remoteHost;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AuthenticationProvider getAuthenticationProvider() {
|
||||
return authenticationProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getIdentifier() {
|
||||
return user.getIdentifier();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setIdentifier(String identifier) {
|
||||
user.setIdentifier(identifier);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -25,17 +25,19 @@ package org.glyptodon.guacamole.auth.jdbc.user;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Provider;
|
||||
import org.glyptodon.guacamole.GuacamoleException;
|
||||
import org.glyptodon.guacamole.net.auth.AuthenticationProvider;
|
||||
import org.glyptodon.guacamole.net.auth.Credentials;
|
||||
import org.glyptodon.guacamole.net.auth.credentials.CredentialsInfo;
|
||||
import org.glyptodon.guacamole.net.auth.credentials.GuacamoleInvalidCredentialsException;
|
||||
|
||||
/**
|
||||
* Service which creates new UserContext instances for valid users based on
|
||||
* credentials.
|
||||
* Service which authenticates users based on credentials and provides for
|
||||
* the creation of corresponding, new UserContext objects for authenticated
|
||||
* users.
|
||||
*
|
||||
* @author Michael Jumper
|
||||
*/
|
||||
public class UserContextService {
|
||||
public class AuthenticationProviderService {
|
||||
|
||||
/**
|
||||
* Service for accessing users.
|
||||
@@ -51,11 +53,44 @@ public class UserContextService {
|
||||
|
||||
/**
|
||||
* Authenticates the user having the given credentials, returning a new
|
||||
* UserContext instance only if the credentials are valid. If the
|
||||
* AuthenticatedUser instance only if the credentials are valid. If the
|
||||
* credentials are invalid or expired, an appropriate GuacamoleException
|
||||
* will be thrown.
|
||||
*
|
||||
* @param authenticationProvider
|
||||
* The AuthenticationProvider on behalf of which the user is being
|
||||
* authenticated.
|
||||
*
|
||||
* @param credentials
|
||||
* The credentials to use to produce the AuthenticatedUser.
|
||||
*
|
||||
* @return
|
||||
* A new AuthenticatedUser instance for the user identified by the
|
||||
* given credentials.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If an error occurs during authentication, or if the given
|
||||
* credentials are invalid or expired.
|
||||
*/
|
||||
public AuthenticatedUser authenticateUser(AuthenticationProvider authenticationProvider,
|
||||
Credentials credentials) throws GuacamoleException {
|
||||
|
||||
// Authenticate user
|
||||
AuthenticatedUser user = userService.retrieveAuthenticatedUser(authenticationProvider, credentials);
|
||||
if (user != null)
|
||||
return user;
|
||||
|
||||
// Otherwise, unauthorized
|
||||
throw new GuacamoleInvalidCredentialsException("Invalid login", CredentialsInfo.USERNAME_PASSWORD);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returning a new UserContext instance for the given already-authenticated
|
||||
* user. A new placeholder account will be created for any user that does
|
||||
* not already exist within the database.
|
||||
*
|
||||
* @param authenticatedUser
|
||||
* The credentials to use to produce the UserContext.
|
||||
*
|
||||
* @return
|
||||
@@ -66,23 +101,18 @@ public class UserContextService {
|
||||
* If an error occurs during authentication, or if the given
|
||||
* credentials are invalid or expired.
|
||||
*/
|
||||
public org.glyptodon.guacamole.net.auth.UserContext
|
||||
getUserContext(Credentials credentials)
|
||||
public UserContext getUserContext(org.glyptodon.guacamole.net.auth.AuthenticatedUser authenticatedUser)
|
||||
throws GuacamoleException {
|
||||
|
||||
// Authenticate user
|
||||
ModeledUser user = userService.retrieveUser(credentials);
|
||||
if (user != null) {
|
||||
// Retrieve user account for already-authenticated user
|
||||
ModeledUser user = userService.retrieveUser(authenticatedUser);
|
||||
if (user == null)
|
||||
return null;
|
||||
|
||||
// Upon successful authentication, return new user context
|
||||
UserContext context = userContextProvider.get();
|
||||
context.init(user.getCurrentUser());
|
||||
return context;
|
||||
|
||||
}
|
||||
|
||||
// Otherwise, unauthorized
|
||||
throw new GuacamoleInvalidCredentialsException("Invalid login", CredentialsInfo.USERNAME_PASSWORD);
|
||||
// Link to user context
|
||||
UserContext context = userContextProvider.get();
|
||||
context.init(user.getCurrentUser());
|
||||
return context;
|
||||
|
||||
}
|
||||
|
@@ -40,6 +40,7 @@ import org.glyptodon.guacamole.auth.jdbc.permission.UserPermissionMapper;
|
||||
import org.glyptodon.guacamole.auth.jdbc.security.PasswordEncryptionService;
|
||||
import org.glyptodon.guacamole.form.Field;
|
||||
import org.glyptodon.guacamole.form.PasswordField;
|
||||
import org.glyptodon.guacamole.net.auth.AuthenticationProvider;
|
||||
import org.glyptodon.guacamole.net.auth.User;
|
||||
import org.glyptodon.guacamole.net.auth.credentials.CredentialsInfo;
|
||||
import org.glyptodon.guacamole.net.auth.credentials.GuacamoleInsufficientCredentialsException;
|
||||
@@ -265,18 +266,22 @@ public class UserService extends ModeledDirectoryObjectService<ModeledUser, User
|
||||
* the necessary additional parameters to reset the user's password, the
|
||||
* password is reset.
|
||||
*
|
||||
* @param authenticationProvider
|
||||
* The AuthenticationProvider on behalf of which the user is being
|
||||
* retrieved.
|
||||
*
|
||||
* @param credentials
|
||||
* The credentials to use when locating the user.
|
||||
*
|
||||
* @return
|
||||
* The existing ModeledUser object if the credentials given are valid,
|
||||
* null otherwise.
|
||||
* An AuthenticatedUser containing the existing ModeledUser object if
|
||||
* the credentials given are valid, null otherwise.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If the provided credentials to not conform to expectations.
|
||||
*/
|
||||
public ModeledUser retrieveUser(Credentials credentials)
|
||||
throws GuacamoleException {
|
||||
public AuthenticatedUser retrieveAuthenticatedUser(AuthenticationProvider authenticationProvider,
|
||||
Credentials credentials) throws GuacamoleException {
|
||||
|
||||
// Get username and password
|
||||
String username = credentials.getUsername();
|
||||
@@ -298,7 +303,7 @@ public class UserService extends ModeledDirectoryObjectService<ModeledUser, User
|
||||
|
||||
// Create corresponding user object, set up cyclic reference
|
||||
ModeledUser user = getObjectInstance(null, userModel);
|
||||
user.setCurrentUser(new AuthenticatedUser(user, credentials));
|
||||
user.setCurrentUser(new AuthenticatedUser(authenticationProvider, user, credentials));
|
||||
|
||||
// Verify user account is still valid as of today
|
||||
if (!user.isAccountValid())
|
||||
@@ -343,6 +348,41 @@ public class UserService extends ModeledDirectoryObjectService<ModeledUser, User
|
||||
}
|
||||
|
||||
// Return now-authenticated user
|
||||
return user.getCurrentUser();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the user corresponding to the given AuthenticatedUser from the
|
||||
* database. If no such user exists, a placeholder entry will be created
|
||||
* first.
|
||||
*
|
||||
* @param authenticatedUser
|
||||
* The AuthenticatedUser to retrieve the corresponding ModeledUser of.
|
||||
*
|
||||
* @return
|
||||
* The ModeledUser which corresponds to the given AuthenticatedUser,
|
||||
* created first if necessary.
|
||||
*/
|
||||
public ModeledUser retrieveUser(org.glyptodon.guacamole.net.auth.AuthenticatedUser authenticatedUser) {
|
||||
|
||||
// If we already queried this user, return that rather than querying again
|
||||
if (authenticatedUser instanceof AuthenticatedUser)
|
||||
return ((AuthenticatedUser) authenticatedUser).getUser();
|
||||
|
||||
// Get username
|
||||
String username = authenticatedUser.getIdentifier();
|
||||
|
||||
// Retrieve corresponding user model, if such a user exists
|
||||
UserModel userModel = userMapper.selectOne(username);
|
||||
if (userModel == null)
|
||||
return null;
|
||||
|
||||
// Create corresponding user object, set up cyclic reference
|
||||
ModeledUser user = getObjectInstance(null, userModel);
|
||||
user.setCurrentUser(new AuthenticatedUser(authenticatedUser.getAuthenticationProvider(), user, authenticatedUser.getCredentials()));
|
||||
|
||||
// Return already-authenticated user
|
||||
return user;
|
||||
|
||||
}
|
||||
|
@@ -31,9 +31,10 @@ import org.glyptodon.guacamole.net.auth.UserContext;
|
||||
import org.glyptodon.guacamole.auth.jdbc.JDBCAuthenticationProviderModule;
|
||||
import org.glyptodon.guacamole.auth.jdbc.tunnel.GuacamoleTunnelService;
|
||||
import org.glyptodon.guacamole.auth.jdbc.tunnel.ConfigurableGuacamoleTunnelService;
|
||||
import org.glyptodon.guacamole.auth.jdbc.user.UserContextService;
|
||||
import org.glyptodon.guacamole.auth.jdbc.user.AuthenticationProviderService;
|
||||
import org.glyptodon.guacamole.environment.Environment;
|
||||
import org.glyptodon.guacamole.environment.LocalEnvironment;
|
||||
import org.glyptodon.guacamole.net.auth.AuthenticatedUser;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -191,18 +192,37 @@ public class MySQLAuthenticationProvider implements AuthenticationProvider {
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserContext getUserContext(Credentials credentials)
|
||||
public AuthenticatedUser authenticateUser(Credentials credentials)
|
||||
throws GuacamoleException {
|
||||
|
||||
// Create AuthenticatedUser based on credentials, if valid
|
||||
AuthenticationProviderService authProviderService = injector.getInstance(AuthenticationProviderService.class);
|
||||
return authProviderService.authenticateUser(this, credentials);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public AuthenticatedUser updateAuthenticatedUser(AuthenticatedUser authenticatedUser,
|
||||
Credentials credentials) throws GuacamoleException {
|
||||
|
||||
// No need to update authenticated users
|
||||
return authenticatedUser;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserContext getUserContext(AuthenticatedUser authenticatedUser)
|
||||
throws GuacamoleException {
|
||||
|
||||
// Create UserContext based on credentials, if valid
|
||||
UserContextService userContextService = injector.getInstance(UserContextService.class);
|
||||
return userContextService.getUserContext(credentials);
|
||||
AuthenticationProviderService authProviderService = injector.getInstance(AuthenticationProviderService.class);
|
||||
return authProviderService.getUserContext(authenticatedUser);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserContext updateUserContext(UserContext context,
|
||||
Credentials credentials) throws GuacamoleException {
|
||||
AuthenticatedUser authenticatedUser) throws GuacamoleException {
|
||||
|
||||
// No need to update the context
|
||||
return context;
|
||||
|
@@ -31,9 +31,10 @@ import org.glyptodon.guacamole.net.auth.UserContext;
|
||||
import org.glyptodon.guacamole.auth.jdbc.JDBCAuthenticationProviderModule;
|
||||
import org.glyptodon.guacamole.auth.jdbc.tunnel.ConfigurableGuacamoleTunnelService;
|
||||
import org.glyptodon.guacamole.auth.jdbc.tunnel.GuacamoleTunnelService;
|
||||
import org.glyptodon.guacamole.auth.jdbc.user.UserContextService;
|
||||
import org.glyptodon.guacamole.auth.jdbc.user.AuthenticationProviderService;
|
||||
import org.glyptodon.guacamole.environment.Environment;
|
||||
import org.glyptodon.guacamole.environment.LocalEnvironment;
|
||||
import org.glyptodon.guacamole.net.auth.AuthenticatedUser;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -191,18 +192,37 @@ public class PostgreSQLAuthenticationProvider implements AuthenticationProvider
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserContext getUserContext(Credentials credentials)
|
||||
public AuthenticatedUser authenticateUser(Credentials credentials)
|
||||
throws GuacamoleException {
|
||||
|
||||
// Create AuthenticatedUser based on credentials, if valid
|
||||
AuthenticationProviderService authProviderService = injector.getInstance(AuthenticationProviderService.class);
|
||||
return authProviderService.authenticateUser(this, credentials);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public AuthenticatedUser updateAuthenticatedUser(AuthenticatedUser authenticatedUser,
|
||||
Credentials credentials) throws GuacamoleException {
|
||||
|
||||
// No need to update authenticated users
|
||||
return authenticatedUser;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserContext getUserContext(AuthenticatedUser authenticatedUser)
|
||||
throws GuacamoleException {
|
||||
|
||||
// Create UserContext based on credentials, if valid
|
||||
UserContextService userContextService = injector.getInstance(UserContextService.class);
|
||||
return userContextService.getUserContext(credentials);
|
||||
AuthenticationProviderService authProviderService = injector.getInstance(AuthenticationProviderService.class);
|
||||
return authProviderService.getUserContext(authenticatedUser);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserContext updateUserContext(UserContext context,
|
||||
Credentials credentials) throws GuacamoleException {
|
||||
AuthenticatedUser authenticatedUser) throws GuacamoleException {
|
||||
|
||||
// No need to update the context
|
||||
return context;
|
||||
|
Reference in New Issue
Block a user