GUACAMOLE-1364: Merge SSO extensions refactoring.

This commit is contained in:
James Muehlner
2021-12-03 20:35:17 -08:00
committed by GitHub
98 changed files with 871 additions and 1096 deletions

View File

@@ -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>

View File

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

View File

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

View File

@@ -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 ..."
}
}

View File

@@ -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..."
}
}

View File

@@ -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..."
}
}

View File

@@ -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..."
}
}

View File

@@ -1,7 +0,0 @@
{
"LOGIN" : {
"INFO_CAS_REDIRECT_PENDING" : "CAS認証にリダイレクトしています。"
}
}

View File

@@ -1,7 +0,0 @@
{
"LOGIN" : {
"INFO_CAS_REDIRECT_PENDING" : "기다려주십시오. CAS 인증으로 리디렉션 중..."
}
}

View File

@@ -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..."
}
}

View File

@@ -1,11 +0,0 @@
{
"DATA_SOURCE_CAS" : {
"NAME" : "Бэкенд CAS SSO"
},
"LOGIN" : {
"INFO_CAS_REDIRECT_PENDING" : "Пожалуйста, подождите. Переадресую на страницу аутентификации CAS..."
}
}

View File

@@ -1,12 +0,0 @@
{
"DATA_SOURCE_CAS" : {
"NAME" : "CAS SSO后端"
},
"LOGIN" : {
"FIELD_HEADER_TICKET" : "",
"INFO_CAS_REDIRECT_PENDING" : "请稍候正在重定向到CAS验证..."
}
}

View File

@@ -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>

View File

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

View File

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

View File

@@ -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 ..."
}
}

View File

@@ -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..."
}
}

View File

@@ -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é..."
}
}

View File

@@ -1,7 +0,0 @@
{
"LOGIN" : {
"INFO_OID_REDIRECT_PENDING" : "IDプロバイダへリダイレクトしています。"
}
}

View File

@@ -1,7 +0,0 @@
{
"LOGIN" : {
"INFO_OID_REDIRECT_PENDING" : "잠시만 기다려주십시오. ID 제공자로 리디렉션 중..."
}
}

View File

@@ -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..."
}
}

View File

@@ -1,11 +0,0 @@
{
"DATA_SOURCE_OPENID" : {
"NAME" : "Бэкенд OpenID SSO"
},
"LOGIN" : {
"INFO_REDIRECT_PENDING" : "Пожалуйста, подождите. Переадресую на страницу аутентификации..."
}
}

View File

@@ -1,12 +0,0 @@
{
"DATA_SOURCE_OPENID" : {
"NAME" : "OpenID SSO后端"
},
"LOGIN" : {
"FIELD_HEADER_ID_TOKEN" : "",
"INFO_REDIRECT_PENDING" : "请稍候,正在重定向到身份提供者..."
}
}

View File

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

View File

@@ -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 ..."
}
}

View File

@@ -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..."
}
}

View File

@@ -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é..."
}
}

View File

@@ -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..."
}
}

View File

@@ -0,0 +1,2 @@
target/
*~

View File

@@ -0,0 +1,55 @@
<?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>
</dependencies>
</project>

View File

