From b6696b9dba39423a54e77287df275ebe8c4add0d Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Fri, 3 Dec 2021 21:12:06 -0800 Subject: [PATCH] GUACAMOLE-1364: Extract common SSO resource for IdP redirect. --- .../auth/sso/SSOAuthenticationProvider.java | 11 ++++- .../sso/SSOAuthenticationProviderService.java | 14 ++++++ .../guacamole/auth/sso/SSOResource.java | 13 +++++- .../cas/AuthenticationProviderService.java | 12 +----- .../auth/cas/CASAuthenticationProvider.java | 3 +- .../guacamole/auth/cas/CASResource.java | 43 ------------------- .../openid/AuthenticationProviderService.java | 12 +----- .../openid/OpenIDAuthenticationProvider.java | 3 +- .../guacamole/auth/openid/OpenIDResource.java | 43 ------------------- .../saml/AuthenticationProviderService.java | 8 +++- .../acs/AssertionConsumerServiceResource.java | 7 +-- 11 files changed, 48 insertions(+), 121 deletions(-) delete mode 100644 extensions/guacamole-auth-sso/modules/guacamole-auth-sso-cas/src/main/java/org/apache/guacamole/auth/cas/CASResource.java delete mode 100644 extensions/guacamole-auth-sso/modules/guacamole-auth-sso-openid/src/main/java/org/apache/guacamole/auth/openid/OpenIDResource.java diff --git a/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-base/src/main/java/org/apache/guacamole/auth/sso/SSOAuthenticationProvider.java b/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-base/src/main/java/org/apache/guacamole/auth/sso/SSOAuthenticationProvider.java index e6846a059..c5b07fabc 100644 --- a/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-base/src/main/java/org/apache/guacamole/auth/sso/SSOAuthenticationProvider.java +++ b/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-base/src/main/java/org/apache/guacamole/auth/sso/SSOAuthenticationProvider.java @@ -24,6 +24,7 @@ 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; @@ -109,10 +110,18 @@ public abstract class SSOAuthenticationProvider extends AbstractAuthenticationPr @Override protected void configure() { + bind(AuthenticationProvider.class).toInstance(SSOAuthenticationProvider.this); bind(Environment.class).toInstance(LocalEnvironment.getInstance()); bind(SSOAuthenticationProviderService.class).to(authService); - bind(SSOResource.class).to(ssoResource); + + // Bind custom SSOResource implementation if different from + // core implementation (explicitly binding SSOResource as + // SSOResource results in a runtime error from Guice otherwise) + LinkedBindingBuilder resourceBinding = bind(SSOResource.class); + if (ssoResource != SSOResource.class) + resourceBinding.to(ssoResource); + } }), modules)); diff --git a/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-base/src/main/java/org/apache/guacamole/auth/sso/SSOAuthenticationProviderService.java b/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-base/src/main/java/org/apache/guacamole/auth/sso/SSOAuthenticationProviderService.java index cd2d424b2..d35c07dab 100644 --- a/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-base/src/main/java/org/apache/guacamole/auth/sso/SSOAuthenticationProviderService.java +++ b/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-base/src/main/java/org/apache/guacamole/auth/sso/SSOAuthenticationProviderService.java @@ -19,6 +19,7 @@ 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; @@ -49,6 +50,19 @@ public interface SSOAuthenticationProviderService { 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 diff --git a/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-base/src/main/java/org/apache/guacamole/auth/sso/SSOResource.java b/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-base/src/main/java/org/apache/guacamole/auth/sso/SSOResource.java index ce61db0b1..91bd39ba2 100644 --- a/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-base/src/main/java/org/apache/guacamole/auth/sso/SSOResource.java +++ b/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-base/src/main/java/org/apache/guacamole/auth/sso/SSOResource.java @@ -18,6 +18,7 @@ */ 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; @@ -28,7 +29,13 @@ import org.apache.guacamole.GuacamoleException; * the applicable identity provider. Implementations may also provide * additional resources and endpoints beneath this resource as needed. */ -public interface SSOResource { +public class SSOResource { + + /** + * Service for authenticating users using CAS. + */ + @Inject + private SSOAuthenticationProviderService authService; /** * Redirects the user to the relevant identity provider. If the SSO @@ -44,6 +51,8 @@ public interface SSOResource { */ @GET @Path("login") - public Response redirectToIdentityProvider() throws GuacamoleException; + public Response redirectToIdentityProvider() throws GuacamoleException { + return Response.seeOther(authService.getLoginURI()).build(); + } } diff --git a/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-cas/src/main/java/org/apache/guacamole/auth/cas/AuthenticationProviderService.java b/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-cas/src/main/java/org/apache/guacamole/auth/cas/AuthenticationProviderService.java index 62eec8a64..f1e393d96 100644 --- a/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-cas/src/main/java/org/apache/guacamole/auth/cas/AuthenticationProviderService.java +++ b/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-cas/src/main/java/org/apache/guacamole/auth/cas/AuthenticationProviderService.java @@ -90,17 +90,7 @@ public class AuthenticationProviderService implements SSOAuthenticationProviderS } - /** - * Returns the full URI of the CAS login endpoint to which a user must be - * redirected in order to authenticate and receive a CAS ticket. - * - * @return - * The full URI of the CAS login endpoint. - * - * @throws GuacamoleException - * If configuration information required for generating the login URI - * cannot be read. - */ + @Override public URI getLoginURI() throws GuacamoleException { return UriBuilder.fromUri(confService.getAuthorizationEndpoint()) .path(CAS_LOGIN_URI) diff --git a/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-cas/src/main/java/org/apache/guacamole/auth/cas/CASAuthenticationProvider.java b/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-cas/src/main/java/org/apache/guacamole/auth/cas/CASAuthenticationProvider.java index 225b230d0..2b542fc9f 100644 --- a/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-cas/src/main/java/org/apache/guacamole/auth/cas/CASAuthenticationProvider.java +++ b/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-cas/src/main/java/org/apache/guacamole/auth/cas/CASAuthenticationProvider.java @@ -20,6 +20,7 @@ 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 @@ -35,7 +36,7 @@ public class CASAuthenticationProvider extends SSOAuthenticationProvider { */ public CASAuthenticationProvider() { super(AuthenticationProviderService.class, - CASResource.class, new CASAuthenticationProviderModule()); + SSOResource.class, new CASAuthenticationProviderModule()); } @Override diff --git a/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-cas/src/main/java/org/apache/guacamole/auth/cas/CASResource.java b/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-cas/src/main/java/org/apache/guacamole/auth/cas/CASResource.java deleted file mode 100644 index 74079f985..000000000 --- a/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-cas/src/main/java/org/apache/guacamole/auth/cas/CASResource.java +++ /dev/null @@ -1,43 +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.Inject; -import javax.ws.rs.core.Response; -import org.apache.guacamole.GuacamoleException; -import org.apache.guacamole.auth.sso.SSOResource; - -/** - * REST API resource that automatically redirects users to the CAS login - * endpoint. - */ -public class CASResource implements SSOResource { - - /** - * Service for authenticating users using CAS. - */ - @Inject - private AuthenticationProviderService authService; - - @Override - public Response redirectToIdentityProvider() throws GuacamoleException { - return Response.seeOther(authService.getLoginURI()).build(); - } - -} diff --git a/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-openid/src/main/java/org/apache/guacamole/auth/openid/AuthenticationProviderService.java b/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-openid/src/main/java/org/apache/guacamole/auth/openid/AuthenticationProviderService.java index 3320d5b1f..23ac815dc 100644 --- a/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-openid/src/main/java/org/apache/guacamole/auth/openid/AuthenticationProviderService.java +++ b/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-openid/src/main/java/org/apache/guacamole/auth/openid/AuthenticationProviderService.java @@ -120,17 +120,7 @@ public class AuthenticationProviderService implements SSOAuthenticationProviderS } - /** - * Returns the full URI of the OpenID login endpoint to which a user must - * be redirected in order to authenticate and receive an OpenID token. - * - * @return - * The full URI of the OpenID login endpoint, including unique nonce. - * - * @throws GuacamoleException - * If configuration information required for generating the login URI - * cannot be read. - */ + @Override public URI getLoginURI() throws GuacamoleException { return UriBuilder.fromUri(confService.getAuthorizationEndpoint()) .queryParam("scope", confService.getScope()) diff --git a/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-openid/src/main/java/org/apache/guacamole/auth/openid/OpenIDAuthenticationProvider.java b/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-openid/src/main/java/org/apache/guacamole/auth/openid/OpenIDAuthenticationProvider.java index 49b7da86f..a760854a6 100644 --- a/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-openid/src/main/java/org/apache/guacamole/auth/openid/OpenIDAuthenticationProvider.java +++ b/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-openid/src/main/java/org/apache/guacamole/auth/openid/OpenIDAuthenticationProvider.java @@ -20,6 +20,7 @@ package org.apache.guacamole.auth.openid; import org.apache.guacamole.auth.sso.SSOAuthenticationProvider; +import org.apache.guacamole.auth.sso.SSOResource; /** * Guacamole authentication backend which authenticates users using an @@ -34,7 +35,7 @@ public class OpenIDAuthenticationProvider extends SSOAuthenticationProvider { * against an OpenID service. */ public OpenIDAuthenticationProvider() { - super(AuthenticationProviderService.class, OpenIDResource.class, + super(AuthenticationProviderService.class, SSOResource.class, new OpenIDAuthenticationProviderModule()); } diff --git a/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-openid/src/main/java/org/apache/guacamole/auth/openid/OpenIDResource.java b/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-openid/src/main/java/org/apache/guacamole/auth/openid/OpenIDResource.java deleted file mode 100644 index e47cf4c17..000000000 --- a/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-openid/src/main/java/org/apache/guacamole/auth/openid/OpenIDResource.java +++ /dev/null @@ -1,43 +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.Inject; -import javax.ws.rs.core.Response; -import org.apache.guacamole.GuacamoleException; -import org.apache.guacamole.auth.sso.SSOResource; - -/** - * REST API resource that automatically redirects users to the OpenID identity - * provider. - */ -public class OpenIDResource implements SSOResource { - - /** - * Service for authenticating users using OpenID. - */ - @Inject - private AuthenticationProviderService authService; - - @Override - public Response redirectToIdentityProvider() throws GuacamoleException { - return Response.seeOther(authService.getLoginURI()).build(); - } - -} diff --git a/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-saml/src/main/java/org/apache/guacamole/auth/saml/AuthenticationProviderService.java b/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-saml/src/main/java/org/apache/guacamole/auth/saml/AuthenticationProviderService.java index 5a1e15881..cdd53dec6 100644 --- a/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-saml/src/main/java/org/apache/guacamole/auth/saml/AuthenticationProviderService.java +++ b/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-saml/src/main/java/org/apache/guacamole/auth/saml/AuthenticationProviderService.java @@ -95,16 +95,20 @@ public class AuthenticationProviderService implements SSOAuthenticationProviderS // Redirect to SAML IdP if no SAML identity is associated with the // Guacamole authentication request - URI authUri = saml.createRequest(); throw new GuacamoleInvalidCredentialsException("Redirecting to SAML IdP.", new CredentialsInfo(Arrays.asList(new Field[] { - new RedirectField(AUTH_SESSION_QUERY_PARAM, authUri, + 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(); diff --git a/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-saml/src/main/java/org/apache/guacamole/auth/saml/acs/AssertionConsumerServiceResource.java b/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-saml/src/main/java/org/apache/guacamole/auth/saml/acs/AssertionConsumerServiceResource.java index 5c75feeca..e316b3868 100644 --- a/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-saml/src/main/java/org/apache/guacamole/auth/saml/acs/AssertionConsumerServiceResource.java +++ b/extensions/guacamole-auth-sso/modules/guacamole-auth-sso-saml/src/main/java/org/apache/guacamole/auth/saml/acs/AssertionConsumerServiceResource.java @@ -39,7 +39,7 @@ import org.slf4j.LoggerFactory; * endpoint. SAML identity providers will issue an HTTP POST to this endpoint * asserting the user's identity when the user has successfully authenticated. */ -public class AssertionConsumerServiceResource implements SSOResource { +public class AssertionConsumerServiceResource extends SSOResource { /** * Logger for this class. @@ -64,11 +64,6 @@ public class AssertionConsumerServiceResource implements SSOResource { @Inject private SAMLService saml; - @Override - public Response redirectToIdentityProvider() throws GuacamoleException { - return Response.seeOther(saml.createRequest()).build(); - } - /** * Processes the SAML response submitted by the SAML IdP via an HTTP POST. * If SSO has been successful, the user is redirected back to Guacamole to