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:
@@ -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
|
||||
* 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.environment.Environment;
|
||||
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.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -46,9 +46,9 @@ public class GuacamoleSession {
|
||||
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.
|
||||
@@ -72,8 +72,8 @@ public class GuacamoleSession {
|
||||
* The environment of the Guacamole server associated with this new
|
||||
* session.
|
||||
*
|
||||
* @param credentials
|
||||
* The credentials provided by the user during login.
|
||||
* @param authenticatedUser
|
||||
* The authenticated user to associate this session with.
|
||||
*
|
||||
* @param userContext
|
||||
* The user context to associate this session with.
|
||||
@@ -81,36 +81,35 @@ public class GuacamoleSession {
|
||||
* @throws GuacamoleException
|
||||
* If an error prevents the session from being created.
|
||||
*/
|
||||
public GuacamoleSession(Environment environment, Credentials credentials,
|
||||
UserContext userContext) throws GuacamoleException {
|
||||
public GuacamoleSession(Environment environment,
|
||||
AuthenticatedUser authenticatedUser, UserContext userContext)
|
||||
throws GuacamoleException {
|
||||
this.lastAccessedTime = System.currentTimeMillis();
|
||||
this.credentials = credentials;
|
||||
this.authenticatedUser = authenticatedUser;
|
||||
this.userContext = userContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the credentials used when the user associated with this session
|
||||
* authenticated.
|
||||
* Returns the authenticated user associated with this session.
|
||||
*
|
||||
* @return
|
||||
* The credentials used when the user associated with this session
|
||||
* authenticated.
|
||||
* The authenticated user associated with this session.
|
||||
*/
|
||||
public Credentials getCredentials() {
|
||||
return credentials;
|
||||
public AuthenticatedUser getAuthenticatedUser() {
|
||||
return authenticatedUser;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces the credentials associated with this session with the given
|
||||
* credentials.
|
||||
* Replaces the authenticated user associated with this session with the
|
||||
* given authenticated user.
|
||||
*
|
||||
* @param credentials
|
||||
* The credentials to associate with this session.
|
||||
* @param authenticatedUser
|
||||
* The authenticated user to associated with this session.
|
||||
*/
|
||||
public void setCredentials(Credentials credentials) {
|
||||
this.credentials = credentials;
|
||||
public void setAuthenticatedUser(AuthenticatedUser authenticatedUser) {
|
||||
this.authenticatedUser = authenticatedUser;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the UserContext associated with this session.
|
||||
*
|
||||
|
@@ -24,6 +24,7 @@ package org.glyptodon.guacamole.net.basic.extension;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
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.Credentials;
|
||||
import org.glyptodon.guacamole.net.auth.UserContext;
|
||||
@@ -118,7 +119,7 @@ public class AuthenticationProviderFacade implements AuthenticationProvider {
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserContext getUserContext(Credentials credentials)
|
||||
public AuthenticatedUser authenticateUser(Credentials credentials)
|
||||
throws GuacamoleException {
|
||||
|
||||
// Ignore auth attempts if no auth provider could be loaded
|
||||
@@ -128,13 +129,13 @@ public class AuthenticationProviderFacade implements AuthenticationProvider {
|
||||
}
|
||||
|
||||
// Delegate to underlying auth provider
|
||||
return authProvider.getUserContext(credentials);
|
||||
|
||||
return authProvider.authenticateUser(credentials);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserContext updateUserContext(UserContext context, Credentials credentials)
|
||||
throws GuacamoleException {
|
||||
public AuthenticatedUser updateAuthenticatedUser(AuthenticatedUser authenticatedUser,
|
||||
Credentials credentials) throws GuacamoleException {
|
||||
|
||||
// Ignore auth attempts if no auth provider could be loaded
|
||||
if (authProvider == null) {
|
||||
@@ -143,7 +144,38 @@ public class AuthenticationProviderFacade implements AuthenticationProvider {
|
||||
}
|
||||
|
||||
// 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 org.glyptodon.guacamole.GuacamoleException;
|
||||
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.Credentials;
|
||||
import org.glyptodon.guacamole.net.auth.UserContext;
|
||||
@@ -222,28 +223,28 @@ public class TokenRESTService {
|
||||
credentials.setPassword(password);
|
||||
credentials.setRequest(request);
|
||||
credentials.setSession(request.getSession(true));
|
||||
|
||||
UserContext userContext;
|
||||
|
||||
AuthenticatedUser authenticatedUser;
|
||||
try {
|
||||
|
||||
// Update existing user context if session already exists
|
||||
// Re-authenticate user if session exists
|
||||
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 {
|
||||
|
||||
userContext = authProvider.getUserContext(credentials);
|
||||
authenticatedUser = authProvider.authenticateUser(credentials);
|
||||
|
||||
// Log successful authentication
|
||||
if (userContext != null && logger.isInfoEnabled())
|
||||
if (authenticatedUser != null && logger.isInfoEnabled())
|
||||
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
|
||||
if (userContext == null)
|
||||
// Request standard username/password if no user was produced
|
||||
if (authenticatedUser == null)
|
||||
throw new GuacamoleInvalidCredentialsException("Permission Denied.",
|
||||
CredentialsInfo.USERNAME_PASSWORD);
|
||||
|
||||
@@ -264,23 +265,35 @@ public class TokenRESTService {
|
||||
|
||||
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
|
||||
String authToken;
|
||||
if (existingSession != null) {
|
||||
authToken = token;
|
||||
existingSession.setCredentials(credentials);
|
||||
existingSession.setAuthenticatedUser(authenticatedUser);
|
||||
existingSession.setUserContext(userContext);
|
||||
}
|
||||
|
||||
// If no existing session, generate a new token/session pair
|
||||
else {
|
||||
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());
|
||||
return new APIAuthToken(authToken, userContext.self().getIdentifier());
|
||||
logger.debug("Login was successful for user \"{}\".", authenticatedUser.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.User;
|
||||
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.ObjectPermissionSet;
|
||||
import org.glyptodon.guacamole.net.auth.permission.Permission;
|
||||
@@ -337,8 +338,16 @@ public class UserRESTService {
|
||||
credentials.setRequest(request);
|
||||
credentials.setSession(request.getSession(true));
|
||||
|
||||
// Verify that the old password was correct
|
||||
if (authProvider.getUserContext(credentials) == null) {
|
||||
// Verify that the old password was correct
|
||||
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,
|
||||
"Permission denied.");
|
||||
}
|
||||
|
Reference in New Issue
Block a user