@@ -0,0 +1,153 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.guacamole.auth.sso;
import com.google.common.collect.Iterables;
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Module;
import java.util.Arrays;
import java.util.Collections;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.auth.sso.user.SSOAuthenticatedUser;
import org.apache.guacamole.environment.Environment;
import org.apache.guacamole.environment.LocalEnvironment;
import org.apache.guacamole.net.auth.AbstractAuthenticationProvider;
import org.apache.guacamole.net.auth.AuthenticatedUser;
import org.apache.guacamole.net.auth.AuthenticationProvider;
import org.apache.guacamole.net.auth.Credentials;
import org.apache.guacamole.net.auth.TokenInjectingUserContext;
import org.apache.guacamole.net.auth.UserContext;
/**
* An AuthenticationProvider which authenticates users against an arbitrary
* SSO system. Guice dependency injection is automatically configured via
* modules provided by the implementation. Implementations will typically
* provide no storage for connections, instead relying on other installed
* extensions.
*/
public abstract class SSOAuthenticationProvider extends AbstractAuthenticationProvider {
/**
* The Guice injector.
*/
private final Injector injector;
/**
* Creates a new SSOAuthenticationProvider that authenticates users against
* an arbitrary SSO system. Guice dependency injection is automatically
* configured, with the resulting injector available to implementations via
* {@link #getInjector()}. Core authentication functions are provided by
* the given SSOAuthenticationProviderService implementation, and
* additional implementation-specific services, providers, etc. may be
* bound by specifying additional Guice modules.
*
* @param authService
* The SSOAuthenticationProviderService implementation that should be
* used for core authentication functions.
*
* @param modules
* Any additional modules that should be used when creating the Guice
* injector.
*/
public SSOAuthenticationProvider(
Class<? extends SSOAuthenticationProviderService> authService,
Module... modules) {
this(authService, Arrays.asList(modules));
}
/**
* Creates a new SSOAuthenticationProvider that authenticates users against
* an arbitrary SSO system. Guice dependency injection is automatically
* configured, with the resulting injector available to implementations via
* {@link #getInjector()}. Core authentication functions are provided by
* the given SSOAuthenticationProviderService implementation, and
* additional may be provided by specifying additional Guice modules.
*
* @param authService
* The SSOAuthenticationProviderService implementation that should be
* used for core authentication functions.
*
* @param modules
* Any additional modules that should be used when creating the Guice
* injector.
*/
public SSOAuthenticationProvider(
Class<? extends SSOAuthenticationProviderService> authService,
Iterable<? extends Module> modules) {
injector = Guice.createInjector(Iterables.concat(Collections.singletonList(new AbstractModule() {
@Override
protected void configure() {
bind(AuthenticationProvider.class).toInstance(SSOAuthenticationProvider.this);
bind(Environment.class).toInstance(LocalEnvironment.getInstance());
bind(SSOAuthenticationProviderService.class).to(authService);
}
}), modules));
}
/**
* Returns the Guice injector available for use by this implementation of
* SSOAuthenticationProvider. The returned injector has already been
* configured with all modules supplied at the time this
* SSOAuthenticationProvider was created.
*
* @return
* The Guice injector available for use by this implementation of
* SSOAuthenticationProvider.
*/
protected final Injector getInjector() {
return injector;
}
@Override
public AuthenticatedUser authenticateUser(Credentials credentials)
throws GuacamoleException {
// Attempt to authenticate user with given credentials
SSOAuthenticationProviderService authProviderService =
injector.getInstance(SSOAuthenticationProviderService.class);
return authProviderService.authenticateUser(credentials);
}
@Override
public UserContext decorate(UserContext context,
AuthenticatedUser authenticatedUser, Credentials credentials)
throws GuacamoleException {
// Only inject tokens for users authenticated by this extension
if (authenticatedUser.getAuthenticationProvider() != this)
return context;
return new TokenInjectingUserContext(context,
((SSOAuthenticatedUser) authenticatedUser).getTokens());
}
@Override
public void shutdown() {
injector.getInstance(SSOAuthenticationProviderService.class).shutdown();
}
}

View File

@@ -0,0 +1,60 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.guacamole.auth.sso;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.auth.sso.user.SSOAuthenticatedUser;
import org.apache.guacamole.net.auth.Credentials;
/**
* Service that authenticates Guacamole users by leveraging an arbitrary SSO
* service.
*/
public interface SSOAuthenticationProviderService {
/**
* Returns an SSOAuthenticatedUser representing the user authenticated by
* the given credentials. Tokens associated with the returned
* SSOAuthenticatedUser will automatically be injected into any connections
* used by that user during their session.
*
* @param credentials
* The credentials to use for authentication.
*
* @return
* An SSOAuthenticatedUser representing the user authenticated by the
* given credentials.
*
* @throws GuacamoleException
* If an error occurs while authenticating the user, or if access is
* denied.
*/
SSOAuthenticatedUser authenticateUser(Credentials credentials)
throws GuacamoleException;
/**
* Frees all resources associated with the relevant
* SSOAuthenticationProvider implementation. This function is automatically
* invoked when an implementation of SSOAuthenticationProvider is shut
* down.
*/
void shutdown();
}

View File

