mirror of
https://github.com/gyurix1968/guacamole-client.git
synced 2025-09-06 13:17:41 +00:00
Merge 1.4.0 changes back to master.
This commit is contained in:
@@ -1,53 +0,0 @@
|
|||||||
<?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.
|
|
||||||
-->
|
|
||||||
<assembly
|
|
||||||
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
|
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
||||||
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
|
|
||||||
|
|
||||||
<id>dist</id>
|
|
||||||
<baseDirectory>${project.artifactId}-${project.version}</baseDirectory>
|
|
||||||
|
|
||||||
<!-- Output tar.gz -->
|
|
||||||
<formats>
|
|
||||||
<format>tar.gz</format>
|
|
||||||
</formats>
|
|
||||||
|
|
||||||
<!-- Include licenses and extension .jar -->
|
|
||||||
<fileSets>
|
|
||||||
|
|
||||||
<!-- Include licenses -->
|
|
||||||
<fileSet>
|
|
||||||
<outputDirectory></outputDirectory>
|
|
||||||
<directory>target/licenses</directory>
|
|
||||||
</fileSet>
|
|
||||||
|
|
||||||
<!-- Include extension .jar -->
|
|
||||||
<fileSet>
|
|
||||||
<directory>target</directory>
|
|
||||||
<outputDirectory></outputDirectory>
|
|
||||||
<includes>
|
|
||||||
<include>*.jar</include>
|
|
||||||
</includes>
|
|
||||||
</fileSet>
|
|
||||||
|
|
||||||
</fileSets>
|
|
||||||
|
|
||||||
</assembly>
|
|
@@ -1,90 +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.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;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Guacamole authentication backend which authenticates users using an
|
|
||||||
* arbitrary external system implementing CAS. No storage for connections is
|
|
||||||
* 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;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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)
|
|
||||||
);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@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());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,81 +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.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.ticket.TicketValidationService;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Guice module which configures CAS-specific injections.
|
|
||||||
*/
|
|
||||||
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);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,78 +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.cas.form;
|
|
||||||
|
|
||||||
import java.net.URI;
|
|
||||||
import javax.ws.rs.core.UriBuilder;
|
|
||||||
import org.apache.guacamole.form.RedirectField;
|
|
||||||
import org.apache.guacamole.language.TranslatableMessage;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Field definition which represents the ticket returned by an CAS service.
|
|
||||||
* This is processed transparently - the user is redirected to CAS, authenticates
|
|
||||||
* and then is returned to Guacamole where the ticket field is
|
|
||||||
* processed.
|
|
||||||
*/
|
|
||||||
public class CASTicketField extends RedirectField {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The parameter that will be present upon successful CAS authentication.
|
|
||||||
*/
|
|
||||||
public static final String PARAMETER_NAME = "ticket";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The standard URI name for the CAS login resource.
|
|
||||||
*/
|
|
||||||
private static final String CAS_LOGIN_URI = "login";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new CAS "ticket" field which links to the given CAS
|
|
||||||
* service using the provided client ID. Successful authentication at the
|
|
||||||
* CAS service will result in the client being redirected to the specified
|
|
||||||
* redirect URI. The CAS ticket will be embedded in the fragment (the part
|
|
||||||
* following the hash symbol) of that URI, which the JavaScript side of
|
|
||||||
* this extension will move to the query parameters.
|
|
||||||
*
|
|
||||||
* @param authorizationEndpoint
|
|
||||||
* The full URL of the endpoint accepting CAS authentication
|
|
||||||
* requests.
|
|
||||||
*
|
|
||||||
* @param redirectURI
|
|
||||||
* The URI that the CAS service should redirect to upon successful
|
|
||||||
* authentication.
|
|
||||||
*
|
|
||||||
* @param redirectMessage
|
|
||||||
* The message that will be displayed for the user while the redirect
|
|
||||||
* is processed. This will be processed through Guacamole's translation
|
|
||||||
* system.
|
|
||||||
*/
|
|
||||||
public CASTicketField(URI authorizationEndpoint, URI redirectURI,
|
|
||||||
TranslatableMessage redirectMessage) {
|
|
||||||
|
|
||||||
super(PARAMETER_NAME, UriBuilder.fromUri(authorizationEndpoint)
|
|
||||||
.path(CAS_LOGIN_URI)
|
|
||||||
.queryParam("service", redirectURI)
|
|
||||||
.build(),
|
|
||||||
redirectMessage);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,11 +0,0 @@
|
|||||||
{
|
|
||||||
|
|
||||||
"DATA_SOURCE_CAS" : {
|
|
||||||
"NAME" : "Backend d'inici de sessió unificat (SSO) CAS"
|
|
||||||
},
|
|
||||||
|
|
||||||
"LOGIN" : {
|
|
||||||
"INFO_CAS_REDIRECT_PENDING" : "Espereu, redireccionant a l'autenticació CAS ..."
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,12 +0,0 @@
|
|||||||
{
|
|
||||||
|
|
||||||
"DATA_SOURCE_CAS" : {
|
|
||||||
"NAME" : "CAS SSO Backend"
|
|
||||||
},
|
|
||||||
|
|
||||||
"LOGIN" : {
|
|
||||||
"FIELD_HEADER_TICKET" : "",
|
|
||||||
"INFO_CAS_REDIRECT_PENDING" : "Bitte warten, Sie werden zur CAS-Authentifizierung weitergeleitet..."
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,12 +0,0 @@
|
|||||||
{
|
|
||||||
|
|
||||||
"DATA_SOURCE_CAS" : {
|
|
||||||
"NAME" : "CAS SSO Backend"
|
|
||||||
},
|
|
||||||
|
|
||||||
"LOGIN" : {
|
|
||||||
"FIELD_HEADER_TICKET" : "",
|
|
||||||
"INFO_CAS_REDIRECT_PENDING" : "Please wait, redirecting to CAS authentication..."
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,12 +0,0 @@
|
|||||||
{
|
|
||||||
|
|
||||||
"DATA_SOURCE_CAS" : {
|
|
||||||
"NAME" : "CAS SSO Backend"
|
|
||||||
},
|
|
||||||
|
|
||||||
"LOGIN" : {
|
|
||||||
"FIELD_HEADER_TICKET" : "",
|
|
||||||
"INFO_CAS_REDIRECT_PENDING" : "Veuillez patienter, redirection vers l'authentification CAS..."
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,7 +0,0 @@
|
|||||||
{
|
|
||||||
|
|
||||||
"LOGIN" : {
|
|
||||||
"INFO_CAS_REDIRECT_PENDING" : "CAS認証にリダイレクトしています。"
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,7 +0,0 @@
|
|||||||
{
|
|
||||||
|
|
||||||
"LOGIN" : {
|
|
||||||
"INFO_CAS_REDIRECT_PENDING" : "기다려주십시오. CAS 인증으로 리디렉션 중..."
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,12 +0,0 @@
|
|||||||
{
|
|
||||||
|
|
||||||
"DATA_SOURCE_CAS" : {
|
|
||||||
"NAME" : "CAS SSO Backend"
|
|
||||||
},
|
|
||||||
|
|
||||||
"LOGIN" : {
|
|
||||||
"FIELD_HEADER_TICKET" : "",
|
|
||||||
"INFO_CAS_REDIRECT_PENDING" : "Por favor aguarde, redirecionando para autenticação CAS..."
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,11 +0,0 @@
|
|||||||
{
|
|
||||||
|
|
||||||
"DATA_SOURCE_CAS" : {
|
|
||||||
"NAME" : "Бэкенд CAS SSO"
|
|
||||||
},
|
|
||||||
|
|
||||||
"LOGIN" : {
|
|
||||||
"INFO_CAS_REDIRECT_PENDING" : "Пожалуйста, подождите. Переадресую на страницу аутентификации CAS..."
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,12 +0,0 @@
|
|||||||
{
|
|
||||||
|
|
||||||
"DATA_SOURCE_CAS" : {
|
|
||||||
"NAME" : "CAS SSO后端"
|
|
||||||
},
|
|
||||||
|
|
||||||
"LOGIN" : {
|
|
||||||
"FIELD_HEADER_TICKET" : "",
|
|
||||||
"INFO_CAS_REDIRECT_PENDING" : "请稍候,正在重定向到CAS验证..."
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,53 +0,0 @@
|
|||||||
<?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.
|
|
||||||
-->
|
|
||||||
<assembly
|
|
||||||
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
|
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
||||||
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
|
|
||||||
|
|
||||||
<id>dist</id>
|
|
||||||
<baseDirectory>${project.artifactId}-${project.version}</baseDirectory>
|
|
||||||
|
|
||||||
<!-- Output tar.gz -->
|
|
||||||
<formats>
|
|
||||||
<format>tar.gz</format>
|
|
||||||
</formats>
|
|
||||||
|
|
||||||
<!-- Include licenses and extension .jar -->
|
|
||||||
<fileSets>
|
|
||||||
|
|
||||||
<!-- Include licenses -->
|
|
||||||
<fileSet>
|
|
||||||
<outputDirectory></outputDirectory>
|
|
||||||
<directory>target/licenses</directory>
|
|
||||||
</fileSet>
|
|
||||||
|
|
||||||
<!-- Include extension .jar -->
|
|
||||||
<fileSet>
|
|
||||||
<directory>target</directory>
|
|
||||||
<outputDirectory></outputDirectory>
|
|
||||||
<includes>
|
|
||||||
<include>*.jar</include>
|
|
||||||
</includes>
|
|
||||||
</fileSet>
|
|
||||||
|
|
||||||
</fileSets>
|
|
||||||
|
|
||||||
</assembly>
|
|
@@ -1,83 +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;
|
|
||||||
|
|
||||||
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.
|
|
||||||
*/
|
|
||||||
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);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,87 +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.form;
|
|
||||||
|
|
||||||
import java.net.URI;
|
|
||||||
import javax.ws.rs.core.UriBuilder;
|
|
||||||
import org.apache.guacamole.form.RedirectField;
|
|
||||||
import org.apache.guacamole.language.TranslatableMessage;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Field definition which represents the token returned by an OpenID Connect
|
|
||||||
* service.
|
|
||||||
*/
|
|
||||||
public class TokenField extends RedirectField {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The standard HTTP parameter which will be included within the URL by all
|
|
||||||
* OpenID services upon successful authentication and redirect.
|
|
||||||
*/
|
|
||||||
public static final String PARAMETER_NAME = "id_token";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new field which requests authentication via OpenID connect.
|
|
||||||
* Successful authentication at the OpenID Connect service will result in
|
|
||||||
* the client being redirected to the specified redirect URI. The OpenID
|
|
||||||
* token will be embedded in the fragment (the part following the hash
|
|
||||||
* symbol) of that URI, which the JavaScript side of this extension will
|
|
||||||
* move to the query parameters.
|
|
||||||
*
|
|
||||||
* @param authorizationEndpoint
|
|
||||||
* The full URL of the endpoint accepting OpenID authentication
|
|
||||||
* requests.
|
|
||||||
*
|
|
||||||
* @param scope
|
|
||||||
* The space-delimited list of OpenID scopes to request from the
|
|
||||||
* identity provider, such as "openid" or "openid email profile".
|
|
||||||
*
|
|
||||||
* @param clientID
|
|
||||||
* The ID of the OpenID client. This is normally determined ahead of
|
|
||||||
* time by the OpenID service through some manual credential request
|
|
||||||
* procedure.
|
|
||||||
*
|
|
||||||
* @param redirectURI
|
|
||||||
* The URI that the OpenID service should redirect to upon successful
|
|
||||||
* authentication.
|
|
||||||
*
|
|
||||||
* @param nonce
|
|
||||||
* A random string unique to this request. To defend against replay
|
|
||||||
* attacks, this value must cease being valid after its first use.
|
|
||||||
*
|
|
||||||
* @param redirectMessage
|
|
||||||
* The message that will be displayed to the user during redirect. This
|
|
||||||
* will be processed through Guacamole's translation system.
|
|
||||||
*/
|
|
||||||
public TokenField(URI authorizationEndpoint, String scope,
|
|
||||||
String clientID, URI redirectURI, String nonce,
|
|
||||||
TranslatableMessage redirectMessage) {
|
|
||||||
|
|
||||||
super(PARAMETER_NAME, UriBuilder.fromUri(authorizationEndpoint)
|
|
||||||
.queryParam("scope", scope)
|
|
||||||
.queryParam("response_type", "id_token")
|
|
||||||
.queryParam("client_id", clientID)
|
|
||||||
.queryParam("redirect_uri", redirectURI)
|
|
||||||
.queryParam("nonce", nonce)
|
|
||||||
.build(),
|
|
||||||
redirectMessage);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -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<String> 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<String> effectiveGroups) {
|
|
||||||
this.credentials = credentials;
|
|
||||||
this.effectiveGroups = effectiveGroups;
|
|
||||||
setIdentifier(username);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public AuthenticationProvider getAuthenticationProvider() {
|
|
||||||
return authProvider;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Credentials getCredentials() {
|
|
||||||
return credentials;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Set<String> getEffectiveUserGroups() {
|
|
||||||
return effectiveGroups;
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,12 +0,0 @@
|
|||||||
{
|
|
||||||
|
|
||||||
"DATA_SOURCE_OPENID" : {
|
|
||||||
"NAME" : "OpenID SSO Backend"
|
|
||||||
},
|
|
||||||
|
|
||||||
"LOGIN" : {
|
|
||||||
"FIELD_HEADER_ID_TOKEN" : "",
|
|
||||||
"INFO_OID_REDIRECT_PENDING" : "Espereu, redirigint al proveïdor d'identitat ..."
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,12 +0,0 @@
|
|||||||
{
|
|
||||||
|
|
||||||
"DATA_SOURCE_OPENID" : {
|
|
||||||
"NAME" : "OpenID SSO Backend"
|
|
||||||
},
|
|
||||||
|
|
||||||
"LOGIN" : {
|
|
||||||
"FIELD_HEADER_ID_TOKEN" : "",
|
|
||||||
"INFO_OID_REDIRECT_PENDING" : "Please wait, redirecting to identity provider..."
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,12 +0,0 @@
|
|||||||
{
|
|
||||||
|
|
||||||
"DATA_SOURCE_OPENID" : {
|
|
||||||
"NAME" : "OpenID SSO Backend"
|
|
||||||
},
|
|
||||||
|
|
||||||
"LOGIN" : {
|
|
||||||
"FIELD_HEADER_ID_TOKEN" : "",
|
|
||||||
"INFO_OID_REDIRECT_PENDING" : "Veuillez patienter, redirection vers le fournisseur d'identité..."
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,7 +0,0 @@
|
|||||||
{
|
|
||||||
|
|
||||||
"LOGIN" : {
|
|
||||||
"INFO_OID_REDIRECT_PENDING" : "IDプロバイダへリダイレクトしています。"
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,7 +0,0 @@
|
|||||||
{
|
|
||||||
|
|
||||||
"LOGIN" : {
|
|
||||||
"INFO_OID_REDIRECT_PENDING" : "잠시만 기다려주십시오. ID 제공자로 리디렉션 중..."
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,12 +0,0 @@
|
|||||||
{
|
|
||||||
|
|
||||||
"DATA_SOURCE_OPENID" : {
|
|
||||||
"NAME" : "OpenID SSO Backend"
|
|
||||||
},
|
|
||||||
|
|
||||||
"LOGIN" : {
|
|
||||||
"FIELD_HEADER_ID_TOKEN" : "",
|
|
||||||
"INFO_OID_REDIRECT_PENDING" : "Por favor aguarde, redirecionando ao provedor de indentidade..."
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,11 +0,0 @@
|
|||||||
{
|
|
||||||
|
|
||||||
"DATA_SOURCE_OPENID" : {
|
|
||||||
"NAME" : "Бэкенд OpenID SSO"
|
|
||||||
},
|
|
||||||
|
|
||||||
"LOGIN" : {
|
|
||||||
"INFO_REDIRECT_PENDING" : "Пожалуйста, подождите. Переадресую на страницу аутентификации..."
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,12 +0,0 @@
|
|||||||
{
|
|
||||||
|
|
||||||
"DATA_SOURCE_OPENID" : {
|
|
||||||
"NAME" : "OpenID SSO后端"
|
|
||||||
},
|
|
||||||
|
|
||||||
"LOGIN" : {
|
|
||||||
"FIELD_HEADER_ID_TOKEN" : "",
|
|
||||||
"INFO_REDIRECT_PENDING" : "请稍候,正在重定向到身份提供者..."
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,102 +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.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;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* AuthenticationProvider implementation that authenticates Guacamole users
|
|
||||||
* against a SAML SSO Identity Provider (IdP). This module does not provide any
|
|
||||||
* 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;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new SAMLAuthenticationProvider that authenticates users
|
|
||||||
* against a SAML IdP.
|
|
||||||
*/
|
|
||||||
public SAMLAuthenticationProvider() {
|
|
||||||
|
|
||||||
// Set up Guice injector.
|
|
||||||
injector = Guice.createInjector(
|
|
||||||
new SAMLAuthenticationProviderModule(this)
|
|
||||||
);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getIdentifier() {
|
|
||||||
return "saml";
|
|
||||||
}
|
|
||||||
|
|
||||||
@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();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,12 +0,0 @@
|
|||||||
{
|
|
||||||
|
|
||||||
"DATA_SOURCE_SAML" : {
|
|
||||||
"NAME" : "Extensión de autenticación SAML"
|
|
||||||
},
|
|
||||||
|
|
||||||
"LOGIN" : {
|
|
||||||
"FIELD_HEADER_SAML" : "",
|
|
||||||
"INFO_SAML_REDIRECT_PENDING" : "Por favor espere, redirigiendo al proveedor de identidad ..."
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,12 +0,0 @@
|
|||||||
{
|
|
||||||
|
|
||||||
"DATA_SOURCE_SAML" : {
|
|
||||||
"NAME" : "SAML Authentication Extension"
|
|
||||||
},
|
|
||||||
|
|
||||||
"LOGIN" : {
|
|
||||||
"FIELD_HEADER_SAML" : "",
|
|
||||||
"INFO_SAML_REDIRECT_PENDING" : "Please wait, redirecting to identity provider..."
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,12 +0,0 @@
|
|||||||
{
|
|
||||||
|
|
||||||
"DATA_SOURCE_SAML" : {
|
|
||||||
"NAME" : "SAML Authentication Extension"
|
|
||||||
},
|
|
||||||
|
|
||||||
"LOGIN" : {
|
|
||||||
"FIELD_HEADER_SAML" : "",
|
|
||||||
"INFO_SAML_REDIRECT_PENDING" : "Veuillez patienter, redirection vers le fournisseur d'identité..."
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,12 +0,0 @@
|
|||||||
{
|
|
||||||
|
|
||||||
"DATA_SOURCE_SAML" : {
|
|
||||||
"NAME" : "SAML Authentication Extension"
|
|
||||||
},
|
|
||||||
|
|
||||||
"LOGIN" : {
|
|
||||||
"FIELD_HEADER_SAML" : "",
|
|
||||||
"INFO_SAML_REDIRECT_PENDING" : "Por favor aguarde, redirecionando para o provedor de indentidade..."
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
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.3.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,180 @@
|
|||||||
|
/*
|
||||||
|
* 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(Environment.class).toInstance(LocalEnvironment.getInstance());
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -17,7 +17,7 @@
|
|||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.apache.guacamole.auth.cas.user;
|
package org.apache.guacamole.auth.sso.user;
|
||||||
|
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
@@ -28,11 +28,12 @@ import org.apache.guacamole.net.auth.AuthenticationProvider;
|
|||||||
import org.apache.guacamole.net.auth.Credentials;
|
import org.apache.guacamole.net.auth.Credentials;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An CAS-specific implementation of AuthenticatedUser, associating a
|
* An AuthenticatedUser whose identity has been supplied by an arbitrary SSO
|
||||||
* username and particular set of credentials with the CAS authentication
|
* service. An SSOAuthenticatedUser may additionally be associated with a set
|
||||||
* provider.
|
* 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
|
* Reference to the authentication provider associated with this
|
||||||
@@ -47,32 +48,20 @@ public class CASAuthenticatedUser extends AbstractAuthenticatedUser {
|
|||||||
private Credentials credentials;
|
private Credentials credentials;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tokens associated with this authenticated user.
|
* The groups that this user belongs to.
|
||||||
*/
|
|
||||||
private Map<String, String> tokens;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The unique identifiers of all user groups which this user is a member of.
|
|
||||||
*/
|
*/
|
||||||
private Set<String> effectiveGroups;
|
private Set<String> effectiveGroups;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes this AuthenticatedUser using the given username and
|
* Parameter tokens to be automatically injected for any connections used
|
||||||
* credentials, and an empty map of parameter tokens.
|
* by this user.
|
||||||
*
|
|
||||||
* @param username
|
|
||||||
* The username of the user that was authenticated.
|
|
||||||
*
|
|
||||||
* @param credentials
|
|
||||||
* The credentials provided when this user was authenticated.
|
|
||||||
*/
|
*/
|
||||||
public void init(String username, Credentials credentials) {
|
private Map<String, String> tokens;
|
||||||
this.init(username, credentials, Collections.emptyMap(), Collections.emptySet());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes this AuthenticatedUser using the given username,
|
* Initializes this SSOAuthenticatedUser, associating it with the given
|
||||||
* credentials, and parameter tokens.
|
* username, credentials, groups, and parameter tokens. This function must
|
||||||
|
* be invoked for every SSOAuthenticatedUser created.
|
||||||
*
|
*
|
||||||
* @param username
|
* @param username
|
||||||
* The username of the user that was authenticated.
|
* The username of the user that was authenticated.
|
||||||
@@ -80,25 +69,30 @@ public class CASAuthenticatedUser extends AbstractAuthenticatedUser {
|
|||||||
* @param credentials
|
* @param credentials
|
||||||
* The credentials provided when this user was authenticated.
|
* The credentials provided when this user was authenticated.
|
||||||
*
|
*
|
||||||
|
* @param effectiveGroups
|
||||||
|
* The groups that the authenticated user belongs to.
|
||||||
|
*
|
||||||
* @param tokens
|
* @param tokens
|
||||||
* A map of all the name/value pairs that should be available
|
* 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,
|
public void init(String username, Credentials credentials,
|
||||||
Map<String, String> tokens, Set<String> effectiveGroups) {
|
Set<String> effectiveGroups, Map<String, String> tokens) {
|
||||||
this.credentials = credentials;
|
this.credentials = credentials;
|
||||||
|
this.effectiveGroups = Collections.unmodifiableSet(effectiveGroups);
|
||||||
this.tokens = Collections.unmodifiableMap(tokens);
|
this.tokens = Collections.unmodifiableMap(tokens);
|
||||||
this.effectiveGroups = effectiveGroups;
|
setIdentifier(username);
|
||||||
setIdentifier(username.toLowerCase());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a Map containing the name/value pairs that can be applied
|
* Returns a Map of the parameter tokens that should be automatically
|
||||||
* as parameter tokens when connections are established by the user.
|
* 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
|
* @return
|
||||||
* A Map containing all of the name/value pairs that can be
|
* A map of the parameter token name/value pairs that should be
|
||||||
* used as parameter tokens by this user.
|
* automatically injected into connections used by this user.
|
||||||
*/
|
*/
|
||||||
public Map<String, String> getTokens() {
|
public Map<String, String> getTokens() {
|
||||||
return tokens;
|
return tokens;
|
@@ -0,0 +1,7 @@
|
|||||||
|
<meta name="after" content=".login-ui .login-dialog-middle">
|
||||||
|
<div class="sso-providers">
|
||||||
|
<div class="sso-providers-content">
|
||||||
|
{{ 'LOGIN.SECTION_HEADER_SSO_OPTIONS' | translate }}
|
||||||
|
<ul class="sso-provider-list"></ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
@@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
* 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 {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-ui .sso-providers:last-child {
|
||||||
|
display: table-row;
|
||||||
|
}
|
||||||
|
|
||||||
|
.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;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sso-providers-content {
|
||||||
|
display: table-cell;
|
||||||
|
padding: 0.25em 0.5em;
|
||||||
|
height: 1px;
|
||||||
|
}
|
@@ -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 ..."
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
|
|
||||||
"LOGIN" : {
|
"LOGIN" : {
|
||||||
"INFO_OID_REDIRECT_PENDING" : "Bitte warten, Sie werden zum Identitätsprovider weitergeleitet..."
|
"INFO_IDP_REDIRECT_PENDING" : "Bitte warten, Sie werden zum Identitätsprovider weitergeleitet..."
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@@ -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" : "Please wait, redirecting to identity provider...",
|
||||||
|
"NAME_IDP_CAS" : "CAS",
|
||||||
|
"NAME_IDP_OPENID" : "OpenID",
|
||||||
|
"NAME_IDP_SAML" : "SAML",
|
||||||
|
"SECTION_HEADER_SSO_OPTIONS" : "Sign in with:"
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
|
||||||
|
"LOGIN" : {
|
||||||
|
"INFO_IDP_REDIRECT_PENDING" : "Veuillez patienter, redirection vers le fournisseur d'identité..."
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
|
||||||
|
"LOGIN" : {
|
||||||
|
"INFO_IDP_REDIRECT_PENDING" : "IDプロバイダへリダイレクトしています。"
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -5,7 +5,7 @@
|
|||||||
},
|
},
|
||||||
|
|
||||||
"LOGIN" : {
|
"LOGIN" : {
|
||||||
"INFO_SAML_REDIRECT_PENDING": "잠시만 기다려주십시오. ID 제공자로 리디렉션 중..."
|
"INFO_IDP_REDIRECT_PENDING" : "잠시만 기다려주십시오. ID 제공자로 리디렉션 중..."
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@@ -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" : "请稍候,正在重定向到身份提供者..."
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1 @@
|
|||||||
|
src/main/resources/html/*.html
|
@@ -24,17 +24,17 @@
|
|||||||
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<groupId>org.apache.guacamole</groupId>
|
<groupId>org.apache.guacamole</groupId>
|
||||||
<artifactId>guacamole-auth-cas</artifactId>
|
<artifactId>guacamole-auth-sso-cas</artifactId>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
<version>1.3.0</version>
|
<version>1.3.0</version>
|
||||||
<name>guacamole-auth-cas</name>
|
<name>guacamole-auth-sso-cas</name>
|
||||||
<url>http://guacamole.apache.org/</url>
|
<url>http://guacamole.apache.org/</url>
|
||||||
|
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>org.apache.guacamole</groupId>
|
<groupId>org.apache.guacamole</groupId>
|
||||||
<artifactId>extensions</artifactId>
|
<artifactId>guacamole-auth-sso</artifactId>
|
||||||
<version>1.3.0</version>
|
<version>1.3.0</version>
|
||||||
<relativePath>../</relativePath>
|
<relativePath>../../</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
@@ -43,8 +43,12 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.guacamole</groupId>
|
<groupId>org.apache.guacamole</groupId>
|
||||||
<artifactId>guacamole-ext</artifactId>
|
<artifactId>guacamole-ext</artifactId>
|
||||||
<version>1.3.0</version>
|
</dependency>
|
||||||
<scope>provided</scope>
|
|
||||||
|
<!-- Core SSO support -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.guacamole</groupId>
|
||||||
|
<artifactId>guacamole-auth-sso-base</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- Apereo CAS Client API -->
|
<!-- Apereo CAS Client API -->
|
||||||
@@ -70,16 +74,12 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>javax.servlet</groupId>
|
<groupId>javax.servlet</groupId>
|
||||||
<artifactId>servlet-api</artifactId>
|
<artifactId>servlet-api</artifactId>
|
||||||
<version>2.5</version>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- Jersey - JAX-RS Implementation -->
|
<!-- JAX-RS Annotations -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>javax.ws.rs</groupId>
|
<groupId>javax.ws.rs</groupId>
|
||||||
<artifactId>jsr311-api</artifactId>
|
<artifactId>jsr311-api</artifactId>
|
||||||
<version>1.1.1</version>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- JUnit -->
|
<!-- JUnit -->
|
@@ -20,24 +20,38 @@
|
|||||||
package org.apache.guacamole.auth.cas;
|
package org.apache.guacamole.auth.cas;
|
||||||
|
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
|
import com.google.inject.Singleton;
|
||||||
|
import java.net.URI;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.ws.rs.core.UriBuilder;
|
||||||
import org.apache.guacamole.form.Field;
|
import org.apache.guacamole.form.Field;
|
||||||
import org.apache.guacamole.GuacamoleException;
|
import org.apache.guacamole.GuacamoleException;
|
||||||
import org.apache.guacamole.net.auth.Credentials;
|
import org.apache.guacamole.net.auth.Credentials;
|
||||||
import org.apache.guacamole.net.auth.credentials.CredentialsInfo;
|
import org.apache.guacamole.net.auth.credentials.CredentialsInfo;
|
||||||
import org.apache.guacamole.net.auth.credentials.GuacamoleInvalidCredentialsException;
|
import org.apache.guacamole.net.auth.credentials.GuacamoleInvalidCredentialsException;
|
||||||
import org.apache.guacamole.auth.cas.conf.ConfigurationService;
|
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.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.form.RedirectField;
|
||||||
import org.apache.guacamole.language.TranslatableMessage;
|
import org.apache.guacamole.language.TranslatableMessage;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Service providing convenience functions for the CAS AuthenticationProvider
|
* Service that authenticates Guacamole users by processing CAS tickets.
|
||||||
* implementation.
|
|
||||||
*/
|
*/
|
||||||
public class AuthenticationProviderService {
|
@Singleton
|
||||||
|
public class AuthenticationProviderService implements SSOAuthenticationProviderService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The parameter that will be present upon successful CAS authentication.
|
||||||
|
*/
|
||||||
|
public static final String TICKET_PARAMETER_NAME = "ticket";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The standard URI name for the CAS login resource.
|
||||||
|
*/
|
||||||
|
private static final String CAS_LOGIN_URI = "login";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Service for retrieving CAS configuration information.
|
* Service for retrieving CAS configuration information.
|
||||||
@@ -51,48 +65,42 @@ public class AuthenticationProviderService {
|
|||||||
@Inject
|
@Inject
|
||||||
private TicketValidationService ticketService;
|
private TicketValidationService ticketService;
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Returns an AuthenticatedUser representing the user authenticated by the
|
public SSOAuthenticatedUser authenticateUser(Credentials credentials)
|
||||||
* 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)
|
|
||||||
throws GuacamoleException {
|
throws GuacamoleException {
|
||||||
|
|
||||||
// Pull CAS ticket from request if present
|
// Pull CAS ticket from request if present
|
||||||
HttpServletRequest request = credentials.getRequest();
|
HttpServletRequest request = credentials.getRequest();
|
||||||
if (request != null) {
|
if (request != null) {
|
||||||
String ticket = request.getParameter(CASTicketField.PARAMETER_NAME);
|
String ticket = request.getParameter(TICKET_PARAMETER_NAME);
|
||||||
if (ticket != null) {
|
if (ticket != null) {
|
||||||
return ticketService.validateTicket(ticket, credentials);
|
return ticketService.validateTicket(ticket, credentials);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Request CAS ticket
|
// Request CAS ticket (will automatically redirect the user to the
|
||||||
|
// CAS authorization page via JavaScript)
|
||||||
throw new GuacamoleInvalidCredentialsException("Invalid login.",
|
throw new GuacamoleInvalidCredentialsException("Invalid login.",
|
||||||
new CredentialsInfo(Arrays.asList(new Field[] {
|
new CredentialsInfo(Arrays.asList(new Field[] {
|
||||||
|
new RedirectField(TICKET_PARAMETER_NAME, getLoginURI(),
|
||||||
// CAS-specific ticket (will automatically redirect the user
|
new TranslatableMessage("LOGIN.INFO_IDP_REDIRECT_PENDING"))
|
||||||
// to the authorization page via JavaScript)
|
|
||||||
new CASTicketField(
|
|
||||||
confService.getAuthorizationEndpoint(),
|
|
||||||
confService.getRedirectURI(),
|
|
||||||
new TranslatableMessage("LOGIN.INFO_CAS_REDIRECT_PENDING")
|
|
||||||
)
|
|
||||||
|
|
||||||
}))
|
}))
|
||||||
);
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public URI getLoginURI() throws GuacamoleException {
|
||||||
|
return UriBuilder.fromUri(confService.getAuthorizationEndpoint())
|
||||||
|
.path(CAS_LOGIN_URI)
|
||||||
|
.queryParam("service", confService.getRedirectURI())
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void shutdown() {
|
||||||
|
// Nothing to clean up
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
@@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
* 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.cas;
|
||||||
|
|
||||||
|
import org.apache.guacamole.auth.sso.SSOAuthenticationProvider;
|
||||||
|
import org.apache.guacamole.auth.sso.SSOResource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Guacamole authentication backend which authenticates users using an
|
||||||
|
* arbitrary external system implementing CAS. No storage for connections is
|
||||||
|
* provided - only authentication. Storage must be provided by some other
|
||||||
|
* extension.
|
||||||
|
*/
|
||||||
|
public class CASAuthenticationProvider extends SSOAuthenticationProvider {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new CASAuthenticationProvider that authenticates users
|
||||||
|
* against an CAS service
|
||||||
|
*/
|
||||||
|
public CASAuthenticationProvider() {
|
||||||
|
super(AuthenticationProviderService.class,
|
||||||
|
SSOResource.class, new CASAuthenticationProviderModule());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getIdentifier() {
|
||||||
|
return "cas";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* 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.cas;
|
||||||
|
|
||||||
|
import com.google.inject.AbstractModule;
|
||||||
|
import org.apache.guacamole.auth.cas.conf.ConfigurationService;
|
||||||
|
import org.apache.guacamole.auth.cas.ticket.TicketValidationService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Guice module which configures CAS-specific injections.
|
||||||
|
*/
|
||||||
|
public class CASAuthenticationProviderModule extends AbstractModule {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void configure() {
|
||||||
|
bind(ConfigurationService.class);
|
||||||
|
bind(TicketValidationService.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -41,7 +41,7 @@ import org.apache.guacamole.GuacamoleException;
|
|||||||
import org.apache.guacamole.GuacamoleSecurityException;
|
import org.apache.guacamole.GuacamoleSecurityException;
|
||||||
import org.apache.guacamole.GuacamoleServerException;
|
import org.apache.guacamole.GuacamoleServerException;
|
||||||
import org.apache.guacamole.auth.cas.conf.ConfigurationService;
|
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.net.auth.Credentials;
|
||||||
import org.apache.guacamole.token.TokenName;
|
import org.apache.guacamole.token.TokenName;
|
||||||
import org.jasig.cas.client.authentication.AttributePrincipal;
|
import org.jasig.cas.client.authentication.AttributePrincipal;
|
||||||
@@ -77,7 +77,7 @@ public class TicketValidationService {
|
|||||||
* Provider for AuthenticatedUser objects.
|
* Provider for AuthenticatedUser objects.
|
||||||
*/
|
*/
|
||||||
@Inject
|
@Inject
|
||||||
private Provider<CASAuthenticatedUser> authenticatedUserProvider;
|
private Provider<SSOAuthenticatedUser> authenticatedUserProvider;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts the given CAS attribute value object (whose type is variable)
|
* 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
|
* If the ID ticket is not valid or guacamole.properties could
|
||||||
* not be parsed.
|
* not be parsed.
|
||||||
*/
|
*/
|
||||||
public CASAuthenticatedUser validateTicket(String ticket,
|
public SSOAuthenticatedUser validateTicket(String ticket,
|
||||||
Credentials credentials) throws GuacamoleException {
|
Credentials credentials) throws GuacamoleException {
|
||||||
|
|
||||||
// Create a ticket validator that uses the configured CAS URL
|
// Create a ticket validator that uses the configured CAS URL
|
||||||
@@ -160,6 +160,9 @@ public class TicketValidationService {
|
|||||||
if (username == null)
|
if (username == null)
|
||||||
throw new GuacamoleSecurityException("No username provided by CAS.");
|
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
|
// Update credentials with username provided by CAS for sake of
|
||||||
// ${GUAC_USERNAME} token
|
// ${GUAC_USERNAME} token
|
||||||
credentials.setUsername(username);
|
credentials.setUsername(username);
|
||||||
@@ -196,8 +199,8 @@ public class TicketValidationService {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
CASAuthenticatedUser authenticatedUser = authenticatedUserProvider.get();
|
SSOAuthenticatedUser authenticatedUser = authenticatedUserProvider.get();
|
||||||
authenticatedUser.init(username, credentials, tokens, effectiveGroups);
|
authenticatedUser.init(username, credentials, effectiveGroups, tokens);
|
||||||
return authenticatedUser;
|
return authenticatedUser;
|
||||||
|
|
||||||
}
|
}
|
@@ -9,6 +9,15 @@
|
|||||||
"org.apache.guacamole.auth.cas.CASAuthenticationProvider"
|
"org.apache.guacamole.auth.cas.CASAuthenticationProvider"
|
||||||
],
|
],
|
||||||
|
|
||||||
|
"css" : [
|
||||||
|
"styles/sso-providers.css"
|
||||||
|
],
|
||||||
|
|
||||||
|
"html" : [
|
||||||
|
"html/sso-providers.html",
|
||||||
|
"html/sso-provider-cas.html"
|
||||||
|
],
|
||||||
|
|
||||||
"translations" : [
|
"translations" : [
|
||||||
"translations/ca.json",
|
"translations/ca.json",
|
||||||
"translations/de.json",
|
"translations/de.json",
|
@@ -0,0 +1,4 @@
|
|||||||
|
<meta name="after-children" content=".login-ui .sso-provider-list:last-child">
|
||||||
|
<li class="sso-provider sso-provider-cas"><a href="api/ext/cas/login">{{
|
||||||
|
'LOGIN.NAME_IDP_CAS' | translate
|
||||||
|
}}</a></li>
|
@@ -0,0 +1,72 @@
|
|||||||
|
<?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-dist</artifactId>
|
||||||
|
<packaging>pom</packaging>
|
||||||
|
<name>guacamole-auth-sso-dist</name>
|
||||||
|
<url>http://guacamole.apache.org/</url>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>org.apache.guacamole</groupId>
|
||||||
|
<artifactId>guacamole-auth-sso</artifactId>
|
||||||
|
<version>1.3.0</version>
|
||||||
|
<relativePath>../../</relativePath>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
|
||||||
|
<!-- CAS Authentication Extension -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.guacamole</groupId>
|
||||||
|
<artifactId>guacamole-auth-sso-cas</artifactId>
|
||||||
|
<version>1.3.0</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- OpenID Authentication Extension -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.guacamole</groupId>
|
||||||
|
<artifactId>guacamole-auth-sso-openid</artifactId>
|
||||||
|
<version>1.3.0</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- SAML Authentication Extension -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.guacamole</groupId>
|
||||||
|
<artifactId>guacamole-auth-sso-saml</artifactId>
|
||||||
|
<version>1.3.0</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
|
||||||
|
<!-- Dist .tar.gz for guacamole-auth-sso should be named after the
|
||||||
|
parent guacamole-auth-sso project, not after guacamole-auth-sso-dist -->
|
||||||
|
<finalName>${project.parent.artifactId}-${project.parent.version}</finalName>
|
||||||
|
|
||||||
|
</build>
|
||||||
|
|
||||||
|
</project>
|
@@ -23,31 +23,51 @@
|
|||||||
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
|
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
|
||||||
|
|
||||||
<id>dist</id>
|
<id>dist</id>
|
||||||
<baseDirectory>${project.artifactId}-${project.version}</baseDirectory>
|
<baseDirectory>${project.parent.artifactId}-${project.parent.version}</baseDirectory>
|
||||||
|
|
||||||
<!-- Output tar.gz -->
|
<!-- Output .tar.gz -->
|
||||||
<formats>
|
<formats>
|
||||||
<format>tar.gz</format>
|
<format>tar.gz</format>
|
||||||
</formats>
|
</formats>
|
||||||
|
|
||||||
<!-- Include licenses and extension .jar -->
|
<!-- Include extension .jars -->
|
||||||
<fileSets>
|
<dependencySets>
|
||||||
|
|
||||||
<!-- Include licenses -->
|
<!-- CAS extension .jar -->
|
||||||
|
<dependencySet>
|
||||||
|
<outputDirectory>cas</outputDirectory>
|
||||||
|
<useProjectArtifact>false</useProjectArtifact>
|
||||||
|
<includes>
|
||||||
|
<include>org.apache.guacamole:guacamole-auth-sso-cas</include>
|
||||||
|
</includes>
|
||||||
|
</dependencySet>
|
||||||
|
|
||||||
|
<!-- OpenID extension .jar -->
|
||||||
|
<dependencySet>
|
||||||
|
<outputDirectory>openid</outputDirectory>
|
||||||
|
<useProjectArtifact>false</useProjectArtifact>
|
||||||
|
<includes>
|
||||||
|
<include>org.apache.guacamole:guacamole-auth-sso-openid</include>
|
||||||
|
</includes>
|
||||||
|
</dependencySet>
|
||||||
|
|
||||||
|
<!-- SAML extension .jar -->
|
||||||
|
<dependencySet>
|
||||||
|
<outputDirectory>saml</outputDirectory>
|
||||||
|
<useProjectArtifact>false</useProjectArtifact>
|
||||||
|
<includes>
|
||||||
|
<include>org.apache.guacamole:guacamole-auth-sso-saml</include>
|
||||||
|
</includes>
|
||||||
|
</dependencySet>
|
||||||
|
|
||||||
|
</dependencySets>
|
||||||
|
|
||||||
|
<!-- Include extension licenses -->
|
||||||
|
<fileSets>
|
||||||
<fileSet>
|
<fileSet>
|
||||||
<outputDirectory></outputDirectory>
|
<outputDirectory></outputDirectory>
|
||||||
<directory>target/licenses</directory>
|
<directory>target/licenses</directory>
|
||||||
</fileSet>
|
</fileSet>
|
||||||
|
|
||||||
<!-- Include extension .jar -->
|
|
||||||
<fileSet>
|
|
||||||
<directory>target</directory>
|
|
||||||
<outputDirectory></outputDirectory>
|
|
||||||
<includes>
|
|
||||||
<include>*.jar</include>
|
|
||||||
</includes>
|
|
||||||
</fileSet>
|
|
||||||
|
|
||||||
</fileSets>
|
</fileSets>
|
||||||
|
|
||||||
</assembly>
|
</assembly>
|
@@ -0,0 +1 @@
|
|||||||
|
src/main/resources/html/*.html
|
@@ -24,17 +24,17 @@
|
|||||||
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<groupId>org.apache.guacamole</groupId>
|
<groupId>org.apache.guacamole</groupId>
|
||||||
<artifactId>guacamole-auth-openid</artifactId>
|
<artifactId>guacamole-auth-sso-openid</artifactId>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
<version>1.3.0</version>
|
<version>1.3.0</version>
|
||||||
<name>guacamole-auth-openid</name>
|
<name>guacamole-auth-sso-openid</name>
|
||||||
<url>http://guacamole.apache.org/</url>
|
<url>http://guacamole.apache.org/</url>
|
||||||
|
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>org.apache.guacamole</groupId>
|
<groupId>org.apache.guacamole</groupId>
|
||||||
<artifactId>extensions</artifactId>
|
<artifactId>guacamole-auth-sso</artifactId>
|
||||||
<version>1.3.0</version>
|
<version>1.3.0</version>
|
||||||
<relativePath>../</relativePath>
|
<relativePath>../../</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
@@ -94,8 +94,12 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.guacamole</groupId>
|
<groupId>org.apache.guacamole</groupId>
|
||||||
<artifactId>guacamole-ext</artifactId>
|
<artifactId>guacamole-ext</artifactId>
|
||||||
<version>1.3.0</version>
|
</dependency>
|
||||||
<scope>provided</scope>
|
|
||||||
|
<!-- Core SSO support -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.guacamole</groupId>
|
||||||
|
<artifactId>guacamole-auth-sso-base</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- Java implementation of JOSE (jose.4.j) -->
|
<!-- Java implementation of JOSE (jose.4.j) -->
|
||||||
@@ -115,16 +119,12 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>javax.servlet</groupId>
|
<groupId>javax.servlet</groupId>
|
||||||
<artifactId>servlet-api</artifactId>
|
<artifactId>servlet-api</artifactId>
|
||||||
<version>2.5</version>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- Jersey - JAX-RS Implementation -->
|
<!-- JAX-RS Annotations -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>javax.ws.rs</groupId>
|
<groupId>javax.ws.rs</groupId>
|
||||||
<artifactId>jsr311-api</artifactId>
|
<artifactId>jsr311-api</artifactId>
|
||||||
<version>1.1.1</version>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
@@ -21,34 +21,38 @@ package org.apache.guacamole.auth.openid;
|
|||||||
|
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
import com.google.inject.Provider;
|
import com.google.inject.Provider;
|
||||||
|
import com.google.inject.Singleton;
|
||||||
|
import java.net.URI;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.ws.rs.core.UriBuilder;
|
||||||
import org.apache.guacamole.auth.openid.conf.ConfigurationService;
|
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.NonceService;
|
||||||
import org.apache.guacamole.auth.openid.token.TokenValidationService;
|
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.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.form.Field;
|
||||||
|
import org.apache.guacamole.form.RedirectField;
|
||||||
import org.apache.guacamole.language.TranslatableMessage;
|
import org.apache.guacamole.language.TranslatableMessage;
|
||||||
import org.apache.guacamole.net.auth.Credentials;
|
import org.apache.guacamole.net.auth.Credentials;
|
||||||
import org.apache.guacamole.net.auth.credentials.CredentialsInfo;
|
import org.apache.guacamole.net.auth.credentials.CredentialsInfo;
|
||||||
import org.apache.guacamole.net.auth.credentials.GuacamoleInvalidCredentialsException;
|
import org.apache.guacamole.net.auth.credentials.GuacamoleInvalidCredentialsException;
|
||||||
import org.jose4j.jwt.JwtClaims;
|
import org.jose4j.jwt.JwtClaims;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Service providing convenience functions for the OpenID AuthenticationProvider
|
* Service that authenticates Guacamole users by processing OpenID tokens.
|
||||||
* implementation.
|
|
||||||
*/
|
*/
|
||||||
public class AuthenticationProviderService {
|
@Singleton
|
||||||
|
public class AuthenticationProviderService implements SSOAuthenticationProviderService {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Logger for this class.
|
* The standard HTTP parameter which will be included within the URL by all
|
||||||
|
* OpenID services upon successful authentication and redirect.
|
||||||
*/
|
*/
|
||||||
private final Logger logger = LoggerFactory.getLogger(AuthenticationProviderService.class);
|
public static final String TOKEN_PARAMETER_NAME = "id_token";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Service for retrieving OpenID configuration information.
|
* Service for retrieving OpenID configuration information.
|
||||||
@@ -72,24 +76,10 @@ public class AuthenticationProviderService {
|
|||||||
* Provider for AuthenticatedUser objects.
|
* Provider for AuthenticatedUser objects.
|
||||||
*/
|
*/
|
||||||
@Inject
|
@Inject
|
||||||
private Provider<AuthenticatedUser> authenticatedUserProvider;
|
private Provider<SSOAuthenticatedUser> authenticatedUserProvider;
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Returns an AuthenticatedUser representing the user authenticated by the
|
public SSOAuthenticatedUser authenticateUser(Credentials credentials)
|
||||||
* 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)
|
|
||||||
throws GuacamoleException {
|
throws GuacamoleException {
|
||||||
|
|
||||||
String username = null;
|
String username = null;
|
||||||
@@ -98,7 +88,7 @@ public class AuthenticationProviderService {
|
|||||||
// Validate OpenID token in request, if present, and derive username
|
// Validate OpenID token in request, if present, and derive username
|
||||||
HttpServletRequest request = credentials.getRequest();
|
HttpServletRequest request = credentials.getRequest();
|
||||||
if (request != null) {
|
if (request != null) {
|
||||||
String token = request.getParameter(TokenField.PARAMETER_NAME);
|
String token = request.getParameter(TOKEN_PARAMETER_NAME);
|
||||||
if (token != null) {
|
if (token != null) {
|
||||||
JwtClaims claims = tokenService.validateToken(token);
|
JwtClaims claims = tokenService.validateToken(token);
|
||||||
if (claims != null) {
|
if (claims != null) {
|
||||||
@@ -113,30 +103,37 @@ public class AuthenticationProviderService {
|
|||||||
if (username != null) {
|
if (username != null) {
|
||||||
|
|
||||||
// Create corresponding authenticated user
|
// Create corresponding authenticated user
|
||||||
AuthenticatedUser authenticatedUser = authenticatedUserProvider.get();
|
SSOAuthenticatedUser authenticatedUser = authenticatedUserProvider.get();
|
||||||
authenticatedUser.init(username, credentials, groups);
|
authenticatedUser.init(username, credentials, groups, Collections.emptyMap());
|
||||||
return authenticatedUser;
|
return authenticatedUser;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Request OpenID token
|
// Request OpenID token (will automatically redirect the user to the
|
||||||
|
// OpenID authorization page via JavaScript)
|
||||||
throw new GuacamoleInvalidCredentialsException("Invalid login.",
|
throw new GuacamoleInvalidCredentialsException("Invalid login.",
|
||||||
new CredentialsInfo(Arrays.asList(new Field[] {
|
new CredentialsInfo(Arrays.asList(new Field[] {
|
||||||
|
new RedirectField(TOKEN_PARAMETER_NAME, getLoginURI(),
|
||||||
// OpenID-specific token (will automatically redirect the user
|
new TranslatableMessage("LOGIN.INFO_IDP_REDIRECT_PENDING"))
|
||||||
// to the authorization page via JavaScript)
|
|
||||||
new TokenField(
|
|
||||||
confService.getAuthorizationEndpoint(),
|
|
||||||
confService.getScope(),
|
|
||||||
confService.getClientID(),
|
|
||||||
confService.getRedirectURI(),
|
|
||||||
nonceService.generate(confService.getMaxNonceValidity() * 60000L),
|
|
||||||
new TranslatableMessage("LOGIN.INFO_OID_REDIRECT_PENDING")
|
|
||||||
)
|
|
||||||
|
|
||||||
}))
|
}))
|
||||||
);
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public URI getLoginURI() throws GuacamoleException {
|
||||||
|
return UriBuilder.fromUri(confService.getAuthorizationEndpoint())
|
||||||
|
.queryParam("scope", confService.getScope())
|
||||||
|
.queryParam("response_type", "id_token")
|
||||||
|
.queryParam("client_id", confService.getClientID())
|
||||||
|
.queryParam("redirect_uri", confService.getRedirectURI())
|
||||||
|
.queryParam("nonce", nonceService.generate(confService.getMaxNonceValidity() * 60000L))
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void shutdown() {
|
||||||
|
// Nothing to clean up
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
@@ -19,12 +19,8 @@
|
|||||||
|
|
||||||
package org.apache.guacamole.auth.openid;
|
package org.apache.guacamole.auth.openid;
|
||||||
|
|
||||||
import com.google.inject.Guice;
|
import org.apache.guacamole.auth.sso.SSOAuthenticationProvider;
|
||||||
import com.google.inject.Injector;
|
import org.apache.guacamole.auth.sso.SSOResource;
|
||||||
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;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Guacamole authentication backend which authenticates users using an
|
* Guacamole authentication backend which authenticates users using an
|
||||||
@@ -32,29 +28,15 @@ import org.apache.guacamole.net.auth.Credentials;
|
|||||||
* provided - only authentication. Storage must be provided by some other
|
* provided - only authentication. Storage must be provided by some other
|
||||||
* extension.
|
* extension.
|
||||||
*/
|
*/
|
||||||
public class OpenIDAuthenticationProvider extends AbstractAuthenticationProvider {
|
public class OpenIDAuthenticationProvider extends SSOAuthenticationProvider {
|
||||||
|
|
||||||
/**
|
|
||||||
* Injector which will manage the object graph of this authentication
|
|
||||||
* provider.
|
|
||||||
*/
|
|
||||||
private final Injector injector;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new OpenIDAuthenticationProvider that authenticates users
|
* Creates a new OpenIDAuthenticationProvider that authenticates users
|
||||||
* against an OpenID service.
|
* against an OpenID service.
|
||||||
*
|
|
||||||
* @throws GuacamoleException
|
|
||||||
* If a required property is missing, or an error occurs while parsing
|
|
||||||
* a property.
|
|
||||||
*/
|
*/
|
||||||
public OpenIDAuthenticationProvider() throws GuacamoleException {
|
public OpenIDAuthenticationProvider() {
|
||||||
|
super(AuthenticationProviderService.class, SSOResource.class,
|
||||||
// Set up Guice injector.
|
new OpenIDAuthenticationProviderModule());
|
||||||
injector = Guice.createInjector(
|
|
||||||
new OpenIDAuthenticationProviderModule(this)
|
|
||||||
);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -62,14 +44,4 @@ public class OpenIDAuthenticationProvider extends AbstractAuthenticationProvider
|
|||||||
return "openid";
|
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);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
@@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Guice module which configures OpenID-specific injections.
|
||||||
|
*/
|
||||||
|
public class OpenIDAuthenticationProviderModule extends AbstractModule {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void configure() {
|
||||||
|
bind(ConfigurationService.class);
|
||||||
|
bind(NonceService.class);
|
||||||
|
bind(TokenValidationService.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -9,6 +9,15 @@
|
|||||||
"org.apache.guacamole.auth.openid.OpenIDAuthenticationProvider"
|
"org.apache.guacamole.auth.openid.OpenIDAuthenticationProvider"
|
||||||
],
|
],
|
||||||
|
|
||||||
|
"css" : [
|
||||||
|
"styles/sso-providers.css"
|
||||||
|
],
|
||||||
|
|
||||||
|
"html" : [
|
||||||
|
"html/sso-providers.html",
|
||||||
|
"html/sso-provider-openid.html"
|
||||||
|
],
|
||||||
|
|
||||||
"translations" : [
|
"translations" : [
|
||||||
"translations/ca.json",
|
"translations/ca.json",
|
||||||
"translations/de.json",
|
"translations/de.json",
|
@@ -0,0 +1,4 @@
|
|||||||
|
<meta name="after-children" content=".login-ui .sso-provider-list:last-child">
|
||||||
|
<li class="sso-provider sso-provider-openid"><a href="api/ext/openid/login">{{
|
||||||
|
'LOGIN.NAME_IDP_OPENID' | translate
|
||||||
|
}}</a></li>
|
@@ -0,0 +1 @@
|
|||||||
|
src/main/resources/html/*.html
|
@@ -24,17 +24,17 @@
|
|||||||
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<groupId>org.apache.guacamole</groupId>
|
<groupId>org.apache.guacamole</groupId>
|
||||||
<artifactId>guacamole-auth-saml</artifactId>
|
<artifactId>guacamole-auth-sso-saml</artifactId>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
<version>1.3.0</version>
|
<version>1.3.0</version>
|
||||||
<name>guacamole-auth-saml</name>
|
<name>guacamole-auth-sso-saml</name>
|
||||||
<url>http://guacamole.apache.org/</url>
|
<url>http://guacamole.apache.org/</url>
|
||||||
|
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>org.apache.guacamole</groupId>
|
<groupId>org.apache.guacamole</groupId>
|
||||||
<artifactId>extensions</artifactId>
|
<artifactId>guacamole-auth-sso</artifactId>
|
||||||
<version>1.3.0</version>
|
<version>1.3.0</version>
|
||||||
<relativePath>../</relativePath>
|
<relativePath>../../</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
@@ -43,8 +43,12 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.guacamole</groupId>
|
<groupId>org.apache.guacamole</groupId>
|
||||||
<artifactId>guacamole-ext</artifactId>
|
<artifactId>guacamole-ext</artifactId>
|
||||||
<version>1.3.0</version>
|
</dependency>
|
||||||
<scope>provided</scope>
|
|
||||||
|
<!-- Core SSO support -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.guacamole</groupId>
|
||||||
|
<artifactId>guacamole-auth-sso-base</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- Guice -->
|
<!-- Guice -->
|
||||||
@@ -57,16 +61,12 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>javax.servlet</groupId>
|
<groupId>javax.servlet</groupId>
|
||||||
<artifactId>servlet-api</artifactId>
|
<artifactId>servlet-api</artifactId>
|
||||||
<version>2.5</version>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- Jersey - JAX-RS Implementation -->
|
<!-- JAX-RS Annotations -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>javax.ws.rs</groupId>
|
<groupId>javax.ws.rs</groupId>
|
||||||
<artifactId>jsr311-api</artifactId>
|
<artifactId>jsr311-api</artifactId>
|
||||||
<version>1.1.1</version>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- OneLogin SAML Library -->
|
<!-- OneLogin SAML Library -->
|
@@ -21,6 +21,7 @@ package org.apache.guacamole.auth.saml;
|
|||||||
|
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
import com.google.inject.Provider;
|
import com.google.inject.Provider;
|
||||||
|
import com.google.inject.Singleton;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
@@ -29,19 +30,20 @@ import org.apache.guacamole.GuacamoleException;
|
|||||||
import org.apache.guacamole.auth.saml.acs.AssertedIdentity;
|
import org.apache.guacamole.auth.saml.acs.AssertedIdentity;
|
||||||
import org.apache.guacamole.auth.saml.acs.AuthenticationSessionManager;
|
import org.apache.guacamole.auth.saml.acs.AuthenticationSessionManager;
|
||||||
import org.apache.guacamole.auth.saml.acs.SAMLService;
|
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.Field;
|
||||||
import org.apache.guacamole.form.RedirectField;
|
import org.apache.guacamole.form.RedirectField;
|
||||||
import org.apache.guacamole.language.TranslatableMessage;
|
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;
|
||||||
import org.apache.guacamole.net.auth.credentials.CredentialsInfo;
|
import org.apache.guacamole.net.auth.credentials.CredentialsInfo;
|
||||||
import org.apache.guacamole.net.auth.credentials.GuacamoleInsufficientCredentialsException;
|
import org.apache.guacamole.net.auth.credentials.GuacamoleInvalidCredentialsException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Service that authenticates Guacamole users by processing the responses of
|
* Service that authenticates Guacamole users by processing the responses of
|
||||||
* SAML identity providers.
|
* SAML identity providers.
|
||||||
*/
|
*/
|
||||||
public class AuthenticationProviderService {
|
@Singleton
|
||||||
|
public class AuthenticationProviderService implements SSOAuthenticationProviderService {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The name of the query parameter that identifies an active authentication
|
* The name of the query parameter that identifies an active authentication
|
||||||
@@ -67,22 +69,8 @@ public class AuthenticationProviderService {
|
|||||||
@Inject
|
@Inject
|
||||||
private SAMLService saml;
|
private SAMLService saml;
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Returns an AuthenticatedUser representing the user authenticated by the
|
public SAMLAuthenticatedUser authenticateUser(Credentials credentials)
|
||||||
* 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)
|
|
||||||
throws GuacamoleException {
|
throws GuacamoleException {
|
||||||
|
|
||||||
// No authentication can be attempted without a corresponding HTTP
|
// No authentication can be attempted without a corresponding HTTP
|
||||||
@@ -107,13 +95,23 @@ public class AuthenticationProviderService {
|
|||||||
|
|
||||||
// Redirect to SAML IdP if no SAML identity is associated with the
|
// Redirect to SAML IdP if no SAML identity is associated with the
|
||||||
// Guacamole authentication request
|
// Guacamole authentication request
|
||||||
URI authUri = saml.createRequest();
|
throw new GuacamoleInvalidCredentialsException("Redirecting to SAML IdP.",
|
||||||
throw new GuacamoleInsufficientCredentialsException("Redirecting to SAML IdP.",
|
|
||||||
new CredentialsInfo(Arrays.asList(new Field[] {
|
new CredentialsInfo(Arrays.asList(new Field[] {
|
||||||
new RedirectField("samlRedirect", authUri, new TranslatableMessage("LOGIN.INFO_SAML_REDIRECT_PENDING"))
|
new RedirectField(AUTH_SESSION_QUERY_PARAM, getLoginURI(),
|
||||||
|
new TranslatableMessage("LOGIN.INFO_IDP_REDIRECT_PENDING"))
|
||||||
}))
|
}))
|
||||||
);
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public URI getLoginURI() throws GuacamoleException {
|
||||||
|
return saml.createRequest();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void shutdown() {
|
||||||
|
sessionManager.shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
@@ -0,0 +1,48 @@
|
|||||||
|
/*
|
||||||
|
* 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.saml;
|
||||||
|
|
||||||
|
import org.apache.guacamole.auth.saml.acs.AssertionConsumerServiceResource;
|
||||||
|
import org.apache.guacamole.auth.sso.SSOAuthenticationProvider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AuthenticationProvider implementation that authenticates Guacamole users
|
||||||
|
* against a SAML SSO Identity Provider (IdP). This module does not provide any
|
||||||
|
* storage for connection information, and must be layered with other modules
|
||||||
|
* for authenticated users to have access to Guacamole connections.
|
||||||
|
*/
|
||||||
|
public class SAMLAuthenticationProvider extends SSOAuthenticationProvider {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new SAMLAuthenticationProvider that authenticates users
|
||||||
|
* against a SAML IdP.
|
||||||
|
*/
|
||||||
|
public SAMLAuthenticationProvider() {
|
||||||
|
super(AuthenticationProviderService.class,
|
||||||
|
AssertionConsumerServiceResource.class,
|
||||||
|
new SAMLAuthenticationProviderModule());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getIdentifier() {
|
||||||
|
return "saml";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -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.AuthenticationSessionManager;
|
||||||
import org.apache.guacamole.auth.saml.acs.IdentifierGenerator;
|
import org.apache.guacamole.auth.saml.acs.IdentifierGenerator;
|
||||||
import org.apache.guacamole.auth.saml.acs.SAMLService;
|
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.
|
* Guice module which configures SAML-specific injections.
|
||||||
*/
|
*/
|
||||||
public class SAMLAuthenticationProviderModule extends AbstractModule {
|
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
|
@Override
|
||||||
protected void configure() {
|
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(AssertionConsumerServiceResource.class);
|
||||||
bind(AuthenticationSessionManager.class);
|
bind(AuthenticationSessionManager.class);
|
||||||
bind(ConfigurationService.class);
|
bind(ConfigurationService.class);
|
||||||
bind(IdentifierGenerator.class);
|
bind(IdentifierGenerator.class);
|
||||||
bind(SAMLService.class);
|
bind(SAMLService.class);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@@ -30,6 +30,7 @@ import javax.ws.rs.core.UriBuilder;
|
|||||||
import org.apache.guacamole.GuacamoleException;
|
import org.apache.guacamole.GuacamoleException;
|
||||||
import org.apache.guacamole.auth.saml.AuthenticationProviderService;
|
import org.apache.guacamole.auth.saml.AuthenticationProviderService;
|
||||||
import org.apache.guacamole.auth.saml.conf.ConfigurationService;
|
import org.apache.guacamole.auth.saml.conf.ConfigurationService;
|
||||||
|
import org.apache.guacamole.auth.sso.SSOResource;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
@@ -38,7 +39,7 @@ import org.slf4j.LoggerFactory;
|
|||||||
* endpoint. SAML identity providers will issue an HTTP POST to this endpoint
|
* endpoint. SAML identity providers will issue an HTTP POST to this endpoint
|
||||||
* asserting the user's identity when the user has successfully authenticated.
|
* asserting the user's identity when the user has successfully authenticated.
|
||||||
*/
|
*/
|
||||||
public class AssertionConsumerServiceResource {
|
public class AssertionConsumerServiceResource extends SSOResource {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Logger for this class.
|
* Logger for this class.
|
@@ -29,8 +29,7 @@ import java.util.stream.Collectors;
|
|||||||
import org.apache.guacamole.GuacamoleException;
|
import org.apache.guacamole.GuacamoleException;
|
||||||
import org.apache.guacamole.auth.saml.acs.AssertedIdentity;
|
import org.apache.guacamole.auth.saml.acs.AssertedIdentity;
|
||||||
import org.apache.guacamole.auth.saml.conf.ConfigurationService;
|
import org.apache.guacamole.auth.saml.conf.ConfigurationService;
|
||||||
import org.apache.guacamole.net.auth.AbstractAuthenticatedUser;
|
import org.apache.guacamole.auth.sso.user.SSOAuthenticatedUser;
|
||||||
import org.apache.guacamole.net.auth.AuthenticationProvider;
|
|
||||||
import org.apache.guacamole.net.auth.Credentials;
|
import org.apache.guacamole.net.auth.Credentials;
|
||||||
import org.apache.guacamole.token.TokenName;
|
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
|
* identity and particular set of credentials with the SAML authentication
|
||||||
* provider.
|
* provider.
|
||||||
*/
|
*/
|
||||||
public class SAMLAuthenticatedUser extends AbstractAuthenticatedUser {
|
public class SAMLAuthenticatedUser extends SSOAuthenticatedUser {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The prefix that should be prepended to all parameter tokens generated
|
* The prefix that should be prepended to all parameter tokens generated
|
||||||
@@ -53,28 +52,6 @@ public class SAMLAuthenticatedUser extends AbstractAuthenticatedUser {
|
|||||||
@Inject
|
@Inject
|
||||||
private ConfigurationService confService;
|
private ConfigurationService confService;
|
||||||
|
|
||||||
/**
|
|
||||||
* Reference to the authentication provider associated with this
|
|
||||||
* authenticated user.
|
|
||||||
*/
|
|
||||||
@Inject
|
|
||||||
private AuthenticationProvider authProvider;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The credentials provided when this user was authenticated.
|
|
||||||
*/
|
|
||||||
private Credentials credentials;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The effective groups of the authenticated user.
|
|
||||||
*/
|
|
||||||
private Set<String> effectiveGroups;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tokens associated with the authenticated user.
|
|
||||||
*/
|
|
||||||
private Map<String, String> tokens;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a Map of all parameter tokens that should be made available for
|
* Returns a Map of all parameter tokens that should be made available for
|
||||||
* substitution based on the given {@link AssertedIdentity}. The resulting
|
* 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)
|
public void init(AssertedIdentity identity, Credentials credentials)
|
||||||
throws GuacamoleException {
|
throws GuacamoleException {
|
||||||
this.credentials = credentials;
|
super.init(identity.getUsername(), credentials, getGroups(identity), getTokens(identity));
|
||||||
this.effectiveGroups = getGroups(identity);
|
|
||||||
this.tokens = getTokens(identity);
|
|
||||||
setIdentifier(identity.getUsername());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a Map of tokens associated with this authenticated user.
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
* A map of token names and values available from this user account.
|
|
||||||
*/
|
|
||||||
public Map<String, String> getTokens() {
|
|
||||||
return tokens;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public AuthenticationProvider getAuthenticationProvider() {
|
|
||||||
return authProvider;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Credentials getCredentials() {
|
|
||||||
return credentials;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Set<String> getEffectiveUserGroups() {
|
|
||||||
return effectiveGroups;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@@ -9,12 +9,25 @@
|
|||||||
"org.apache.guacamole.auth.saml.SAMLAuthenticationProvider"
|
"org.apache.guacamole.auth.saml.SAMLAuthenticationProvider"
|
||||||
],
|
],
|
||||||
|
|
||||||
|
"css" : [
|
||||||
|
"styles/sso-providers.css"
|
||||||
|
],
|
||||||
|
|
||||||
|
"html" : [
|
||||||
|
"html/sso-providers.html",
|
||||||
|
"html/sso-provider-saml.html"
|
||||||
|
],
|
||||||
|
|
||||||
"translations" : [
|
"translations" : [
|
||||||
"translations/ca.json",
|
"translations/ca.json",
|
||||||
|
"translations/de.json",
|
||||||
"translations/en.json",
|
"translations/en.json",
|
||||||
"translations/ko.json",
|
|
||||||
"translations/fr.json",
|
"translations/fr.json",
|
||||||
"translations/pt.json"
|
"translations/ja.json",
|
||||||
|
"translations/ko.json",
|
||||||
|
"translations/pt.json",
|
||||||
|
"translations/ru.json",
|
||||||
|
"translations/zh.json"
|
||||||
]
|
]
|
||||||
|
|
||||||
}
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user