Add .gitignore and .ratignore files for various directories
Some checks failed
continuous-integration/drone/push Build is failing
Some checks failed
continuous-integration/drone/push Build is failing
This commit is contained in:
2
extensions/guacamole-auth-sso/modules/guacamole-auth-sso-base/.gitignore
vendored
Normal file
2
extensions/guacamole-auth-sso/modules/guacamole-auth-sso-base/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
target/
|
||||
*~
|
@@ -0,0 +1 @@
|
||||
src/main/resources/html/*.html
|
@@ -0,0 +1,61 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
|
||||
http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.apache.guacamole</groupId>
|
||||
<artifactId>guacamole-auth-sso-base</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<name>guacamole-auth-sso-base</name>
|
||||
<url>http://guacamole.apache.org/</url>
|
||||
|
||||
<parent>
|
||||
<groupId>org.apache.guacamole</groupId>
|
||||
<artifactId>guacamole-auth-sso</artifactId>
|
||||
<version>1.6.0</version>
|
||||
<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>
|
||||
|
||||
<!-- JAX-RS Annotations -->
|
||||
<dependency>
|
||||
<groupId>javax.ws.rs</groupId>
|
||||
<artifactId>jsr311-api</artifactId>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
</project>
|
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* 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 java.util.Iterator;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import org.apache.guacamole.net.auth.IdentifierGenerator;
|
||||
|
||||
/**
|
||||
* Service for generating and validating single-use random tokens (nonces).
|
||||
* Each generated nonce is at least 128 bits and case-insensitive.
|
||||
*/
|
||||
public class NonceService {
|
||||
|
||||
/**
|
||||
* Map of all generated nonces to their corresponding expiration timestamps.
|
||||
* This Map must be periodically swept of expired nonces to avoid growing
|
||||
* without bound.
|
||||
*/
|
||||
private final Map<String, Long> nonces = new ConcurrentHashMap<>();
|
||||
|
||||
/**
|
||||
* The timestamp of the last expired nonce sweep.
|
||||
*/
|
||||
private long lastSweep = System.currentTimeMillis();
|
||||
|
||||
/**
|
||||
* The minimum number of bits of entropy to include in each nonce.
|
||||
*/
|
||||
private static final int NONCE_BITS = 128;
|
||||
|
||||
/**
|
||||
* The minimum amount of time to wait between sweeping expired nonces from
|
||||
* the Map.
|
||||
*/
|
||||
private static final long SWEEP_INTERVAL = 60000;
|
||||
|
||||
/**
|
||||
* Iterates through the entire Map of generated nonces, removing any nonce
|
||||
* that has exceeded its expiration timestamp. If insufficient time has
|
||||
* elapsed since the last sweep, as dictated by SWEEP_INTERVAL, this
|
||||
* function has no effect.
|
||||
*/
|
||||
private void sweepExpiredNonces() {
|
||||
|
||||
// Do not sweep until enough time has elapsed since the last sweep
|
||||
long currentTime = System.currentTimeMillis();
|
||||
if (currentTime - lastSweep < SWEEP_INTERVAL)
|
||||
return;
|
||||
|
||||
// Record time of sweep
|
||||
lastSweep = currentTime;
|
||||
|
||||
// For each stored nonce
|
||||
Iterator<Map.Entry<String, Long>> entries = nonces.entrySet().iterator();
|
||||
while (entries.hasNext()) {
|
||||
|
||||
// Remove all entries which have expired
|
||||
Map.Entry<String, Long> current = entries.next();
|
||||
if (current.getValue() <= System.currentTimeMillis())
|
||||
entries.remove();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a cryptographically-secure nonce value. The nonce is intended
|
||||
* to be used to prevent replay attacks.
|
||||
*
|
||||
* @param maxAge
|
||||
* The maximum amount of time that the generated nonce should remain
|
||||
* valid, in milliseconds.
|
||||
*
|
||||
* @return
|
||||
* A cryptographically-secure nonce value. Generated nonces are at
|
||||
* least 128-bit and are case-insensitive.
|
||||
*/
|
||||
public String generate(long maxAge) {
|
||||
|
||||
// Sweep expired nonces if enough time has passed
|
||||
sweepExpiredNonces();
|
||||
|
||||
// Generate and store nonce, along with expiration timestamp
|
||||
String nonce = IdentifierGenerator.generateIdentifier(NONCE_BITS, false);
|
||||
nonces.put(nonce, System.currentTimeMillis() + maxAge);
|
||||
return nonce;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the give nonce value is valid. A nonce is valid if and
|
||||
* only if it was generated by this instance of the NonceService. Testing
|
||||
* nonce validity through this function immediately and permanently
|
||||
* invalidates that nonce.
|
||||
*
|
||||
* @param nonce
|
||||
* The nonce value to test. This value may be null, which will be
|
||||
* considered an invalid nonce. Comparisons are case-insensitive.
|
||||
*
|
||||
* @return
|
||||
* true if the provided nonce is valid, false otherwise.
|
||||
*/
|
||||
public boolean isValid(String nonce) {
|
||||
|
||||
// All null nonces are invalid.
|
||||
if (nonce == null)
|
||||
return false;
|
||||
|
||||
// Remove nonce, verifying whether it was present at all
|
||||
Long expires = nonces.remove(nonce.toLowerCase(Locale.US));
|
||||
if (expires == null)
|
||||
return false;
|
||||
|
||||
// Nonce is only valid if it hasn't expired
|
||||
return expires > System.currentTimeMillis();
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* 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.GuacamoleClientException;
|
||||
import org.apache.guacamole.GuacamoleException;
|
||||
import org.apache.guacamole.GuacamoleSecurityException;
|
||||
import org.apache.guacamole.net.auth.Credentials;
|
||||
import org.apache.guacamole.net.auth.credentials.GuacamoleInsufficientCredentialsException;
|
||||
import org.apache.guacamole.net.event.AuthenticationFailureEvent;
|
||||
import org.apache.guacamole.net.event.AuthenticationRequestReceivedEvent;
|
||||
import org.apache.guacamole.net.event.CredentialEvent;
|
||||
import org.apache.guacamole.net.event.listener.Listener;
|
||||
|
||||
/**
|
||||
* A Listener that will reactivate or invalidate SSO auth sessions depending on
|
||||
* overall auth success or failure.
|
||||
*/
|
||||
public abstract class SSOAuthenticationEventListener implements Listener {
|
||||
|
||||
@Override
|
||||
public void handleEvent(Object event) throws GuacamoleException {
|
||||
|
||||
// If the authentication attempt is incomplete or credentials cannot be
|
||||
// extracted, there's nothing to do
|
||||
if (event instanceof AuthenticationRequestReceivedEvent
|
||||
|| !(event instanceof CredentialEvent))
|
||||
return;
|
||||
|
||||
// Look for a session identifier associated with these credentials
|
||||
String sessionIdentifier = getSessionIdentifier(
|
||||
((CredentialEvent) event).getCredentials());
|
||||
|
||||
// If no session is associated with these credentials, there's
|
||||
// nothing to do
|
||||
if (sessionIdentifier == null)
|
||||
return;
|
||||
|
||||
// If the SSO auth succeeded, but other auth providers failed to
|
||||
// authenticate the user associated with the credentials in this
|
||||
// failure event, they may wish to make another login attempt. To
|
||||
// avoid an infinite login attempt loop, re-enable the session
|
||||
// associated with these credentials, allowing the auth attempt to be
|
||||
// resumed without requiring another round trip to the SSO service.
|
||||
if (event instanceof AuthenticationFailureEvent) {
|
||||
Throwable failure = ((AuthenticationFailureEvent) event).getFailure();
|
||||
|
||||
// If and only if the failure was associated with missing or
|
||||
// credentials, or a non-security related request issue,
|
||||
// reactivate the session
|
||||
if (failure instanceof GuacamoleInsufficientCredentialsException
|
||||
|| ((failure instanceof GuacamoleClientException)
|
||||
&& !(failure instanceof GuacamoleSecurityException))) {
|
||||
|
||||
reactivateSession(sessionIdentifier);
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Invalidate the session in all other cases
|
||||
invalidateSession(sessionIdentifier);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the session identifier associated with the provided credentials,
|
||||
* if any. If no session is associated with the credentials, null will
|
||||
* be returned.
|
||||
*
|
||||
* @param credentials
|
||||
* The credentials assoociated with the deferred SSO authentication
|
||||
* session to reactivate.
|
||||
*
|
||||
* @return
|
||||
* The session identifier associated with the provided credentials,
|
||||
* or null if no session is found.
|
||||
*/
|
||||
protected abstract String getSessionIdentifier(Credentials credentials);
|
||||
|
||||
/**
|
||||
* Reactivate the session identified by the provided identifier, if any.
|
||||
*
|
||||
* @param sessionIdentifier
|
||||
* The identifier of the session to reactivate.
|
||||
*/
|
||||
protected abstract void reactivateSession(String sessionIdentifier);
|
||||
|
||||
/**
|
||||
* Invalidate the session identified by the provided identifier, if any.
|
||||
*
|
||||
* @param sessionIdentifier
|
||||
* The identifier of the session to invalidate.
|
||||
*/
|
||||
protected abstract void invalidateSession(String sessionIdentifier);
|
||||
|
||||
}
|
@@ -0,0 +1,179 @@
|
||||
/*
|
||||
* 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 com.google.inject.binder.LinkedBindingBuilder;
|
||||
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 ssoResource
|
||||
* The SSOResource that should be used to manually redirect the user to
|
||||
* the IdP, as well as to provide any implementation-specific REST
|
||||
* endpoints.
|
||||
*
|
||||
* @param modules
|
||||
* Any additional modules that should be used when creating the Guice
|
||||
* injector.
|
||||
*/
|
||||
public SSOAuthenticationProvider(
|
||||
Class<? extends SSOAuthenticationProviderService> authService,
|
||||
Class<? extends SSOResource> ssoResource,
|
||||
Module... modules) {
|
||||
this(authService, ssoResource, 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 ssoResource
|
||||
* The SSOResource that should be used to manually redirect the user to
|
||||
* the IdP, as well as to provide any implementation-specific REST
|
||||
* endpoints.
|
||||
*
|
||||
* @param modules
|
||||
* Any additional modules that should be used when creating the Guice
|
||||
* injector.
|
||||
*/
|
||||
public SSOAuthenticationProvider(
|
||||
Class<? extends SSOAuthenticationProviderService> authService,
|
||||
Class<? extends SSOResource> ssoResource,
|
||||
Iterable<? extends Module> modules) {
|
||||
injector = Guice.createInjector(Iterables.concat(Collections.singletonList(new AbstractModule() {
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
|
||||
bind(AuthenticationProvider.class).toInstance(SSOAuthenticationProvider.this);
|
||||
bind(SSOAuthenticationProviderService.class).to(authService);
|
||||
|
||||
// Bind custom SSOResource implementation if different from
|
||||
// core implementation (explicitly binding SSOResource as
|
||||
// SSOResource results in a runtime error from Guice otherwise)
|
||||
LinkedBindingBuilder<SSOResource> resourceBinding = bind(SSOResource.class);
|
||||
if (ssoResource != SSOResource.class)
|
||||
resourceBinding.to(ssoResource);
|
||||
|
||||
}
|
||||
|
||||
}), 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 SSOResource getResource() {
|
||||
return getInjector().getInstance(SSOResource.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shutdown() {
|
||||
injector.getInstance(SSOAuthenticationProviderService.class).shutdown();
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* 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 java.net.URI;
|
||||
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;
|
||||
|
||||
/**
|
||||
* Returns the full URI of the login endpoint to which a user must be
|
||||
* redirected in order to authenticate with the SSO identity provider.
|
||||
*
|
||||
* @return
|
||||
* The full URI of the SSO login endpoint.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If configuration information required for generating the login URI
|
||||
* cannot be read.
|
||||
*/
|
||||
URI getLoginURI() 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();
|
||||
|
||||
}
|
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* 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.inject.Inject;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.Path;
|
||||
import org.apache.guacamole.GuacamoleException;
|
||||
|
||||
/**
|
||||
* REST API resource that provides allows the user to be manually redirected to
|
||||
* the applicable identity provider. Implementations may also provide
|
||||
* additional resources and endpoints beneath this resource as needed.
|
||||
*/
|
||||
public class SSOResource {
|
||||
|
||||
/**
|
||||
* Service for authenticating users using CAS.
|
||||
*/
|
||||
@Inject
|
||||
private SSOAuthenticationProviderService authService;
|
||||
|
||||
/**
|
||||
* Redirects the user to the relevant identity provider. If the SSO
|
||||
* extension defining this resource is not the primary extension, and thus
|
||||
* the user will not be automatically redirected to the IdP, this endpoint
|
||||
* allows that redirect to occur manually upon a link/button click.
|
||||
*
|
||||
* @return
|
||||
* An HTTP Response that will redirect the user to the IdP.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If an error occurs preventing the redirect from being created.
|
||||
*/
|
||||
@GET
|
||||
@Path("login")
|
||||
public Response redirectToIdentityProvider() throws GuacamoleException {
|
||||
return Response.seeOther(authService.getLoginURI()).build();
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* 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. The contents of the
|
||||
* given credentials are automatically updated to match the provided
|
||||
* username. 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. These
|
||||
* credentials will be updated to match the provided username.
|
||||
*
|
||||
* @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);
|
||||
|
||||
// Update credentials with username provided via SSO for sake of
|
||||
// ${GUAC_USERNAME} token
|
||||
credentials.setUsername(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;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,5 @@
|
||||
<meta name="after" content=".login-ui .login-dialog-middle:not(:has(~ .sso-providers))">
|
||||
<div class="sso-providers">
|
||||
{{ 'LOGIN.SECTION_HEADER_SSO_OPTIONS' | translate }}
|
||||
<ul class="sso-provider-list"></ul>
|
||||
</div>
|
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
.login-ui .sso-providers {
|
||||
|
||||
padding: 0.25em 0.5em;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
|
||||
}
|
||||
|
||||
.sso-providers ul {
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.sso-providers ul, .sso-providers li {
|
||||
display: inline-block;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.sso-providers li::before {
|
||||
content: ' / ';
|
||||
}
|
||||
|
||||
.sso-providers li:first-child::before {
|
||||
display: none;
|
||||
}
|
@@ -0,0 +1,15 @@
|
||||
{
|
||||
|
||||
"DATA_SOURCE_CAS" : {
|
||||
"NAME" : "Backend d'inici de sessió unificat (SSO) CAS"
|
||||
},
|
||||
|
||||
"DATA_SOURCE_SAML" : {
|
||||
"NAME" : "Extensión de autenticación SAML"
|
||||
},
|
||||
|
||||
"LOGIN" : {
|
||||
"INFO_IDP_REDIRECT_PENDING" : "Espereu, redirigint al proveïdor d'identitat ..."
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,7 @@
|
||||
{
|
||||
|
||||
"LOGIN" : {
|
||||
"INFO_IDP_REDIRECT_PENDING" : "Bitte warten, Sie werden zum Identitätsprovider weitergeleitet..."
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,32 @@
|
||||
{
|
||||
|
||||
"DATA_SOURCE_CAS" : {
|
||||
"NAME" : "CAS SSO Backend"
|
||||
},
|
||||
|
||||
"DATA_SOURCE_OPENID" : {
|
||||
"NAME" : "OpenID SSO Backend"
|
||||
},
|
||||
|
||||
"DATA_SOURCE_SAML" : {
|
||||
"NAME" : "SAML SSO Backend"
|
||||
},
|
||||
|
||||
"DATA_SOURCE_SSL" : {
|
||||
"NAME" : "SSL/TLS SSO Backend"
|
||||
},
|
||||
|
||||
"LOGIN" : {
|
||||
"FIELD_HEADER_ID_TOKEN" : "",
|
||||
"FIELD_HEADER_STATE" : "",
|
||||
"FIELD_HEADER_TICKET" : "",
|
||||
"INFO_IDP_REDIRECT_PENDING" : "Please wait, redirecting to identity provider...",
|
||||
"INFO_REDIRECT_PENDING" : "Please wait while you are redirected...",
|
||||
"NAME_IDP_CAS" : "CAS",
|
||||
"NAME_IDP_OPENID" : "OpenID",
|
||||
"NAME_IDP_SAML" : "SAML",
|
||||
"NAME_IDP_SSL" : "Certificate / Smart Card",
|
||||
"SECTION_HEADER_SSO_OPTIONS" : "Sign in with:"
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,29 @@
|
||||
{
|
||||
|
||||
"DATA_SOURCE_CAS" : {
|
||||
"NAME" : "Backend CAS SSO"
|
||||
},
|
||||
|
||||
"DATA_SOURCE_OPENID" : {
|
||||
"NAME" : "Backend OpenID SSO"
|
||||
},
|
||||
|
||||
"DATA_SOURCE_SAML" : {
|
||||
"NAME" : "Backend SAML SSO"
|
||||
},
|
||||
|
||||
"DATA_SOURCE_SSL" : {
|
||||
"NAME" : "Backend SSL/TLS SSO"
|
||||
},
|
||||
|
||||
"LOGIN" : {
|
||||
"INFO_IDP_REDIRECT_PENDING" : "Veuillez patienter, redirection vers le fournisseur d'identité...",
|
||||
"INFO_REDIRECT_PENDING" : "Veuillez patienter pendant que vous êtes redirigé...",
|
||||
"NAME_IDP_CAS" : "CAS",
|
||||
"NAME_IDP_OPENID" : "OpenID",
|
||||
"NAME_IDP_SAML" : "SAML",
|
||||
"NAME_IDP_SSL" : "Certificat / Carte à puce",
|
||||
"SECTION_HEADER_SSO_OPTIONS" : "Connectez-vous avec:"
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
{
|
||||
|
||||
"LOGIN" : {
|
||||
"INFO_IDP_REDIRECT_PENDING" : "Attendi, reindirizzamento al provider di identità...",
|
||||
"NAME_IDP_CAS" : "CAS",
|
||||
"NAME_IDP_OPENID" : "OpenID",
|
||||
"NAME_IDP_SAML" : "SAML",
|
||||
"SECTION_HEADER_SSO_OPTIONS" : "Accedi con:"
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,7 @@
|
||||
{
|
||||
|
||||
"LOGIN" : {
|
||||
"INFO_IDP_REDIRECT_PENDING" : "IDプロバイダへリダイレクトしています。"
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
{
|
||||
|
||||
"DATA_SOURCE_SAML" : {
|
||||
"NAME" : "SAML 인증 확장 프로그램"
|
||||
},
|
||||
|
||||
"LOGIN" : {
|
||||
"INFO_IDP_REDIRECT_PENDING" : "잠시만 기다려주십시오. ID 제공자로 리디렉션 중..."
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,26 @@
|
||||
{
|
||||
|
||||
"DATA_SOURCE_CAS" : {
|
||||
"NAME" : "CAS SSO Backend"
|
||||
},
|
||||
|
||||
"DATA_SOURCE_OPENID" : {
|
||||
"NAME" : "OpenID SSO Backend"
|
||||
},
|
||||
|
||||
"DATA_SOURCE_SAML" : {
|
||||
"NAME" : "SAML SSO Backend"
|
||||
},
|
||||
|
||||
"LOGIN" : {
|
||||
"FIELD_HEADER_ID_TOKEN" : "",
|
||||
"FIELD_HEADER_STATE" : "",
|
||||
"FIELD_HEADER_TICKET" : "",
|
||||
"INFO_IDP_REDIRECT_PENDING" : "Proszę czekać, przekierowanie do dostawcy tożsamości...",
|
||||
"NAME_IDP_CAS" : "CAS",
|
||||
"NAME_IDP_OPENID" : "OpenID",
|
||||
"NAME_IDP_SAML" : "SAML",
|
||||
"SECTION_HEADER_SSO_OPTIONS" : "Zaloguj z:"
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,7 @@
|
||||
{
|
||||
|
||||
"LOGIN" : {
|
||||
"INFO_IDP_REDIRECT_PENDING" : "Por favor aguarde, redirecionando ao provedor de indentidade..."
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,15 @@
|
||||
{
|
||||
|
||||
"DATA_SOURCE_CAS" : {
|
||||
"NAME" : "Бэкенд CAS SSO"
|
||||
},
|
||||
|
||||
"DATA_SOURCE_OPENID" : {
|
||||
"NAME" : "Бэкенд OpenID SSO"
|
||||
},
|
||||
|
||||
"LOGIN" : {
|
||||
"INFO_IDP_REDIRECT_PENDING" : "Пожалуйста, подождите. Переадресую на страницу аутентификации..."
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,15 @@
|
||||
{
|
||||
|
||||
"DATA_SOURCE_CAS" : {
|
||||
"NAME" : "CAS SSO后端"
|
||||
},
|
||||
|
||||
"DATA_SOURCE_OPENID" : {
|
||||
"NAME" : "OpenID SSO后端"
|
||||
},
|
||||
|
||||
"LOGIN" : {
|
||||
"INFO_IDP_REDIRECT_PENDING" : "请稍候,正在重定向到身份提供者..."
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user