@@ -17,7 +17,7 @@
* under the License.
*/
package org.apache.guacamole.auth.cas.user;
package org.apache.guacamole.auth.sso.user;
import com.google.inject.Inject;
import java.util.Collections;
@@ -28,11 +28,12 @@ import org.apache.guacamole.net.auth.AuthenticationProvider;
import org.apache.guacamole.net.auth.Credentials;
/**
* An CAS-specific implementation of AuthenticatedUser, associating a
* username and particular set of credentials with the CAS authentication
* provider.
* An AuthenticatedUser whose identity has been supplied by an arbitrary SSO
* service. An SSOAuthenticatedUser may additionally be associated with a set
* of user-specific parameter tokens to be injected into any connections used
* by that user.
*/
public class CASAuthenticatedUser extends AbstractAuthenticatedUser {
public class SSOAuthenticatedUser extends AbstractAuthenticatedUser {
/**
* Reference to the authentication provider associated with this
@@ -45,60 +46,53 @@ public class CASAuthenticatedUser extends AbstractAuthenticatedUser {
* The credentials provided when this user was authenticated.
*/
private Credentials credentials;
/**
* Tokens associated with this authenticated user.
*/
private Map<String, String> tokens;
/**
* The unique identifiers of all user groups which this user is a member of.
* The groups that this user belongs to.
*/
private Set<String> effectiveGroups;
/**
* Initializes this AuthenticatedUser using the given username and
* credentials, and an empty map of parameter tokens.
*
* @param username
* The username of the user that was authenticated.
*
* @param credentials
* The credentials provided when this user was authenticated.
* Parameter tokens to be automatically injected for any connections used
* by this user.
*/
public void init(String username, Credentials credentials) {
this.init(username, credentials, Collections.emptyMap(), Collections.emptySet());
}
private Map<String, String> tokens;
/**
* Initializes this AuthenticatedUser using the given username,
* credentials, and parameter tokens.
* Initializes this SSOAuthenticatedUser, associating it with the given
* username, credentials, groups, and parameter tokens. This function must
* be invoked for every SSOAuthenticatedUser created.
*
* @param username
* The username of the user that was authenticated.
*
* @param credentials
* The credentials provided when this user was authenticated.
*
*
* @param effectiveGroups
* The groups that the authenticated user belongs to.
*
* @param tokens
* A map of all the name/value pairs that should be available
* as tokens when connections are established with this user.
* as tokens when connections are established by this user.
*/
public void init(String username, Credentials credentials,
Map<String, String> tokens, Set<String> effectiveGroups) {
Set<String> effectiveGroups, Map<String, String> tokens) {
this.credentials = credentials;
this.effectiveGroups = Collections.unmodifiableSet(effectiveGroups);
this.tokens = Collections.unmodifiableMap(tokens);
this.effectiveGroups = effectiveGroups;
setIdentifier(username.toLowerCase());
setIdentifier(username);
}
/**
* Returns a Map containing the name/value pairs that can be applied
* as parameter tokens when connections are established by the user.
*
* Returns a Map of the parameter tokens that should be automatically
* injected into connections used by this user during their session. If
* there are no parameter tokens applicable to the SSO implementation, this
* may simply be an empty map.
*
* @return
* A Map containing all of the name/value pairs that can be
* used as parameter tokens by this user.
* A map of the parameter token name/value pairs that should be
* automatically injected into connections used by this user.
*/
public Map<String, String> getTokens() {
return tokens;

View File

@@ -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 ..."
}
}

View File

@@ -1,7 +1,7 @@
{
"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..."
}
}

View File

@@ -0,0 +1,22 @@
{
"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..."
}
}

View File

@@ -0,0 +1,7 @@
{
"LOGIN" : {
"INFO_IDP_REDIRECT_PENDING" : "Veuillez patienter, redirection vers le fournisseur d'identité..."
}
}

View File

@@ -0,0 +1,7 @@
{
"LOGIN" : {
"INFO_IDP_REDIRECT_PENDING" : "IDプロバイダへリダイレクトしています。"
}
}

View File

@@ -5,7 +5,7 @@
},
"LOGIN" : {
"INFO_SAML_REDIRECT_PENDING": "잠시만 기다려주십시오. ID 제공자로 리디렉션 중..."
"INFO_IDP_REDIRECT_PENDING" : "잠시만 기다려주십시오. ID 제공자로 리디렉션 중..."
}
}

View File

@@ -0,0 +1,7 @@
{
"LOGIN" : {
"INFO_IDP_REDIRECT_PENDING" : "Por favor aguarde, redirecionando ao provedor de indentidade..."
}
}

View File

@@ -0,0 +1,15 @@
{
"DATA_SOURCE_CAS" : {
"NAME" : "Бэкенд CAS SSO"
},
"DATA_SOURCE_OPENID" : {
"NAME" : "Бэкенд OpenID SSO"
},
"LOGIN" : {
"INFO_IDP_REDIRECT_PENDING" : "Пожалуйста, подождите. Переадресую на страницу аутентификации..."
}
}

View File

@@ -0,0 +1,15 @@
{
"DATA_SOURCE_CAS" : {
"NAME" : "CAS SSO后端"
},
"DATA_SOURCE_OPENID" : {
"NAME" : "OpenID SSO后端"
},
"LOGIN" : {
"INFO_IDP_REDIRECT_PENDING" : "请稍候,正在重定向到身份提供者..."
}
}

View File

@@ -24,17 +24,17 @@
<modelVersion>4.0.0</modelVersion>
<groupId>org.apache.guacamole</groupId>
<artifactId>guacamole-auth-cas</artifactId>
<artifactId>guacamole-auth-sso-cas</artifactId>
<packaging>jar</packaging>
<version>1.3.0</version>
<name>guacamole-auth-cas</name>
<name>guacamole-auth-sso-cas</name>
<url>http://guacamole.apache.org/</url>
<parent>
<groupId>org.apache.guacamole</groupId>
<artifactId>extensions</artifactId>
<artifactId>guacamole-auth-sso</artifactId>
<version>1.3.0</version>
<relativePath>../</relativePath>
<relativePath>../../</relativePath>
</parent>
<dependencies>
@@ -43,8 +43,12 @@
<dependency>
<groupId>org.apache.guacamole</groupId>
<artifactId>guacamole-ext</artifactId>
<version>1.3.0</version>
<scope>provided</scope>
</dependency>
<!-- Core SSO support -->
<dependency>
<groupId>org.apache.guacamole</groupId>
<artifactId>guacamole-auth-sso-base</artifactId>
</dependency>
<!-- Apereo CAS Client API -->
@@ -70,16 +74,12 @@
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<!-- Jersey - JAX-RS Implementation -->
<!-- JAX-RS Annotations -->
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>jsr311-api</artifactId>
<version>1.1.1</version>
<scope>provided</scope>
</dependency>
<!-- JUnit -->

