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

@@ -36,4 +36,20 @@
<relativePath>../../</relativePath>
</parent>
<dependencies>
<!-- Guacamole Extension API -->
<dependency>
<groupId>org.apache.guacamole</groupId>
<artifactId>guacamole-ext</artifactId>
</dependency>
<!-- Guice -->
<dependency>
<groupId>com.google.inject</groupId>
<artifactId>guice</artifactId>
</dependency>
</dependencies>
</project>

View File

@@ -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<? extends SSOAuthenticationProviderService> 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<? extends SSOAuthenticationProviderService> authService,
Iterable<? extends Module> 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();
}
}

View File

@@ -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();
}

View File

@@ -0,0 +1,116 @@
/*
* 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.user;
import com.google.inject.Inject;
import java.util.Collections;
import java.util.Map;
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 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 SSOAuthenticatedUser 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 that this user belongs to.
*/
private Set<String> effectiveGroups;
/**
* Parameter tokens to be automatically injected for any connections used
* by this user.
*/
private Map<String, String> 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 by this user.
*/
public void init(String username, Credentials credentials,
Set<String> effectiveGroups, Map<String, String> tokens) {
this.credentials = credentials;
this.effectiveGroups = Collections.unmodifiableSet(effectiveGroups);
this.tokens = Collections.unmodifiableMap(tokens);
setIdentifier(username);
}
/**
* 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 of the parameter token name/value pairs that should be
* automatically injected into connections used by this user.
*/
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;
}
}