GUACAMOLE-839: Ensure all SSO and related mechanisms set Credentials username.

This is necessary to ensure the ${GUAC_USERNAME} token is properly
substituted in cases where SSO and SSO-like auth methods are used.
This commit is contained in:
Michael Jumper
2025-04-14 10:20:00 -07:00
parent b9f43cd8f0
commit 0103b27547
5 changed files with 22 additions and 13 deletions

View File

@@ -66,9 +66,15 @@ public class AuthenticationProviderService {
// Get the username from the header configured in guacamole.properties // Get the username from the header configured in guacamole.properties
String username = credentials.getHeader(confService.getHttpAuthHeader()); String username = credentials.getHeader(confService.getHttpAuthHeader());
if (username != null) { if (username != null) {
// Update credentials with username provided via header for sake of
// ${GUAC_USERNAME} token
credentials.setUsername(username);
AuthenticatedUser authenticatedUser = authenticatedUserProvider.get(); AuthenticatedUser authenticatedUser = authenticatedUserProvider.get();
authenticatedUser.init(username, credentials); authenticatedUser.init(username, credentials);
return authenticatedUser; return authenticatedUser;
} }
// Authentication not provided via header, yet, so we request it. // Authentication not provided via header, yet, so we request it.

View File

@@ -76,6 +76,10 @@ public class AuthenticationProviderService {
if (userData == null) if (userData == null)
throw new GuacamoleInvalidCredentialsException("Permission denied.", CredentialsInfo.EMPTY); throw new GuacamoleInvalidCredentialsException("Permission denied.", CredentialsInfo.EMPTY);
// Update credentials with username provided via JSON for sake of
// ${GUAC_USERNAME} token
credentials.setUsername(userData.getUsername());
// Produce AuthenticatedUser associated with derived UserData // Produce AuthenticatedUser associated with derived UserData
AuthenticatedUser authenticatedUser = authenticatedUserProvider.get(); AuthenticatedUser authenticatedUser = authenticatedUserProvider.get();
authenticatedUser.init(credentials, userData); authenticatedUser.init(credentials, userData);

View File

@@ -60,14 +60,17 @@ public class SSOAuthenticatedUser extends AbstractAuthenticatedUser {
/** /**
* Initializes this SSOAuthenticatedUser, associating it with the given * Initializes this SSOAuthenticatedUser, associating it with the given
* username, credentials, groups, and parameter tokens. This function must * username, credentials, groups, and parameter tokens. The contents of the
* be invoked for every SSOAuthenticatedUser created. * given credentials are automatically updated to match the provided
* username. This function must be invoked for every SSOAuthenticatedUser
* created.
* *
* @param username * @param username
* The username of the user that was authenticated. * The username of the user that was authenticated.
* *
* @param credentials * @param credentials
* The credentials provided when this user was authenticated. * The credentials provided when this user was authenticated. These
* credentials will be updated to match the provided username.
* *
* @param effectiveGroups * @param effectiveGroups
* The groups that the authenticated user belongs to. * The groups that the authenticated user belongs to.
@@ -78,10 +81,16 @@ public class SSOAuthenticatedUser extends AbstractAuthenticatedUser {
*/ */
public void init(String username, Credentials credentials, public void init(String username, Credentials credentials,
Set<String> effectiveGroups, Map<String, String> tokens) { Set<String> effectiveGroups, Map<String, String> tokens) {
this.credentials = credentials; this.credentials = credentials;
this.effectiveGroups = Collections.unmodifiableSet(effectiveGroups); this.effectiveGroups = Collections.unmodifiableSet(effectiveGroups);
this.tokens = Collections.unmodifiableMap(tokens); this.tokens = Collections.unmodifiableMap(tokens);
setIdentifier(username); setIdentifier(username);
// Update credentials with username provided via SSO for sake of
// ${GUAC_USERNAME} token
credentials.setUsername(username);
} }
/** /**

View File

@@ -163,10 +163,6 @@ public class TicketValidationService {
// Canonicalize username as lowercase // Canonicalize username as lowercase
username = username.toLowerCase(); username = username.toLowerCase();
// Update credentials with username provided by CAS for sake of
// ${GUAC_USERNAME} token
credentials.setUsername(username);
// Retrieve password, attempt decryption, and set credentials. // Retrieve password, attempt decryption, and set credentials.
Object credObj = ticketAttrs.remove("credential"); Object credObj = ticketAttrs.remove("credential");
if (credObj != null) { if (credObj != null) {

View File

@@ -96,15 +96,9 @@ public class AuthenticationProviderService implements SSOAuthenticationProviderS
getSessionIdentifier(credentials)); getSessionIdentifier(credentials));
if (identity != null) { if (identity != null) {
// Back-port the username to the credentials
credentials.setUsername(identity.getUsername());
// Configure the AuthenticatedUser and return it
SAMLAuthenticatedUser authenticatedUser = authenticatedUserProvider.get(); SAMLAuthenticatedUser authenticatedUser = authenticatedUserProvider.get();
authenticatedUser.init(identity, credentials); authenticatedUser.init(identity, credentials);
return authenticatedUser; return authenticatedUser;
} }
// Redirect to SAML IdP if no SAML identity is associated with the // Redirect to SAML IdP if no SAML identity is associated with the