View File

@@ -30,14 +30,14 @@ import org.apache.guacamole.net.auth.credentials.GuacamoleInvalidCredentialsExce
import org.apache.guacamole.auth.cas.conf.ConfigurationService;
import org.apache.guacamole.auth.cas.form.CASTicketField;
import org.apache.guacamole.auth.cas.ticket.TicketValidationService;
import org.apache.guacamole.auth.cas.user.CASAuthenticatedUser;
import org.apache.guacamole.auth.sso.SSOAuthenticationProviderService;
import org.apache.guacamole.auth.sso.user.SSOAuthenticatedUser;
import org.apache.guacamole.language.TranslatableMessage;
/**
* Service providing convenience functions for the CAS AuthenticationProvider
* implementation.
* Service that authenticates Guacamole users by processing CAS tickets.
*/
public class AuthenticationProviderService {
public class AuthenticationProviderService implements SSOAuthenticationProviderService {
/**
* Service for retrieving CAS configuration information.
@@ -51,22 +51,8 @@ public class AuthenticationProviderService {
@Inject
private TicketValidationService ticketService;
/**
* Returns an AuthenticatedUser representing the user authenticated by the
* given credentials.
*
* @param credentials
* The credentials to use for authentication.
*
* @return
* A CASAuthenticatedUser representing the user authenticated by the
* given credentials.
*
* @throws GuacamoleException
* If an error occurs while authenticating the user, or if access is
* denied.
*/
public CASAuthenticatedUser authenticateUser(Credentials credentials)
@Override
public SSOAuthenticatedUser authenticateUser(Credentials credentials)
throws GuacamoleException {
// Pull CAS ticket from request if present
@@ -87,7 +73,7 @@ public class AuthenticationProviderService {
new CASTicketField(
confService.getAuthorizationEndpoint(),
confService.getRedirectURI(),
new TranslatableMessage("LOGIN.INFO_CAS_REDIRECT_PENDING")
new TranslatableMessage("LOGIN.INFO_IDP_REDIRECT_PENDING")
)
}))
@@ -95,4 +81,9 @@ public class AuthenticationProviderService {
}
@Override
public void shutdown() {
// Nothing to clean up
}
}

View File

@@ -0,0 +1,45 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.guacamole.auth.cas;
import org.apache.guacamole.auth.sso.SSOAuthenticationProvider;
/**
* 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, new CASAuthenticationProviderModule());
}
@Override
public String getIdentifier() {
return "cas";
}
}

View File

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

View File

@@ -41,7 +41,7 @@ import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.GuacamoleSecurityException;
import org.apache.guacamole.GuacamoleServerException;
import org.apache.guacamole.auth.cas.conf.ConfigurationService;
import org.apache.guacamole.auth.cas.user.CASAuthenticatedUser;
import org.apache.guacamole.auth.sso.user.SSOAuthenticatedUser;
import org.apache.guacamole.net.auth.Credentials;
import org.apache.guacamole.token.TokenName;
import org.jasig.cas.client.authentication.AttributePrincipal;
@@ -77,7 +77,7 @@ public class TicketValidationService {
* Provider for AuthenticatedUser objects.
*/
@Inject
private Provider<CASAuthenticatedUser> authenticatedUserProvider;
private Provider<SSOAuthenticatedUser> authenticatedUserProvider;
/**
* Converts the given CAS attribute value object (whose type is variable)
@@ -132,7 +132,7 @@ public class TicketValidationService {
* If the ID ticket is not valid or guacamole.properties could
* not be parsed.
*/
public CASAuthenticatedUser validateTicket(String ticket,
public SSOAuthenticatedUser validateTicket(String ticket,
Credentials credentials) throws GuacamoleException {
// Create a ticket validator that uses the configured CAS URL
@@ -160,6 +160,9 @@ public class TicketValidationService {
if (username == null)
throw new GuacamoleSecurityException("No username provided by CAS.");
// Canonicalize username as lowercase
username = username.toLowerCase();
// Update credentials with username provided by CAS for sake of
// ${GUAC_USERNAME} token
credentials.setUsername(username);
@@ -196,8 +199,8 @@ public class TicketValidationService {
}
});
CASAuthenticatedUser authenticatedUser = authenticatedUserProvider.get();
authenticatedUser.init(username, credentials, tokens, effectiveGroups);
SSOAuthenticatedUser authenticatedUser = authenticatedUserProvider.get();
authenticatedUser.init(username, credentials, effectiveGroups, tokens);
return authenticatedUser;
}

View File

@@ -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>

View File

