GUACAMOLE-1364: Extract common base SSO classes.

This commit is contained in:
Michael Jumper
2021-12-03 20:29:13 -08:00
parent a6b38bec62
commit 7dc0b3b509
16 changed files with 320 additions and 514 deletions

View File

@@ -29,10 +29,10 @@ import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.auth.saml.acs.AssertedIdentity;
import org.apache.guacamole.auth.saml.acs.AuthenticationSessionManager;
import org.apache.guacamole.auth.saml.acs.SAMLService;
import org.apache.guacamole.auth.sso.SSOAuthenticationProviderService;
import org.apache.guacamole.form.Field;
import org.apache.guacamole.form.RedirectField;
import org.apache.guacamole.language.TranslatableMessage;
import org.apache.guacamole.net.auth.AuthenticatedUser;
import org.apache.guacamole.net.auth.Credentials;
import org.apache.guacamole.net.auth.credentials.CredentialsInfo;
import org.apache.guacamole.net.auth.credentials.GuacamoleInsufficientCredentialsException;
@@ -41,7 +41,7 @@ import org.apache.guacamole.net.auth.credentials.GuacamoleInsufficientCredential
* Service that authenticates Guacamole users by processing the responses of
* SAML identity providers.
*/
public class AuthenticationProviderService {
public class AuthenticationProviderService implements SSOAuthenticationProviderService {
/**
* The name of the query parameter that identifies an active authentication
@@ -67,22 +67,8 @@ public class AuthenticationProviderService {
@Inject
private SAMLService saml;
/**
* Returns an AuthenticatedUser representing the user authenticated by the
* given credentials.
*
* @param credentials
* The credentials to use for authentication.
*
* @return
* An AuthenticatedUser representing the user authenticated by the
* given credentials.
*
* @throws GuacamoleException
* If an error occurs while authenticating the user, or if access is
* denied.
*/
public AuthenticatedUser authenticateUser(Credentials credentials)
@Override
public SAMLAuthenticatedUser authenticateUser(Credentials credentials)
throws GuacamoleException {
// No authentication can be attempted without a corresponding HTTP
@@ -116,5 +102,10 @@ public class AuthenticationProviderService {
);
}
@Override
public void shutdown() {
sessionManager.shutdown();
}
}

View File

@@ -19,17 +19,9 @@
package org.apache.guacamole.auth.saml;
import com.google.inject.Guice;
import com.google.inject.Injector;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.auth.saml.acs.AssertionConsumerServiceResource;
import org.apache.guacamole.auth.saml.acs.AuthenticationSessionManager;
import org.apache.guacamole.auth.saml.user.SAMLAuthenticatedUser;
import org.apache.guacamole.net.auth.AuthenticatedUser;
import org.apache.guacamole.net.auth.AbstractAuthenticationProvider;
import org.apache.guacamole.net.auth.Credentials;
import org.apache.guacamole.net.auth.TokenInjectingUserContext;
import org.apache.guacamole.net.auth.UserContext;
import org.apache.guacamole.auth.sso.SSOAuthenticationProvider;
/**
* AuthenticationProvider implementation that authenticates Guacamole users
@@ -37,25 +29,14 @@ import org.apache.guacamole.net.auth.UserContext;
* storage for connection information, and must be layered with other modules
* for authenticated users to have access to Guacamole connections.
*/
public class SAMLAuthenticationProvider extends AbstractAuthenticationProvider {
/**
* Injector which will manage the object graph of this authentication
* provider.
*/
private final Injector injector;
public class SAMLAuthenticationProvider extends SSOAuthenticationProvider {
/**
* Creates a new SAMLAuthenticationProvider that authenticates users
* against a SAML IdP.
*/
public SAMLAuthenticationProvider() {
// Set up Guice injector.
injector = Guice.createInjector(
new SAMLAuthenticationProviderModule(this)
);
super(AuthenticationProviderService.class, new SAMLAuthenticationProviderModule());
}
@Override
@@ -65,38 +46,7 @@ public class SAMLAuthenticationProvider extends AbstractAuthenticationProvider {
@Override
public Object getResource() throws GuacamoleException {
return injector.getInstance(AssertionConsumerServiceResource.class);
}
@Override
public AuthenticatedUser authenticateUser(Credentials credentials)
throws GuacamoleException {
// Attempt to authenticate user with given credentials
AuthenticationProviderService authProviderService =
injector.getInstance(AuthenticationProviderService.class);
return authProviderService.authenticateUser(credentials);
}
@Override
public UserContext decorate(UserContext context,
AuthenticatedUser authenticatedUser, Credentials credentials)
throws GuacamoleException {
// Only decorate if the user authenticated with SAML
if (!(authenticatedUser instanceof SAMLAuthenticatedUser))
return context;
// Apply SAML-specific tokens to all connections / connection groups
return new TokenInjectingUserContext(context,
((SAMLAuthenticatedUser) authenticatedUser).getTokens());
}
@Override
public void shutdown() {
injector.getInstance(AuthenticationSessionManager.class).shutdown();
return getInjector().getInstance(AssertionConsumerServiceResource.class);
}
}

View File

@@ -25,57 +25,19 @@ import org.apache.guacamole.auth.saml.acs.AssertionConsumerServiceResource;
import org.apache.guacamole.auth.saml.acs.AuthenticationSessionManager;
import org.apache.guacamole.auth.saml.acs.IdentifierGenerator;
import org.apache.guacamole.auth.saml.acs.SAMLService;
import org.apache.guacamole.environment.Environment;
import org.apache.guacamole.environment.LocalEnvironment;
import org.apache.guacamole.net.auth.AuthenticationProvider;
/**
* Guice module which configures SAML-specific injections.
*/
public class SAMLAuthenticationProviderModule extends AbstractModule {
/**
* Guacamole server environment.
*/
private final Environment environment;
/**
* A reference to the SAMLAuthenticationProvider on behalf of which this
* module has configured injection.
*/
private final AuthenticationProvider authProvider;
/**
* Creates a new SAML authentication provider module which configures
* injection for the SAMLAuthenticationProvider.
*
* @param authProvider
* The AuthenticationProvider for which injection is being configured.
*/
public SAMLAuthenticationProviderModule(AuthenticationProvider authProvider) {
// Get local environment
this.environment = LocalEnvironment.getInstance();
// Store associated auth provider
this.authProvider = authProvider;
}
@Override
protected void configure() {
// Bind core implementations of guacamole-ext classes
bind(AuthenticationProvider.class).toInstance(authProvider);
bind(Environment.class).toInstance(environment);
// Bind SAML-specific services
bind(AssertionConsumerServiceResource.class);
bind(AuthenticationSessionManager.class);
bind(ConfigurationService.class);
bind(IdentifierGenerator.class);
bind(SAMLService.class);
}
}

View File

@@ -29,8 +29,7 @@ import java.util.stream.Collectors;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.auth.saml.acs.AssertedIdentity;
import org.apache.guacamole.auth.saml.conf.ConfigurationService;
import org.apache.guacamole.net.auth.AbstractAuthenticatedUser;
import org.apache.guacamole.net.auth.AuthenticationProvider;
import org.apache.guacamole.auth.sso.user.SSOAuthenticatedUser;
import org.apache.guacamole.net.auth.Credentials;
import org.apache.guacamole.token.TokenName;
@@ -39,7 +38,7 @@ import org.apache.guacamole.token.TokenName;
* identity and particular set of credentials with the SAML authentication
* provider.
*/
public class SAMLAuthenticatedUser extends AbstractAuthenticatedUser {
public class SAMLAuthenticatedUser extends SSOAuthenticatedUser {
/**
* The prefix that should be prepended to all parameter tokens generated
@@ -53,28 +52,6 @@ public class SAMLAuthenticatedUser extends AbstractAuthenticatedUser {
@Inject
private ConfigurationService confService;
/**
* Reference to the authentication provider associated with this
* authenticated user.
*/
@Inject
private AuthenticationProvider authProvider;
/**
* The credentials provided when this user was authenticated.
*/
private Credentials credentials;
/**
* The effective groups of the authenticated user.
*/
private Set<String> effectiveGroups;
/**
* Tokens associated with the authenticated user.
*/
private Map<String, String> tokens;
/**
* Returns a Map of all parameter tokens that should be made available for
* substitution based on the given {@link AssertedIdentity}. The resulting
@@ -144,35 +121,7 @@ public class SAMLAuthenticatedUser extends AbstractAuthenticatedUser {
*/
public void init(AssertedIdentity identity, Credentials credentials)
throws GuacamoleException {
this.credentials = credentials;
this.effectiveGroups = getGroups(identity);
this.tokens = getTokens(identity);
setIdentifier(identity.getUsername());
super.init(identity.getUsername(), credentials, getGroups(identity), getTokens(identity));
}
/**
* Returns a Map of tokens associated with this authenticated user.
*
* @return
* A map of token names and values available from this user account.
*/
public Map<String, String> getTokens() {
return tokens;
}
@Override
public AuthenticationProvider getAuthenticationProvider() {
return authProvider;
}
@Override
public Credentials getCredentials() {
return credentials;
}
@Override
public Set<String> getEffectiveUserGroups() {
return effectiveGroups;
}
}