diff --git a/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-base/pom.xml b/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-base/pom.xml index 50ec02f5f..b23280596 100644 --- a/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-base/pom.xml +++ b/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-base/pom.xml @@ -36,4 +36,20 @@ ../../ + + + + + org.apache.guacamole + guacamole-ext + + + + + com.google.inject + guice + + + + diff --git a/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-base/src/main/java/org/apache/guacamole/auth/sso/SSOAuthenticationProvider.java b/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-base/src/main/java/org/apache/guacamole/auth/sso/SSOAuthenticationProvider.java new file mode 100644 index 000000000..1a389283f --- /dev/null +++ b/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-base/src/main/java/org/apache/guacamole/auth/sso/SSOAuthenticationProvider.java @@ -0,0 +1,153 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.guacamole.auth.sso; + +import com.google.common.collect.Iterables; +import com.google.inject.AbstractModule; +import com.google.inject.Guice; +import com.google.inject.Injector; +import com.google.inject.Module; +import java.util.Arrays; +import java.util.Collections; +import org.apache.guacamole.GuacamoleException; +import org.apache.guacamole.auth.sso.user.SSOAuthenticatedUser; +import org.apache.guacamole.environment.Environment; +import org.apache.guacamole.environment.LocalEnvironment; +import org.apache.guacamole.net.auth.AbstractAuthenticationProvider; +import org.apache.guacamole.net.auth.AuthenticatedUser; +import org.apache.guacamole.net.auth.AuthenticationProvider; +import org.apache.guacamole.net.auth.Credentials; +import org.apache.guacamole.net.auth.TokenInjectingUserContext; +import org.apache.guacamole.net.auth.UserContext; + +/** + * An AuthenticationProvider which authenticates users against an arbitrary + * SSO system. Guice dependency injection is automatically configured via + * modules provided by the implementation. Implementations will typically + * provide no storage for connections, instead relying on other installed + * extensions. + */ +public abstract class SSOAuthenticationProvider extends AbstractAuthenticationProvider { + + /** + * The Guice injector. + */ + private final Injector injector; + + /** + * Creates a new SSOAuthenticationProvider that authenticates users against + * an arbitrary SSO system. Guice dependency injection is automatically + * configured, with the resulting injector available to implementations via + * {@link #getInjector()}. Core authentication functions are provided by + * the given SSOAuthenticationProviderService implementation, and + * additional implementation-specific services, providers, etc. may be + * bound by specifying additional Guice modules. + * + * @param authService + * The SSOAuthenticationProviderService implementation that should be + * used for core authentication functions. + * + * @param modules + * Any additional modules that should be used when creating the Guice + * injector. + */ + public SSOAuthenticationProvider( + Class authService, + Module... modules) { + this(authService, Arrays.asList(modules)); + } + + /** + * Creates a new SSOAuthenticationProvider that authenticates users against + * an arbitrary SSO system. Guice dependency injection is automatically + * configured, with the resulting injector available to implementations via + * {@link #getInjector()}. Core authentication functions are provided by + * the given SSOAuthenticationProviderService implementation, and + * additional may be provided by specifying additional Guice modules. + * + * @param authService + * The SSOAuthenticationProviderService implementation that should be + * used for core authentication functions. + * + * @param modules + * Any additional modules that should be used when creating the Guice + * injector. + */ + public SSOAuthenticationProvider( + Class authService, + Iterable modules) { + injector = Guice.createInjector(Iterables.concat(Collections.singletonList(new AbstractModule() { + + @Override + protected void configure() { + bind(AuthenticationProvider.class).toInstance(SSOAuthenticationProvider.this); + bind(Environment.class).toInstance(LocalEnvironment.getInstance()); + bind(SSOAuthenticationProviderService.class).to(authService); + } + + }), modules)); + } + + /** + * Returns the Guice injector available for use by this implementation of + * SSOAuthenticationProvider. The returned injector has already been + * configured with all modules supplied at the time this + * SSOAuthenticationProvider was created. + * + * @return + * The Guice injector available for use by this implementation of + * SSOAuthenticationProvider. + */ + protected final Injector getInjector() { + return injector; + } + + @Override + public AuthenticatedUser authenticateUser(Credentials credentials) + throws GuacamoleException { + + // Attempt to authenticate user with given credentials + SSOAuthenticationProviderService authProviderService = + injector.getInstance(SSOAuthenticationProviderService.class); + + return authProviderService.authenticateUser(credentials); + + } + + @Override + public UserContext decorate(UserContext context, + AuthenticatedUser authenticatedUser, Credentials credentials) + throws GuacamoleException { + + // Only inject tokens for users authenticated by this extension + if (authenticatedUser.getAuthenticationProvider() != this) + return context; + + return new TokenInjectingUserContext(context, + ((SSOAuthenticatedUser) authenticatedUser).getTokens()); + + } + + @Override + public void shutdown() { + injector.getInstance(SSOAuthenticationProviderService.class).shutdown(); + } + +} diff --git a/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-base/src/main/java/org/apache/guacamole/auth/sso/SSOAuthenticationProviderService.java b/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-base/src/main/java/org/apache/guacamole/auth/sso/SSOAuthenticationProviderService.java new file mode 100644 index 000000000..cd2d424b2 --- /dev/null +++ b/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-base/src/main/java/org/apache/guacamole/auth/sso/SSOAuthenticationProviderService.java @@ -0,0 +1,60 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.guacamole.auth.sso; + +import org.apache.guacamole.GuacamoleException; +import org.apache.guacamole.auth.sso.user.SSOAuthenticatedUser; +import org.apache.guacamole.net.auth.Credentials; + +/** + * Service that authenticates Guacamole users by leveraging an arbitrary SSO + * service. + */ +public interface SSOAuthenticationProviderService { + + /** + * Returns an SSOAuthenticatedUser representing the user authenticated by + * the given credentials. Tokens associated with the returned + * SSOAuthenticatedUser will automatically be injected into any connections + * used by that user during their session. + * + * @param credentials + * The credentials to use for authentication. + * + * @return + * An SSOAuthenticatedUser representing the user authenticated by the + * given credentials. + * + * @throws GuacamoleException + * If an error occurs while authenticating the user, or if access is + * denied. + */ + SSOAuthenticatedUser authenticateUser(Credentials credentials) + throws GuacamoleException; + + /** + * Frees all resources associated with the relevant + * SSOAuthenticationProvider implementation. This function is automatically + * invoked when an implementation of SSOAuthenticationProvider is shut + * down. + */ + void shutdown(); + +} diff --git a/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-cas/src/main/java/org/apache/guacamole/auth/cas/user/CASAuthenticatedUser.java b/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-base/src/main/java/org/apache/guacamole/auth/sso/user/SSOAuthenticatedUser.java similarity index 61% rename from extensions/guacamole-auth-sso/modules/guacamole-auth-sso-cas/src/main/java/org/apache/guacamole/auth/cas/user/CASAuthenticatedUser.java rename to extensions/guacamole-auth-sso/modules/guacamole-auth-sso-base/src/main/java/org/apache/guacamole/auth/sso/user/SSOAuthenticatedUser.java index b79344eb8..1e46f6d25 100644 --- a/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-cas/src/main/java/org/apache/guacamole/auth/cas/user/CASAuthenticatedUser.java +++ b/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-base/src/main/java/org/apache/guacamole/auth/sso/user/SSOAuthenticatedUser.java @@ -17,7 +17,7 @@ * under the License. */ -package org.apache.guacamole.auth.cas.user; +package org.apache.guacamole.auth.sso.user; import com.google.inject.Inject; import java.util.Collections; @@ -28,11 +28,12 @@ import org.apache.guacamole.net.auth.AuthenticationProvider; import org.apache.guacamole.net.auth.Credentials; /** - * An CAS-specific implementation of AuthenticatedUser, associating a - * username and particular set of credentials with the CAS authentication - * provider. + * An AuthenticatedUser whose identity has been supplied by an arbitrary SSO + * service. An SSOAuthenticatedUser may additionally be associated with a set + * of user-specific parameter tokens to be injected into any connections used + * by that user. */ -public class CASAuthenticatedUser extends AbstractAuthenticatedUser { +public class SSOAuthenticatedUser extends AbstractAuthenticatedUser { /** * Reference to the authentication provider associated with this @@ -45,60 +46,53 @@ public class CASAuthenticatedUser extends AbstractAuthenticatedUser { * The credentials provided when this user was authenticated. */ private Credentials credentials; - - /** - * Tokens associated with this authenticated user. - */ - private Map tokens; /** - * The unique identifiers of all user groups which this user is a member of. + * The groups that this user belongs to. */ private Set effectiveGroups; /** - * Initializes this AuthenticatedUser using the given username and - * credentials, and an empty map of parameter tokens. - * - * @param username - * The username of the user that was authenticated. - * - * @param credentials - * The credentials provided when this user was authenticated. + * Parameter tokens to be automatically injected for any connections used + * by this user. */ - public void init(String username, Credentials credentials) { - this.init(username, credentials, Collections.emptyMap(), Collections.emptySet()); - } - + private Map tokens; + /** - * Initializes this AuthenticatedUser using the given username, - * credentials, and parameter tokens. + * Initializes this SSOAuthenticatedUser, associating it with the given + * username, credentials, groups, and parameter tokens. This function must + * be invoked for every SSOAuthenticatedUser created. * * @param username * The username of the user that was authenticated. * * @param credentials * The credentials provided when this user was authenticated. - * + * + * @param effectiveGroups + * The groups that the authenticated user belongs to. + * * @param tokens * A map of all the name/value pairs that should be available - * as tokens when connections are established with this user. + * as tokens when connections are established by this user. */ public void init(String username, Credentials credentials, - Map tokens, Set effectiveGroups) { + Set effectiveGroups, Map tokens) { this.credentials = credentials; + this.effectiveGroups = Collections.unmodifiableSet(effectiveGroups); this.tokens = Collections.unmodifiableMap(tokens); - this.effectiveGroups = effectiveGroups; - setIdentifier(username.toLowerCase()); + setIdentifier(username); } /** - * Returns a Map containing the name/value pairs that can be applied - * as parameter tokens when connections are established by the user. - * + * Returns a Map of the parameter tokens that should be automatically + * injected into connections used by this user during their session. If + * there are no parameter tokens applicable to the SSO implementation, this + * may simply be an empty map. + * * @return - * A Map containing all of the name/value pairs that can be - * used as parameter tokens by this user. + * A map of the parameter token name/value pairs that should be + * automatically injected into connections used by this user. */ public Map getTokens() { return tokens; diff --git a/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-cas/src/main/java/org/apache/guacamole/auth/cas/AuthenticationProviderService.java b/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-cas/src/main/java/org/apache/guacamole/auth/cas/AuthenticationProviderService.java index 98fc6615f..7aa3c1b87 100644 --- a/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-cas/src/main/java/org/apache/guacamole/auth/cas/AuthenticationProviderService.java +++ b/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-cas/src/main/java/org/apache/guacamole/auth/cas/AuthenticationProviderService.java @@ -30,14 +30,14 @@ import org.apache.guacamole.net.auth.credentials.GuacamoleInvalidCredentialsExce import org.apache.guacamole.auth.cas.conf.ConfigurationService; import org.apache.guacamole.auth.cas.form.CASTicketField; import org.apache.guacamole.auth.cas.ticket.TicketValidationService; -import org.apache.guacamole.auth.cas.user.CASAuthenticatedUser; +import org.apache.guacamole.auth.sso.SSOAuthenticationProviderService; +import org.apache.guacamole.auth.sso.user.SSOAuthenticatedUser; import org.apache.guacamole.language.TranslatableMessage; /** - * Service providing convenience functions for the CAS AuthenticationProvider - * implementation. + * Service that authenticates Guacamole users by processing CAS tickets. */ -public class AuthenticationProviderService { +public class AuthenticationProviderService implements SSOAuthenticationProviderService { /** * Service for retrieving CAS configuration information. @@ -51,22 +51,8 @@ public class AuthenticationProviderService { @Inject private TicketValidationService ticketService; - /** - * Returns an AuthenticatedUser representing the user authenticated by the - * given credentials. - * - * @param credentials - * The credentials to use for authentication. - * - * @return - * A CASAuthenticatedUser representing the user authenticated by the - * given credentials. - * - * @throws GuacamoleException - * If an error occurs while authenticating the user, or if access is - * denied. - */ - public CASAuthenticatedUser authenticateUser(Credentials credentials) + @Override + public SSOAuthenticatedUser authenticateUser(Credentials credentials) throws GuacamoleException { // Pull CAS ticket from request if present @@ -95,4 +81,9 @@ public class AuthenticationProviderService { } + @Override + public void shutdown() { + // Nothing to clean up + } + } diff --git a/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-cas/src/main/java/org/apache/guacamole/auth/cas/CASAuthenticationProvider.java b/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-cas/src/main/java/org/apache/guacamole/auth/cas/CASAuthenticationProvider.java index 5b4154ef8..dda5b73b5 100644 --- a/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-cas/src/main/java/org/apache/guacamole/auth/cas/CASAuthenticationProvider.java +++ b/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-cas/src/main/java/org/apache/guacamole/auth/cas/CASAuthenticationProvider.java @@ -19,15 +19,7 @@ package org.apache.guacamole.auth.cas; -import com.google.inject.Guice; -import com.google.inject.Injector; -import org.apache.guacamole.GuacamoleException; -import org.apache.guacamole.auth.cas.user.CASAuthenticatedUser; -import org.apache.guacamole.net.auth.AbstractAuthenticationProvider; -import org.apache.guacamole.net.auth.AuthenticatedUser; -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; /** * Guacamole authentication backend which authenticates users using an @@ -35,56 +27,19 @@ import org.apache.guacamole.net.auth.UserContext; * provided - only authentication. Storage must be provided by some other * extension. */ -public class CASAuthenticationProvider extends AbstractAuthenticationProvider { - - /** - * Injector which will manage the object graph of this authentication - * provider. - */ - private final Injector injector; - +public class CASAuthenticationProvider extends SSOAuthenticationProvider { + /** * Creates a new CASAuthenticationProvider that authenticates users * against an CAS service - * - * @throws GuacamoleException - * If a required property is missing, or an error occurs while parsing - * a property. */ - public CASAuthenticationProvider() throws GuacamoleException { - - // Set up Guice injector. - injector = Guice.createInjector( - new CASAuthenticationProviderModule(this) - ); - + public CASAuthenticationProvider() { + super(AuthenticationProviderService.class, new CASAuthenticationProviderModule()); } - + @Override public String getIdentifier() { return "cas"; } - @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 { - - if (!(authenticatedUser instanceof CASAuthenticatedUser)) - return context; - - return new TokenInjectingUserContext(context, - ((CASAuthenticatedUser) authenticatedUser).getTokens()); - } - } diff --git a/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-cas/src/main/java/org/apache/guacamole/auth/cas/CASAuthenticationProviderModule.java b/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-cas/src/main/java/org/apache/guacamole/auth/cas/CASAuthenticationProviderModule.java index a259e449d..0cfeacd42 100644 --- a/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-cas/src/main/java/org/apache/guacamole/auth/cas/CASAuthenticationProviderModule.java +++ b/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-cas/src/main/java/org/apache/guacamole/auth/cas/CASAuthenticationProviderModule.java @@ -19,12 +19,8 @@ package org.apache.guacamole.auth.cas; -import org.apache.guacamole.auth.cas.conf.ConfigurationService; import com.google.inject.AbstractModule; -import org.apache.guacamole.GuacamoleException; -import org.apache.guacamole.environment.Environment; -import org.apache.guacamole.environment.LocalEnvironment; -import org.apache.guacamole.net.auth.AuthenticationProvider; +import org.apache.guacamole.auth.cas.conf.ConfigurationService; import org.apache.guacamole.auth.cas.ticket.TicketValidationService; /** @@ -32,50 +28,10 @@ import org.apache.guacamole.auth.cas.ticket.TicketValidationService; */ public class CASAuthenticationProviderModule extends AbstractModule { - /** - * Guacamole server environment. - */ - private final Environment environment; - - /** - * A reference to the CASAuthenticationProvider on behalf of which this - * module has configured injection. - */ - private final AuthenticationProvider authProvider; - - /** - * Creates a new CAS authentication provider module which configures - * injection for the CASAuthenticationProvider. - * - * @param authProvider - * The AuthenticationProvider for which injection is being configured. - * - * @throws GuacamoleException - * If an error occurs while retrieving the Guacamole server - * environment. - */ - public CASAuthenticationProviderModule(AuthenticationProvider authProvider) - throws GuacamoleException { - - // 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 CAS-specific services bind(ConfigurationService.class); bind(TicketValidationService.class); - } } diff --git a/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-cas/src/main/java/org/apache/guacamole/auth/cas/ticket/TicketValidationService.java b/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-cas/src/main/java/org/apache/guacamole/auth/cas/ticket/TicketValidationService.java index 17ef92342..8b53b6982 100644 --- a/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-cas/src/main/java/org/apache/guacamole/auth/cas/ticket/TicketValidationService.java +++ b/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-cas/src/main/java/org/apache/guacamole/auth/cas/ticket/TicketValidationService.java @@ -41,7 +41,7 @@ import org.apache.guacamole.GuacamoleException; import org.apache.guacamole.GuacamoleSecurityException; import org.apache.guacamole.GuacamoleServerException; import org.apache.guacamole.auth.cas.conf.ConfigurationService; -import org.apache.guacamole.auth.cas.user.CASAuthenticatedUser; +import org.apache.guacamole.auth.sso.user.SSOAuthenticatedUser; import org.apache.guacamole.net.auth.Credentials; import org.apache.guacamole.token.TokenName; import org.jasig.cas.client.authentication.AttributePrincipal; @@ -77,7 +77,7 @@ public class TicketValidationService { * Provider for AuthenticatedUser objects. */ @Inject - private Provider authenticatedUserProvider; + private Provider authenticatedUserProvider; /** * Converts the given CAS attribute value object (whose type is variable) @@ -132,7 +132,7 @@ public class TicketValidationService { * If the ID ticket is not valid or guacamole.properties could * not be parsed. */ - public CASAuthenticatedUser validateTicket(String ticket, + public SSOAuthenticatedUser validateTicket(String ticket, Credentials credentials) throws GuacamoleException { // Create a ticket validator that uses the configured CAS URL @@ -160,6 +160,9 @@ public class TicketValidationService { if (username == null) throw new GuacamoleSecurityException("No username provided by CAS."); + // Canonicalize username as lowercase + username = username.toLowerCase(); + // Update credentials with username provided by CAS for sake of // ${GUAC_USERNAME} token credentials.setUsername(username); @@ -196,8 +199,8 @@ public class TicketValidationService { } }); - CASAuthenticatedUser authenticatedUser = authenticatedUserProvider.get(); - authenticatedUser.init(username, credentials, tokens, effectiveGroups); + SSOAuthenticatedUser authenticatedUser = authenticatedUserProvider.get(); + authenticatedUser.init(username, credentials, effectiveGroups, tokens); return authenticatedUser; } diff --git a/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-openid/src/main/java/org/apache/guacamole/auth/openid/AuthenticationProviderService.java b/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-openid/src/main/java/org/apache/guacamole/auth/openid/AuthenticationProviderService.java index ba151dc48..08ad373dd 100644 --- a/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-openid/src/main/java/org/apache/guacamole/auth/openid/AuthenticationProviderService.java +++ b/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-openid/src/main/java/org/apache/guacamole/auth/openid/AuthenticationProviderService.java @@ -22,33 +22,27 @@ package org.apache.guacamole.auth.openid; import com.google.inject.Inject; import com.google.inject.Provider; import java.util.Arrays; +import java.util.Collections; import java.util.Set; import javax.servlet.http.HttpServletRequest; import org.apache.guacamole.auth.openid.conf.ConfigurationService; import org.apache.guacamole.auth.openid.form.TokenField; import org.apache.guacamole.auth.openid.token.NonceService; import org.apache.guacamole.auth.openid.token.TokenValidationService; -import org.apache.guacamole.auth.openid.user.AuthenticatedUser; import org.apache.guacamole.GuacamoleException; +import org.apache.guacamole.auth.sso.SSOAuthenticationProviderService; +import org.apache.guacamole.auth.sso.user.SSOAuthenticatedUser; import org.apache.guacamole.form.Field; import org.apache.guacamole.language.TranslatableMessage; import org.apache.guacamole.net.auth.Credentials; import org.apache.guacamole.net.auth.credentials.CredentialsInfo; import org.apache.guacamole.net.auth.credentials.GuacamoleInvalidCredentialsException; import org.jose4j.jwt.JwtClaims; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; /** - * Service providing convenience functions for the OpenID AuthenticationProvider - * implementation. + * Service that authenticates Guacamole users by processing OpenID tokens. */ -public class AuthenticationProviderService { - - /** - * Logger for this class. - */ - private final Logger logger = LoggerFactory.getLogger(AuthenticationProviderService.class); +public class AuthenticationProviderService implements SSOAuthenticationProviderService { /** * Service for retrieving OpenID configuration information. @@ -72,24 +66,10 @@ public class AuthenticationProviderService { * Provider for AuthenticatedUser objects. */ @Inject - private Provider authenticatedUserProvider; + private Provider authenticatedUserProvider; - /** - * 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 SSOAuthenticatedUser authenticateUser(Credentials credentials) throws GuacamoleException { String username = null; @@ -113,8 +93,8 @@ public class AuthenticationProviderService { if (username != null) { // Create corresponding authenticated user - AuthenticatedUser authenticatedUser = authenticatedUserProvider.get(); - authenticatedUser.init(username, credentials, groups); + SSOAuthenticatedUser authenticatedUser = authenticatedUserProvider.get(); + authenticatedUser.init(username, credentials, groups, Collections.emptyMap()); return authenticatedUser; } @@ -139,4 +119,9 @@ public class AuthenticationProviderService { } + @Override + public void shutdown() { + // Nothing to clean up + } + } diff --git a/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-openid/src/main/java/org/apache/guacamole/auth/openid/OpenIDAuthenticationProvider.java b/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-openid/src/main/java/org/apache/guacamole/auth/openid/OpenIDAuthenticationProvider.java index 04a372e55..32588d811 100644 --- a/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-openid/src/main/java/org/apache/guacamole/auth/openid/OpenIDAuthenticationProvider.java +++ b/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-openid/src/main/java/org/apache/guacamole/auth/openid/OpenIDAuthenticationProvider.java @@ -19,12 +19,7 @@ package org.apache.guacamole.auth.openid; -import com.google.inject.Guice; -import com.google.inject.Injector; -import org.apache.guacamole.GuacamoleException; -import org.apache.guacamole.net.auth.AbstractAuthenticationProvider; -import org.apache.guacamole.net.auth.AuthenticatedUser; -import org.apache.guacamole.net.auth.Credentials; +import org.apache.guacamole.auth.sso.SSOAuthenticationProvider; /** * Guacamole authentication backend which authenticates users using an @@ -32,29 +27,14 @@ import org.apache.guacamole.net.auth.Credentials; * provided - only authentication. Storage must be provided by some other * extension. */ -public class OpenIDAuthenticationProvider extends AbstractAuthenticationProvider { - - /** - * Injector which will manage the object graph of this authentication - * provider. - */ - private final Injector injector; +public class OpenIDAuthenticationProvider extends SSOAuthenticationProvider { /** * Creates a new OpenIDAuthenticationProvider that authenticates users * against an OpenID service. - * - * @throws GuacamoleException - * If a required property is missing, or an error occurs while parsing - * a property. */ - public OpenIDAuthenticationProvider() throws GuacamoleException { - - // Set up Guice injector. - injector = Guice.createInjector( - new OpenIDAuthenticationProviderModule(this) - ); - + public OpenIDAuthenticationProvider() { + super(AuthenticationProviderService.class, new OpenIDAuthenticationProviderModule()); } @Override @@ -62,14 +42,4 @@ public class OpenIDAuthenticationProvider extends AbstractAuthenticationProvider return "openid"; } - @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); - - } - } diff --git a/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-openid/src/main/java/org/apache/guacamole/auth/openid/OpenIDAuthenticationProviderModule.java b/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-openid/src/main/java/org/apache/guacamole/auth/openid/OpenIDAuthenticationProviderModule.java index 83e8c3777..dde4ef2a6 100644 --- a/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-openid/src/main/java/org/apache/guacamole/auth/openid/OpenIDAuthenticationProviderModule.java +++ b/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-openid/src/main/java/org/apache/guacamole/auth/openid/OpenIDAuthenticationProviderModule.java @@ -23,61 +23,17 @@ import com.google.inject.AbstractModule; import org.apache.guacamole.auth.openid.conf.ConfigurationService; import org.apache.guacamole.auth.openid.token.NonceService; import org.apache.guacamole.auth.openid.token.TokenValidationService; -import org.apache.guacamole.GuacamoleException; -import org.apache.guacamole.environment.Environment; -import org.apache.guacamole.environment.LocalEnvironment; -import org.apache.guacamole.net.auth.AuthenticationProvider; /** - * Guice module which configures openid-specific injections. + * Guice module which configures OpenID-specific injections. */ public class OpenIDAuthenticationProviderModule extends AbstractModule { - /** - * Guacamole server environment. - */ - private final Environment environment; - - /** - * A reference to the OpenIDAuthenticationProvider on behalf of which this - * module has configured injection. - */ - private final AuthenticationProvider authProvider; - - /** - * Creates a new OpenID authentication provider module which configures - * injection for the OpenIDAuthenticationProvider. - * - * @param authProvider - * The AuthenticationProvider for which injection is being configured. - * - * @throws GuacamoleException - * If an error occurs while retrieving the Guacamole server - * environment. - */ - public OpenIDAuthenticationProviderModule(AuthenticationProvider authProvider) - throws GuacamoleException { - - // 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 openid-specific services bind(ConfigurationService.class); bind(NonceService.class); bind(TokenValidationService.class); - } } diff --git a/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-openid/src/main/java/org/apache/guacamole/auth/openid/user/AuthenticatedUser.java b/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-openid/src/main/java/org/apache/guacamole/auth/openid/user/AuthenticatedUser.java deleted file mode 100644 index cfc998309..000000000 --- a/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-openid/src/main/java/org/apache/guacamole/auth/openid/user/AuthenticatedUser.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.apache.guacamole.auth.openid.user; - -import com.google.inject.Inject; -import java.util.Set; -import org.apache.guacamole.net.auth.AbstractAuthenticatedUser; -import org.apache.guacamole.net.auth.AuthenticationProvider; -import org.apache.guacamole.net.auth.Credentials; - -/** - * An openid-specific implementation of AuthenticatedUser, associating a - * username, a particular set of credentials and the groups with the - * OpenID authentication provider. - */ -public class AuthenticatedUser extends AbstractAuthenticatedUser { - - /** - * 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 groups of the user that was authenticated. - */ - private Set effectiveGroups; - - /** - * Initializes this AuthenticatedUser using the given username and - * credentials. - * - * @param username - * The username of the user that was authenticated. - * - * @param credentials - * The credentials provided when this user was authenticated. - * - * @param effectiveGroups - * The groups of the user that was authenticated. - */ - public void init(String username, Credentials credentials, Set effectiveGroups) { - this.credentials = credentials; - this.effectiveGroups = effectiveGroups; - setIdentifier(username); - } - - @Override - public AuthenticationProvider getAuthenticationProvider() { - return authProvider; - } - - @Override - public Credentials getCredentials() { - return credentials; - } - - @Override - public Set getEffectiveUserGroups() { - return effectiveGroups; - } -} diff --git a/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-saml/src/main/java/org/apache/guacamole/auth/saml/AuthenticationProviderService.java b/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-saml/src/main/java/org/apache/guacamole/auth/saml/AuthenticationProviderService.java index d09ae78ce..bb4f368ff 100644 --- a/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-saml/src/main/java/org/apache/guacamole/auth/saml/AuthenticationProviderService.java +++ b/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-saml/src/main/java/org/apache/guacamole/auth/saml/AuthenticationProviderService.java @@ -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(); + } } diff --git a/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-saml/src/main/java/org/apache/guacamole/auth/saml/SAMLAuthenticationProvider.java b/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-saml/src/main/java/org/apache/guacamole/auth/saml/SAMLAuthenticationProvider.java index 0f802aba0..4d1f0b9d8 100644 --- a/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-saml/src/main/java/org/apache/guacamole/auth/saml/SAMLAuthenticationProvider.java +++ b/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-saml/src/main/java/org/apache/guacamole/auth/saml/SAMLAuthenticationProvider.java @@ -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); } } diff --git a/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-saml/src/main/java/org/apache/guacamole/auth/saml/SAMLAuthenticationProviderModule.java b/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-saml/src/main/java/org/apache/guacamole/auth/saml/SAMLAuthenticationProviderModule.java index feb61d6f6..3c7300baa 100644 --- a/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-saml/src/main/java/org/apache/guacamole/auth/saml/SAMLAuthenticationProviderModule.java +++ b/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-saml/src/main/java/org/apache/guacamole/auth/saml/SAMLAuthenticationProviderModule.java @@ -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); - } } diff --git a/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-saml/src/main/java/org/apache/guacamole/auth/saml/user/SAMLAuthenticatedUser.java b/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-saml/src/main/java/org/apache/guacamole/auth/saml/user/SAMLAuthenticatedUser.java index 689937c0c..88adee66a 100644 --- a/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-saml/src/main/java/org/apache/guacamole/auth/saml/user/SAMLAuthenticatedUser.java +++ b/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-saml/src/main/java/org/apache/guacamole/auth/saml/user/SAMLAuthenticatedUser.java @@ -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 effectiveGroups; - - /** - * Tokens associated with the authenticated user. - */ - private Map 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 getTokens() { - return tokens; - } - - @Override - public AuthenticationProvider getAuthenticationProvider() { - return authProvider; - } - - @Override - public Credentials getCredentials() { - return credentials; - } - - @Override - public Set getEffectiveUserGroups() { - return effectiveGroups; - } - }