@@ -21,33 +21,53 @@
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 -->
<id>dist</id>
<baseDirectory>${project.parent.artifactId}-${project.parent.version}</baseDirectory>
<!-- Output .tar.gz -->
<formats>
<format>tar.gz</format>
</formats>
<!-- Include licenses and extension .jar -->
<fileSets>
<!-- Include extension .jars -->
<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>
<outputDirectory></outputDirectory>
<directory>target/licenses</directory>
</fileSet>
<!-- Include extension .jar -->
<fileSet>
<directory>target</directory>
<outputDirectory></outputDirectory>
<includes>
<include>*.jar</include>
</includes>
</fileSet>
</fileSets>
</assembly>

View File

@@ -24,17 +24,17 @@
<modelVersion>4.0.0</modelVersion>
<groupId>org.apache.guacamole</groupId>
<artifactId>guacamole-auth-openid</artifactId>
<artifactId>guacamole-auth-sso-openid</artifactId>
<packaging>jar</packaging>
<version>1.3.0</version>
<name>guacamole-auth-openid</name>
<name>guacamole-auth-sso-openid</name>
<url>http://guacamole.apache.org/</url>
<parent>
<groupId>org.apache.guacamole</groupId>
<artifactId>extensions</artifactId>
<artifactId>guacamole-auth-sso</artifactId>
<version>1.3.0</version>
<relativePath>../</relativePath>
<relativePath>../../</relativePath>
</parent>
<build>
@@ -94,8 +94,12 @@
<dependency>
<groupId>org.apache.guacamole</groupId>
<artifactId>guacamole-ext</artifactId>
<version>1.3.0</version>
<scope>provided</scope>
</dependency>
<!-- Core SSO support -->
<dependency>
<groupId>org.apache.guacamole</groupId>
<artifactId>guacamole-auth-sso-base</artifactId>
</dependency>
<!-- Java implementation of JOSE (jose.4.j) -->
@@ -115,16 +119,12 @@
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<!-- Jersey - JAX-RS Implementation -->
<!-- JAX-RS Annotations -->
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>jsr311-api</artifactId>
<version>1.1.1</version>
<scope>provided</scope>
</dependency>
</dependencies>

View File

@@ -22,33 +22,27 @@ package org.apache.guacamole.auth.openid;
import com.google.inject.Inject;
import com.google.inject.Provider;
import java.util.Arrays;
import java.util.Collections;
import java.util.Set;
import javax.servlet.http.HttpServletRequest;
import org.apache.guacamole.auth.openid.conf.ConfigurationService;
import org.apache.guacamole.auth.openid.form.TokenField;
import org.apache.guacamole.auth.openid.token.NonceService;
import org.apache.guacamole.auth.openid.token.TokenValidationService;
import org.apache.guacamole.auth.openid.user.AuthenticatedUser;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.auth.sso.SSOAuthenticationProviderService;
import org.apache.guacamole.auth.sso.user.SSOAuthenticatedUser;
import org.apache.guacamole.form.Field;
import org.apache.guacamole.language.TranslatableMessage;
import org.apache.guacamole.net.auth.Credentials;
import org.apache.guacamole.net.auth.credentials.CredentialsInfo;
import org.apache.guacamole.net.auth.credentials.GuacamoleInvalidCredentialsException;
import org.jose4j.jwt.JwtClaims;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Service providing convenience functions for the OpenID AuthenticationProvider
* implementation.
* Service that authenticates Guacamole users by processing OpenID tokens.
*/
public class AuthenticationProviderService {
/**
* Logger for this class.
*/
private final Logger logger = LoggerFactory.getLogger(AuthenticationProviderService.class);
public class AuthenticationProviderService implements SSOAuthenticationProviderService {
/**
* Service for retrieving OpenID configuration information.
@@ -72,24 +66,10 @@ public class AuthenticationProviderService {
* Provider for AuthenticatedUser objects.
*/
@Inject
private Provider<AuthenticatedUser> authenticatedUserProvider;
private Provider<SSOAuthenticatedUser> authenticatedUserProvider;
/**
* Returns an AuthenticatedUser representing the user authenticated by the
* given credentials.
*
* @param credentials
* The credentials to use for authentication.
*
* @return
* An AuthenticatedUser representing the user authenticated by the
* given credentials.
*
* @throws GuacamoleException
* If an error occurs while authenticating the user, or if access is
* denied.
*/
public AuthenticatedUser authenticateUser(Credentials credentials)
@Override
public SSOAuthenticatedUser authenticateUser(Credentials credentials)
throws GuacamoleException {
String username = null;
@@ -113,8 +93,8 @@ public class AuthenticationProviderService {
if (username != null) {
// Create corresponding authenticated user
AuthenticatedUser authenticatedUser = authenticatedUserProvider.get();
authenticatedUser.init(username, credentials, groups);
SSOAuthenticatedUser authenticatedUser = authenticatedUserProvider.get();
authenticatedUser.init(username, credentials, groups, Collections.emptyMap());
return authenticatedUser;
}
@@ -131,7 +111,7 @@ public class AuthenticationProviderService {
confService.getClientID(),
confService.getRedirectURI(),
nonceService.generate(confService.getMaxNonceValidity() * 60000L),
new TranslatableMessage("LOGIN.INFO_OID_REDIRECT_PENDING")
new TranslatableMessage("LOGIN.INFO_IDP_REDIRECT_PENDING")
)
}))
@@ -139,4 +119,9 @@ public class AuthenticationProviderService {
}
@Override
public void shutdown() {
// Nothing to clean up
}
}

