mirror of
https://github.com/gyurix1968/guacamole-client.git
synced 2025-09-06 13:17:41 +00:00
GUACAMOLE-1364: Merge functionality to allow traditional username/password or SSO.
This commit is contained in:
@@ -0,0 +1 @@
|
||||
src/main/resources/html/*.html
|
||||
|
@@ -50,6 +50,12 @@
|
||||
<artifactId>guice</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- JAX-RS Annotations -->
|
||||
<dependency>
|
||||
<groupId>javax.ws.rs</groupId>
|
||||
<artifactId>jsr311-api</artifactId>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
|
@@ -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;
|
||||
@@ -64,14 +65,20 @@ public abstract class SSOAuthenticationProvider extends AbstractAuthenticationPr
|
||||
* 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, Arrays.asList(modules));
|
||||
this(authService, ssoResource, Arrays.asList(modules));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -86,20 +93,35 @@ public abstract class SSOAuthenticationProvider extends AbstractAuthenticationPr
|
||||
* 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));
|
||||
@@ -145,6 +167,11 @@ public abstract class SSOAuthenticationProvider extends AbstractAuthenticationPr
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public SSOResource getResource() {
|
||||
return getInjector().getInstance(SSOResource.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shutdown() {
|
||||
injector.getInstance(SSOAuthenticationProviderService.class).shutdown();
|
||||
|
@@ -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
|
||||
|
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.guacamole.auth.sso;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.Path;
|
||||
import org.apache.guacamole.GuacamoleException;
|
||||
|
||||
/**
|
||||
* REST API resource that provides allows the user to be manually redirected to
|
||||
* the applicable identity provider. Implementations may also provide
|
||||
* additional resources and endpoints beneath this resource as needed.
|
||||
*/
|
||||
public class SSOResource {
|
||||
|
||||
/**
|
||||
* Service for authenticating users using CAS.
|
||||
*/
|
||||
@Inject
|
||||
private SSOAuthenticationProviderService authService;
|
||||
|
||||
/**
|
||||
* Redirects the user to the relevant identity provider. If the SSO
|
||||
* extension defining this resource is not the primary extension, and thus
|
||||
* the user will not be automatically redirected to the IdP, this endpoint
|
||||
* allows that redirect to occur manually upon a link/button click.
|
||||
*
|
||||
* @return
|
||||
* An HTTP Response that will redirect the user to the IdP.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If an error occurs preventing the redirect from being created.
|
||||
*/
|
||||
@GET
|
||||
@Path("login")
|
||||
public Response redirectToIdentityProvider() throws GuacamoleException {
|
||||
return Response.seeOther(authService.getLoginURI()).build();
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,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;
|
||||
}
|
@@ -13,10 +13,14 @@
|
||||
},
|
||||
|
||||
"LOGIN" : {
|
||||
"FIELD_HEADER_ID_TOKEN" : "",
|
||||
"FIELD_HEADER_STATE" : "",
|
||||
"FIELD_HEADER_TICKET" : "",
|
||||
"INFO_IDP_REDIRECT_PENDING" : "Please wait, redirecting to identity provider..."
|
||||
"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 @@
|
||||
src/main/resources/html/*.html
|
||||
|
@@ -20,25 +20,39 @@
|
||||
package org.apache.guacamole.auth.cas;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Singleton;
|
||||
import java.net.URI;
|
||||
import java.util.Arrays;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.ws.rs.core.UriBuilder;
|
||||
import org.apache.guacamole.form.Field;
|
||||
import org.apache.guacamole.GuacamoleException;
|
||||
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.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.sso.SSOAuthenticationProviderService;
|
||||
import org.apache.guacamole.auth.sso.user.SSOAuthenticatedUser;
|
||||
import org.apache.guacamole.form.RedirectField;
|
||||
import org.apache.guacamole.language.TranslatableMessage;
|
||||
|
||||
/**
|
||||
* Service that authenticates Guacamole users by processing CAS tickets.
|
||||
*/
|
||||
@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.
|
||||
*/
|
||||
@@ -58,29 +72,32 @@ public class AuthenticationProviderService implements SSOAuthenticationProviderS
|
||||
// Pull CAS ticket from request if present
|
||||
HttpServletRequest request = credentials.getRequest();
|
||||
if (request != null) {
|
||||
String ticket = request.getParameter(CASTicketField.PARAMETER_NAME);
|
||||
String ticket = request.getParameter(TICKET_PARAMETER_NAME);
|
||||
if (ticket != null) {
|
||||
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.",
|
||||
new CredentialsInfo(Arrays.asList(new Field[] {
|
||||
|
||||
// CAS-specific ticket (will automatically redirect the user
|
||||
// to the authorization page via JavaScript)
|
||||
new CASTicketField(
|
||||
confService.getAuthorizationEndpoint(),
|
||||
confService.getRedirectURI(),
|
||||
new TranslatableMessage("LOGIN.INFO_IDP_REDIRECT_PENDING")
|
||||
)
|
||||
new RedirectField(TICKET_PARAMETER_NAME, getLoginURI(),
|
||||
new TranslatableMessage("LOGIN.INFO_IDP_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
|
||||
|
@@ -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
|
||||
@@ -34,7 +35,8 @@ public class CASAuthenticationProvider extends SSOAuthenticationProvider {
|
||||
* against an CAS service
|
||||
*/
|
||||
public CASAuthenticationProvider() {
|
||||
super(AuthenticationProviderService.class, new CASAuthenticationProviderModule());
|
||||
super(AuthenticationProviderService.class,
|
||||
SSOResource.class, new CASAuthenticationProviderModule());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@@ -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);
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -9,6 +9,15 @@
|
||||
"org.apache.guacamole.auth.cas.CASAuthenticationProvider"
|
||||
],
|
||||
|
||||
"css" : [
|
||||
"styles/sso-providers.css"
|
||||
],
|
||||
|
||||
"html" : [
|
||||
"html/sso-providers.html",
|
||||
"html/sso-provider-cas.html"
|
||||
],
|
||||
|
||||
"translations" : [
|
||||
"translations/ca.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 @@
|
||||
src/main/resources/html/*.html
|
||||
|
@@ -21,18 +21,21 @@ package org.apache.guacamole.auth.openid;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Provider;
|
||||
import com.google.inject.Singleton;
|
||||
import java.net.URI;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
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.form.TokenField;
|
||||
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.auth.sso.SSOAuthenticationProviderService;
|
||||
import org.apache.guacamole.auth.sso.user.SSOAuthenticatedUser;
|
||||
import org.apache.guacamole.form.Field;
|
||||
import org.apache.guacamole.form.RedirectField;
|
||||
import org.apache.guacamole.language.TranslatableMessage;
|
||||
import org.apache.guacamole.net.auth.Credentials;
|
||||
import org.apache.guacamole.net.auth.credentials.CredentialsInfo;
|
||||
@@ -42,8 +45,15 @@ import org.jose4j.jwt.JwtClaims;
|
||||
/**
|
||||
* Service that authenticates Guacamole users by processing OpenID tokens.
|
||||
*/
|
||||
@Singleton
|
||||
public class AuthenticationProviderService implements SSOAuthenticationProviderService {
|
||||
|
||||
/**
|
||||
* The standard HTTP parameter which will be included within the URL by all
|
||||
* OpenID services upon successful authentication and redirect.
|
||||
*/
|
||||
public static final String TOKEN_PARAMETER_NAME = "id_token";
|
||||
|
||||
/**
|
||||
* Service for retrieving OpenID configuration information.
|
||||
*/
|
||||
@@ -78,7 +88,7 @@ public class AuthenticationProviderService implements SSOAuthenticationProviderS
|
||||
// Validate OpenID token in request, if present, and derive username
|
||||
HttpServletRequest request = credentials.getRequest();
|
||||
if (request != null) {
|
||||
String token = request.getParameter(TokenField.PARAMETER_NAME);
|
||||
String token = request.getParameter(TOKEN_PARAMETER_NAME);
|
||||
if (token != null) {
|
||||
JwtClaims claims = tokenService.validateToken(token);
|
||||
if (claims != null) {
|
||||
@@ -99,26 +109,28 @@ public class AuthenticationProviderService implements SSOAuthenticationProviderS
|
||||
|
||||
}
|
||||
|
||||
// Request OpenID token
|
||||
// Request OpenID token (will automatically redirect the user to the
|
||||
// OpenID authorization page via JavaScript)
|
||||
throw new GuacamoleInvalidCredentialsException("Invalid login.",
|
||||
new CredentialsInfo(Arrays.asList(new Field[] {
|
||||
|
||||
// OpenID-specific token (will automatically redirect the user
|
||||
// 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_IDP_REDIRECT_PENDING")
|
||||
)
|
||||
|
||||
new RedirectField(TOKEN_PARAMETER_NAME, getLoginURI(),
|
||||
new TranslatableMessage("LOGIN.INFO_IDP_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
|
||||
|
@@ -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,8 @@ public class OpenIDAuthenticationProvider extends SSOAuthenticationProvider {
|
||||
* against an OpenID service.
|
||||
*/
|
||||
public OpenIDAuthenticationProvider() {
|
||||
super(AuthenticationProviderService.class, new OpenIDAuthenticationProviderModule());
|
||||
super(AuthenticationProviderService.class, SSOResource.class,
|
||||
new OpenIDAuthenticationProviderModule());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@@ -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);
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -9,6 +9,15 @@
|
||||
"org.apache.guacamole.auth.openid.OpenIDAuthenticationProvider"
|
||||
],
|
||||
|
||||
"css" : [
|
||||
"styles/sso-providers.css"
|
||||
],
|
||||
|
||||
"html" : [
|
||||
"html/sso-providers.html",
|
||||
"html/sso-provider-openid.html"
|
||||
],
|
||||
|
||||
"translations" : [
|
||||
"translations/ca.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>
|
@@ -21,6 +21,7 @@ package org.apache.guacamole.auth.saml;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Provider;
|
||||
import com.google.inject.Singleton;
|
||||
import java.net.URI;
|
||||
import java.util.Arrays;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
@@ -35,12 +36,13 @@ import org.apache.guacamole.form.RedirectField;
|
||||
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.GuacamoleInsufficientCredentialsException;
|
||||
import org.apache.guacamole.net.auth.credentials.GuacamoleInvalidCredentialsException;
|
||||
|
||||
/**
|
||||
* Service that authenticates Guacamole users by processing the responses of
|
||||
* SAML identity providers.
|
||||
*/
|
||||
@Singleton
|
||||
public class AuthenticationProviderService implements SSOAuthenticationProviderService {
|
||||
|
||||
/**
|
||||
@@ -93,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 GuacamoleInsufficientCredentialsException("Redirecting to SAML IdP.",
|
||||
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();
|
||||
|
@@ -19,7 +19,6 @@
|
||||
|
||||
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;
|
||||
|
||||
@@ -36,7 +35,9 @@ public class SAMLAuthenticationProvider extends SSOAuthenticationProvider {
|
||||
* against a SAML IdP.
|
||||
*/
|
||||
public SAMLAuthenticationProvider() {
|
||||
super(AuthenticationProviderService.class, new SAMLAuthenticationProviderModule());
|
||||
super(AuthenticationProviderService.class,
|
||||
AssertionConsumerServiceResource.class,
|
||||
new SAMLAuthenticationProviderModule());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -44,9 +45,4 @@ public class SAMLAuthenticationProvider extends SSOAuthenticationProvider {
|
||||
return "saml";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getResource() throws GuacamoleException {
|
||||
return getInjector().getInstance(AssertionConsumerServiceResource.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -30,6 +30,7 @@ import javax.ws.rs.core.UriBuilder;
|
||||
import org.apache.guacamole.GuacamoleException;
|
||||
import org.apache.guacamole.auth.saml.AuthenticationProviderService;
|
||||
import org.apache.guacamole.auth.saml.conf.ConfigurationService;
|
||||
import org.apache.guacamole.auth.sso.SSOResource;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -38,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 {
|
||||
public class AssertionConsumerServiceResource extends SSOResource {
|
||||
|
||||
/**
|
||||
* Logger for this class.
|
||||
|
@@ -9,6 +9,15 @@
|
||||
"org.apache.guacamole.auth.saml.SAMLAuthenticationProvider"
|
||||
],
|
||||
|
||||
"css" : [
|
||||
"styles/sso-providers.css"
|
||||
],
|
||||
|
||||
"html" : [
|
||||
"html/sso-providers.html",
|
||||
"html/sso-provider-saml.html"
|
||||
],
|
||||
|
||||
"translations" : [
|
||||
"translations/ca.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-saml"><a href="api/ext/saml/login">{{
|
||||
'LOGIN.NAME_IDP_SAML' | translate
|
||||
}}</a></li>
|
Reference in New Issue
Block a user