diff --git a/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-saml/pom.xml b/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-saml/pom.xml
index 67515beab..f2d5a9e0c 100644
--- a/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-saml/pom.xml
+++ b/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-saml/pom.xml
@@ -36,6 +36,52 @@
../../
+
+
+
+
+
+ com.github.buckelieg
+ minify-maven-plugin
+
+
+ default-cli
+
+ UTF-8
+
+ ${basedir}/src/main/resources
+ ${project.build.directory}/classes
+
+ /
+ /
+ saml.js
+
+
+ license.txt
+
+
+
+ **/*.js
+
+ CLOSURE
+
+
+
+ OFF
+ OFF
+
+
+
+
+ minify
+
+
+
+
+
+
+
+
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 ace19d55e..f026916d4 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
@@ -24,9 +24,11 @@ import com.google.inject.Provider;
import com.google.inject.Singleton;
import java.net.URI;
import java.util.Arrays;
+import javax.ws.rs.core.UriBuilder;
import org.apache.guacamole.auth.saml.user.SAMLAuthenticatedUser;
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.auth.saml.acs.SAMLAuthenticationSessionManager;
import org.apache.guacamole.auth.saml.acs.SAMLService;
import org.apache.guacamole.auth.sso.SSOAuthenticationProviderService;
@@ -68,6 +70,12 @@ public class AuthenticationProviderService implements SSOAuthenticationProviderS
@Inject
private SAMLService saml;
+ /**
+ * Service for retrieving SAML configuration information.
+ */
+ @Inject
+ private ConfigurationService confService;
+
/**
* Return the value of the session identifier associated with the given
* credentials, or null if no session identifier is found in the
@@ -117,9 +125,25 @@ public class AuthenticationProviderService implements SSOAuthenticationProviderS
return saml.createRequest();
}
+ @Override
+ public URI getLogoutURI(String idToken) throws GuacamoleException {
+
+ // If no logout endpoint is configured, return null
+ URI logoutEndpoint = confService.getLogoutEndpoint();
+ if (logoutEndpoint == null)
+ return null;
+
+ // Build the logout URI with post-logout redirect
+ UriBuilder logoutUriBuilder = UriBuilder.fromUri(logoutEndpoint);
+ logoutUriBuilder.queryParam("RelayState",
+ confService.getPostLogoutRedirectURI());
+
+ return logoutUriBuilder.build();
+ }
+
@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/conf/ConfigurationService.java b/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-saml/src/main/java/org/apache/guacamole/auth/saml/conf/ConfigurationService.java
index 47ead8820..da10043ee 100644
--- a/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-saml/src/main/java/org/apache/guacamole/auth/saml/conf/ConfigurationService.java
+++ b/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-saml/src/main/java/org/apache/guacamole/auth/saml/conf/ConfigurationService.java
@@ -190,6 +190,30 @@ public class ConfigurationService {
};
+ /**
+ * The logout endpoint (URI) of the SAML IdP. When configured, users will
+ * be redirected to this endpoint when they log out of Guacamole.
+ */
+ private static final URIGuacamoleProperty SAML_LOGOUT_ENDPOINT =
+ new URIGuacamoleProperty() {
+
+ @Override
+ public String getName() { return "saml-logout-endpoint"; }
+
+ };
+
+ /**
+ * The URI to redirect to after logout is complete. Defaults to the
+ * callback URL if not specified.
+ */
+ private static final URIGuacamoleProperty SAML_POST_LOGOUT_REDIRECT_URI =
+ new URIGuacamoleProperty() {
+
+ @Override
+ public String getName() { return "saml-post-logout-redirect-uri"; }
+
+ };
+
/**
* The Guacamole server environment.
*/
@@ -390,6 +414,37 @@ public class ConfigurationService {
return environment.getProperty(SAML_PRIVATE_KEY_PATH);
}
+ /**
+ * Returns the logout endpoint (URI) of the SAML IdP. If not configured,
+ * null will be returned and logout will only end the Guacamole session.
+ *
+ * @return
+ * The logout endpoint of the SAML IdP, or null if not configured.
+ *
+ * @throws GuacamoleException
+ * If guacamole.properties cannot be parsed.
+ */
+ public URI getLogoutEndpoint() throws GuacamoleException {
+ return environment.getProperty(SAML_LOGOUT_ENDPOINT);
+ }
+
+ /**
+ * Returns the URI to redirect to after logout is complete. If not
+ * configured, the callback URL will be used.
+ *
+ * @return
+ * The post-logout redirect URI.
+ *
+ * @throws GuacamoleException
+ * If guacamole.properties cannot be parsed.
+ */
+ public URI getPostLogoutRedirectURI() throws GuacamoleException {
+ URI postLogoutUri = environment.getProperty(SAML_POST_LOGOUT_REDIRECT_URI);
+ if (postLogoutUri != null)
+ return postLogoutUri;
+ return getCallbackUrl();
+ }
+
/**
* Returns the contents of a small file, such as a private key or certificate into
* a String. If the file does not exist, or cannot be read for any reason, an exception
diff --git a/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-saml/src/main/resource-templates/guac-manifest.json b/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-saml/src/main/resource-templates/guac-manifest.json
index f19c11593..64db565cb 100644
--- a/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-saml/src/main/resource-templates/guac-manifest.json
+++ b/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-saml/src/main/resource-templates/guac-manifest.json
@@ -17,6 +17,10 @@
"styles/sso-providers.css"
],
+ "js" : [
+ "saml.min.js"
+ ],
+
"html" : [
"html/sso-providers.html",
"html/sso-provider-saml.html"
diff --git a/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-saml/src/main/resources/samlModule.js b/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-saml/src/main/resources/samlModule.js
new file mode 100644
index 000000000..b3ee9869e
--- /dev/null
+++ b/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-saml/src/main/resources/samlModule.js
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+
+/**
+ * The module for code implementing SSO using SAML.
+ */
+angular.module('guacSsoSaml', []);
+
+/**
+ * Redirect to the SSO logout endpoint when the user logs out, allowing
+ * Single Logout to occur if configured.
+ */
+angular.module('guacSsoSaml').run(['$rootScope', '$window',
+ function guacSsoSamlLogout($rootScope, $window) {
+
+ // Redirect to SSO logout endpoint when user logs out
+ $rootScope.$on('guacLogout', function handleLogout() {
+ $window.location.href = 'api/ext/saml/logout';
+ });
+
+}]);
+
+// Ensure the guacSsoSaml module is loaded along with the rest of the app
+angular.module('index').requires.push('guacSsoSaml');