View File

@@ -19,12 +19,7 @@
package org.apache.guacamole.auth.openid;
import com.google.inject.Guice;
import com.google.inject.Injector;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.net.auth.AbstractAuthenticationProvider;
import org.apache.guacamole.net.auth.AuthenticatedUser;
import org.apache.guacamole.net.auth.Credentials;
import org.apache.guacamole.auth.sso.SSOAuthenticationProvider;
/**
* Guacamole authentication backend which authenticates users using an
@@ -32,29 +27,14 @@ import org.apache.guacamole.net.auth.Credentials;
* provided - only authentication. Storage must be provided by some other
* extension.
*/
public class OpenIDAuthenticationProvider extends AbstractAuthenticationProvider {
/**
* Injector which will manage the object graph of this authentication
* provider.
*/
private final Injector injector;
public class OpenIDAuthenticationProvider extends SSOAuthenticationProvider {
/**
* Creates a new OpenIDAuthenticationProvider that authenticates users
* against an OpenID service.
*
* @throws GuacamoleException
* If a required property is missing, or an error occurs while parsing
* a property.
*/
public OpenIDAuthenticationProvider() throws GuacamoleException {
// Set up Guice injector.
injector = Guice.createInjector(
new OpenIDAuthenticationProviderModule(this)
);
public OpenIDAuthenticationProvider() {
super(AuthenticationProviderService.class, new OpenIDAuthenticationProviderModule());
}
@Override
@@ -62,14 +42,4 @@ public class OpenIDAuthenticationProvider extends AbstractAuthenticationProvider
return "openid";
}
@Override
public AuthenticatedUser authenticateUser(Credentials credentials)
throws GuacamoleException {
// Attempt to authenticate user with given credentials
AuthenticationProviderService authProviderService = injector.getInstance(AuthenticationProviderService.class);
return authProviderService.authenticateUser(credentials);
}
}

View File

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

View File

@@ -0,0 +1 @@
src/main/resources/html/*.html

View File

@@ -24,17 +24,17 @@
<modelVersion>4.0.0</modelVersion>
<groupId>org.apache.guacamole</groupId>
<artifactId>guacamole-auth-saml</artifactId>
<artifactId>guacamole-auth-sso-saml</artifactId>
<packaging>jar</packaging>
<version>1.3.0</version>
<name>guacamole-auth-saml</name>
<name>guacamole-auth-sso-saml</name>
<url>http://guacamole.apache.org/</url>
<parent>
<groupId>org.apache.guacamole</groupId>
<artifactId>extensions</artifactId>
<artifactId>guacamole-auth-sso</artifactId>
<version>1.3.0</version>
<relativePath>../</relativePath>
<relativePath>../../</relativePath>
</parent>
<dependencies>
@@ -43,8 +43,12 @@
<dependency>
<groupId>org.apache.guacamole</groupId>
<artifactId>guacamole-ext</artifactId>
<version>1.3.0</version>
<scope>provided</scope>
</dependency>
<!-- Core SSO support -->
<dependency>
<groupId>org.apache.guacamole</groupId>
<artifactId>guacamole-auth-sso-base</artifactId>
</dependency>
<!-- Guice -->
@@ -57,16 +61,12 @@
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<!-- Jersey - JAX-RS Implementation -->
<!-- JAX-RS Annotations -->
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>jsr311-api</artifactId>
<version>1.1.1</version>
<scope>provided</scope>
</dependency>
<!-- OneLogin SAML Library -->

View File

@@ -29,10 +29,10 @@ import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.auth.saml.acs.AssertedIdentity;
import org.apache.guacamole.auth.saml.acs.AuthenticationSessionManager;
import org.apache.guacamole.auth.saml.acs.SAMLService;
import org.apache.guacamole.auth.sso.SSOAuthenticationProviderService;
import org.apache.guacamole.form.Field;
import org.apache.guacamole.form.RedirectField;
import org.apache.guacamole.language.TranslatableMessage;
import org.apache.guacamole.net.auth.AuthenticatedUser;
import org.apache.guacamole.net.auth.Credentials;
import org.apache.guacamole.net.auth.credentials.CredentialsInfo;
import org.apache.guacamole.net.auth.credentials.GuacamoleInsufficientCredentialsException;
@@ -41,7 +41,7 @@ import org.apache.guacamole.net.auth.credentials.GuacamoleInsufficientCredential
* Service that authenticates Guacamole users by processing the responses of
* SAML identity providers.
*/
public class AuthenticationProviderService {
public class AuthenticationProviderService implements SSOAuthenticationProviderService {
/**
* The name of the query parameter that identifies an active authentication
@@ -67,22 +67,8 @@ public class AuthenticationProviderService {
@Inject
private SAMLService saml;
/**
* Returns an AuthenticatedUser representing the user authenticated by the
* given credentials.
*
* @param credentials
* The credentials to use for authentication.
*
* @return
* An AuthenticatedUser representing the user authenticated by the
* given credentials.
*
* @throws GuacamoleException
* If an error occurs while authenticating the user, or if access is
* denied.
*/
public AuthenticatedUser authenticateUser(Credentials credentials)
@Override
public SAMLAuthenticatedUser authenticateUser(Credentials credentials)
throws GuacamoleException {
// No authentication can be attempted without a corresponding HTTP
@@ -110,10 +96,16 @@ public class AuthenticationProviderService {
URI authUri = saml.createRequest();
throw new GuacamoleInsufficientCredentialsException("Redirecting to SAML IdP.",
new CredentialsInfo(Arrays.asList(new Field[] {
new RedirectField("samlRedirect", authUri, new TranslatableMessage("LOGIN.INFO_SAML_REDIRECT_PENDING"))
new RedirectField(AUTH_SESSION_QUERY_PARAM, authUri,
new TranslatableMessage("LOGIN.INFO_IDP_REDIRECT_PENDING"))
}))
);
}
@Override
public void shutdown() {
sessionManager.shutdown();
}
}

View File

@@ -0,0 +1,52 @@
/*
* 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.GuacamoleException;
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, new SAMLAuthenticationProviderModule());
}
@Override
public String getIdentifier() {
return "saml";
}
@Override
public Object getResource() throws GuacamoleException {
return getInjector().getInstance(AssertionConsumerServiceResource.class);
}
}

View File

@@ -25,57 +25,19 @@ import org.apache.guacamole.auth.saml.acs.AssertionConsumerServiceResource;
import org.apache.guacamole.auth.saml.acs.AuthenticationSessionManager;
import org.apache.guacamole.auth.saml.acs.IdentifierGenerator;
import org.apache.guacamole.auth.saml.acs.SAMLService;
import org.apache.guacamole.environment.Environment;
import org.apache.guacamole.environment.LocalEnvironment;
import org.apache.guacamole.net.auth.AuthenticationProvider;
/**
* Guice module which configures SAML-specific injections.
*/
public class SAMLAuthenticationProviderModule extends AbstractModule {
/**
* Guacamole server environment.
*/
private final Environment environment;
/**
* A reference to the SAMLAuthenticationProvider on behalf of which this
* module has configured injection.
*/
private final AuthenticationProvider authProvider;
/**
* Creates a new SAML authentication provider module which configures
* injection for the SAMLAuthenticationProvider.
*
* @param authProvider
* The AuthenticationProvider for which injection is being configured.
*/
public SAMLAuthenticationProviderModule(AuthenticationProvider authProvider) {
// Get local environment
this.environment = LocalEnvironment.getInstance();
// Store associated auth provider
this.authProvider = authProvider;
}
@Override
protected void configure() {
// Bind core implementations of guacamole-ext classes
bind(AuthenticationProvider.class).toInstance(authProvider);
bind(Environment.class).toInstance(environment);
// Bind SAML-specific services
bind(AssertionConsumerServiceResource.class);
bind(AuthenticationSessionManager.class);
bind(ConfigurationService.class);
bind(IdentifierGenerator.class);
bind(SAMLService.class);
}
}

View File

@@ -29,8 +29,7 @@ import java.util.stream.Collectors;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.auth.saml.acs.AssertedIdentity;
import org.apache.guacamole.auth.saml.conf.ConfigurationService;
import org.apache.guacamole.net.auth.AbstractAuthenticatedUser;
import org.apache.guacamole.net.auth.AuthenticationProvider;
import org.apache.guacamole.auth.sso.user.SSOAuthenticatedUser;
import org.apache.guacamole.net.auth.Credentials;
import org.apache.guacamole.token.TokenName;
@@ -39,7 +38,7 @@ import org.apache.guacamole.token.TokenName;
* identity and particular set of credentials with the SAML authentication
* provider.
*/
public class SAMLAuthenticatedUser extends AbstractAuthenticatedUser {
public class SAMLAuthenticatedUser extends SSOAuthenticatedUser {
/**
* The prefix that should be prepended to all parameter tokens generated
@@ -53,28 +52,6 @@ public class SAMLAuthenticatedUser extends AbstractAuthenticatedUser {
@Inject
private ConfigurationService confService;
/**
* Reference to the authentication provider associated with this
* authenticated user.
*/
@Inject
private AuthenticationProvider authProvider;
/**
* The credentials provided when this user was authenticated.
*/
private Credentials credentials;
/**
* The effective groups of the authenticated user.
*/
private Set<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
* substitution based on the given {@link AssertedIdentity}. The resulting
@@ -144,35 +121,7 @@ public class SAMLAuthenticatedUser extends AbstractAuthenticatedUser {
*/
public void init(AssertedIdentity identity, Credentials credentials)
throws GuacamoleException {
this.credentials = credentials;
this.effectiveGroups = getGroups(identity);
this.tokens = getTokens(identity);
setIdentifier(identity.getUsername());
super.init(identity.getUsername(), credentials, getGroups(identity), getTokens(identity));
}
/**
* Returns a Map of tokens associated with this authenticated user.
*
* @return
* A map of token names and values available from this user account.
*/
public Map<String, String> getTokens() {
return tokens;
}
@Override
public AuthenticationProvider getAuthenticationProvider() {
return authProvider;
}
@Override
public Credentials getCredentials() {
return credentials;
}
@Override
public Set<String> getEffectiveUserGroups() {
return effectiveGroups;
}
}

View File

@@ -11,10 +11,14 @@
"translations" : [
"translations/ca.json",
"translations/de.json",
"translations/en.json",
"translations/ko.json",
"translations/fr.json",
"translations/pt.json"
"translations/ja.json",
"translations/ko.json",
"translations/pt.json",
"translations/ru.json",
"translations/zh.json"
]
}

View File

@@ -0,0 +1,92 @@
<?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</artifactId>
<packaging>pom</packaging>
<version>1.3.0</version>
<name>guacamole-auth-sso</name>
<url>http://guacamole.apache.org/</url>
<parent>
<groupId>org.apache.guacamole</groupId>
<artifactId>extensions</artifactId>
<version>1.3.0</version>
<relativePath>../</relativePath>
</parent>
<modules>
<!-- Distribution .tar.gz -->
<module>modules/guacamole-auth-sso-dist</module>
<!-- Base classes -->
<module>modules/guacamole-auth-sso-base</module>
<!-- SSO implementations -->
<module>modules/guacamole-auth-sso-cas</module>
<module>modules/guacamole-auth-sso-openid</module>
<module>modules/guacamole-auth-sso-saml</module>
</modules>
<dependencyManagement>
<dependencies>
<!-- Guacamole Extension API -->
<dependency>
<groupId>org.apache.guacamole</groupId>
<artifactId>guacamole-ext</artifactId>
<version>1.3.0</version>
<scope>provided</scope>
</dependency>
<!-- Core SSO support -->
<dependency>
<groupId>org.apache.guacamole</groupId>
<artifactId>guacamole-auth-sso-base</artifactId>
<version>1.3.0</version>
</dependency>
<!-- Java servlet API -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<!-- JAX-RS Annotations -->
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>jsr311-api</artifactId>
<version>1.1.1</version>
<scope>provided</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>

View File

@@ -40,15 +40,13 @@
<modules>
<!-- Authentication extensions -->
<module>guacamole-auth-cas</module>
<module>guacamole-auth-duo</module>
<module>guacamole-auth-header</module>
<module>guacamole-auth-jdbc</module>
<module>guacamole-auth-json</module>
<module>guacamole-auth-ldap</module>
<module>guacamole-auth-openid</module>
<module>guacamole-auth-quickconnect</module>
<module>guacamole-auth-saml</module>
<module>guacamole-auth-sso</module>
<module>guacamole-auth-totp</module>
</modules>

View File

@@ -110,6 +110,17 @@ tar -xz \
echo "Downloading PostgreSQL JDBC driver ..."
curl -L "https://jdbc.postgresql.org/download/postgresql-9.4-1201.jdbc41.jar" > "$DESTINATION/postgresql/postgresql-9.4-1201.jdbc41.jar"
#
# Copy SSO auth extensions
#
tar -xzf extensions/guacamole-auth-sso/modules/guacamole-auth-sso-dist/target/*.tar.gz \
-C "$DESTINATION" \
--wildcards \
--no-anchored \
--strip-components=1 \
"*.jar"
#
# Copy LDAP auth extension and schema modifications
#
@@ -132,15 +143,6 @@ if [ -f extensions/guacamole-auth-radius/target/guacamole-auth-radius*.jar ]; th
cp extensions/guacamole-auth-radius/target/guacamole-auth-radius*.jar "$DESTINATION/radius"
fi
#
# Copy OPENID auth extension and schema modifications
#
if [ -f extensions/guacamole-auth-openid/target/guacamole-auth-openid*.jar ]; then
mkdir -p "$DESTINATION/openid"
cp extensions/guacamole-auth-openid/target/guacamole-auth-openid*.jar "$DESTINATION/openid"
fi
#
# Copy TOTP auth extension if it was built
#
@@ -174,21 +176,6 @@ if [ -f extensions/guacamole-auth-header/target/guacamole-auth-header*.jar ]; th
cp extensions/guacamole-auth-header/target/guacamole-auth-header*.jar "$DESTINATION/header"
fi
#
# Copy CAS auth extension if it was built
#
if [ -f extensions/guacamole-auth-cas/target/*.tar.gz ]; then
mkdir -p "$DESTINATION/cas"
tar -xzf extensions/guacamole-auth-cas/target/*.tar.gz \
-C "$DESTINATION/cas/" \
--wildcards \
--no-anchored \
--no-wildcards-match-slash \
--strip-components=1 \
"*.jar"
fi
#
# Copy json auth extension if it was built
#