mirror of
https://github.com/gyurix1968/guacamole-client.git
synced 2025-09-06 13:17:41 +00:00
GUACAMOLE-990: Merge new guacamole-auth-ban extension to block brute-force auth attempts.
This commit is contained in:
@@ -198,12 +198,16 @@ angular.module('auth').factory('authenticationService', ['$injector',
|
||||
['catch'](requestService.createErrorCallback(function authenticationFailed(error) {
|
||||
|
||||
// Request credentials if provided credentials were invalid
|
||||
if (error.type === Error.Type.INVALID_CREDENTIALS)
|
||||
if (error.type === Error.Type.INVALID_CREDENTIALS) {
|
||||
$rootScope.$broadcast('guacInvalidCredentials', parameters, error);
|
||||
clearAuthenticationResult();
|
||||
}
|
||||
|
||||
// Request more credentials if provided credentials were not enough
|
||||
else if (error.type === Error.Type.INSUFFICIENT_CREDENTIALS)
|
||||
else if (error.type === Error.Type.INSUFFICIENT_CREDENTIALS) {
|
||||
$rootScope.$broadcast('guacInsufficientCredentials', parameters, error);
|
||||
clearAuthenticationResult();
|
||||
}
|
||||
|
||||
// Abort rendering of page if an internal error occurs
|
||||
else if (error.type === Error.Type.INTERNAL_ERROR)
|
||||
|
@@ -34,7 +34,6 @@ 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.UserContext;
|
||||
import org.apache.guacamole.net.auth.credentials.CredentialsInfo;
|
||||
import org.apache.guacamole.net.auth.credentials.GuacamoleCredentialsException;
|
||||
import org.apache.guacamole.net.auth.credentials.GuacamoleInsufficientCredentialsException;
|
||||
import org.apache.guacamole.net.auth.credentials.GuacamoleInvalidCredentialsException;
|
||||
@@ -169,14 +168,15 @@ public class AuthenticationService {
|
||||
* The AuthenticatedUser given by the highest-priority
|
||||
* AuthenticationProvider for which the given credentials are valid.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* @throws GuacamoleAuthenticationProcessException
|
||||
* If the given credentials are not valid for any
|
||||
* AuthenticationProvider, or if an error occurs while authenticating
|
||||
* the user.
|
||||
*/
|
||||
private AuthenticatedUser authenticateUser(Credentials credentials)
|
||||
throws GuacamoleException {
|
||||
throws GuacamoleAuthenticationProcessException {
|
||||
|
||||
AuthenticationProvider failedAuthProvider = null;
|
||||
GuacamoleCredentialsException authFailure = null;
|
||||
|
||||
// Attempt authentication against each AuthenticationProvider
|
||||
@@ -191,27 +191,29 @@ public class AuthenticationService {
|
||||
|
||||
// Insufficient credentials should take precedence
|
||||
catch (GuacamoleInsufficientCredentialsException e) {
|
||||
if (authFailure == null || authFailure instanceof GuacamoleInvalidCredentialsException)
|
||||
if (authFailure == null || authFailure instanceof GuacamoleInvalidCredentialsException) {
|
||||
failedAuthProvider = authProvider;
|
||||
authFailure = e;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Catch other credentials exceptions and assign the first one
|
||||
catch (GuacamoleCredentialsException e) {
|
||||
if (authFailure == null)
|
||||
if (authFailure == null) {
|
||||
failedAuthProvider = authProvider;
|
||||
authFailure = e;
|
||||
}
|
||||
}
|
||||
|
||||
catch (GuacamoleException | RuntimeException | Error e) {
|
||||
throw new GuacamoleAuthenticationProcessException("User "
|
||||
+ "authentication was aborted.", authProvider, e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// If a specific failure occured, rethrow that
|
||||
if (authFailure != null)
|
||||
throw authFailure;
|
||||
|
||||
// Otherwise, request standard username/password
|
||||
throw new GuacamoleInvalidCredentialsException(
|
||||
"Permission Denied.",
|
||||
CredentialsInfo.USERNAME_PASSWORD
|
||||
);
|
||||
throw new GuacamoleAuthenticationProcessException("User authentication "
|
||||
+ "failed.", failedAuthProvider, authFailure);
|
||||
|
||||
}
|
||||
|
||||
@@ -230,51 +232,29 @@ public class AuthenticationService {
|
||||
* A AuthenticatedUser which may have been updated due to re-
|
||||
* authentication.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* @throws GuacamoleAuthenticationProcessException
|
||||
* If an error prevents the user from being re-authenticated.
|
||||
*/
|
||||
private AuthenticatedUser updateAuthenticatedUser(AuthenticatedUser authenticatedUser,
|
||||
Credentials credentials) throws GuacamoleException {
|
||||
Credentials credentials) throws GuacamoleAuthenticationProcessException {
|
||||
|
||||
// Get original AuthenticationProvider
|
||||
AuthenticationProvider authProvider = authenticatedUser.getAuthenticationProvider();
|
||||
|
||||
// Re-authenticate the AuthenticatedUser against the original AuthenticationProvider only
|
||||
authenticatedUser = authProvider.updateAuthenticatedUser(authenticatedUser, credentials);
|
||||
if (authenticatedUser == null)
|
||||
throw new GuacamoleSecurityException("User re-authentication failed.");
|
||||
try {
|
||||
|
||||
return authenticatedUser;
|
||||
// Re-authenticate the AuthenticatedUser against the original AuthenticationProvider only
|
||||
authenticatedUser = authProvider.updateAuthenticatedUser(authenticatedUser, credentials);
|
||||
if (authenticatedUser == null)
|
||||
throw new GuacamoleSecurityException("User re-authentication failed.");
|
||||
|
||||
}
|
||||
return authenticatedUser;
|
||||
|
||||
/**
|
||||
* Notify all bound listeners that a successful authentication
|
||||
* has occurred.
|
||||
*
|
||||
* @param authenticatedUser
|
||||
* The user that was successfully authenticated.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If thrown by a listener.
|
||||
*/
|
||||
private void fireAuthenticationSuccessEvent(AuthenticatedUser authenticatedUser)
|
||||
throws GuacamoleException {
|
||||
listenerService.handleEvent(new AuthenticationSuccessEvent(authenticatedUser));
|
||||
}
|
||||
}
|
||||
catch (GuacamoleException | RuntimeException | Error e) {
|
||||
throw new GuacamoleAuthenticationProcessException("User re-authentication failed.", authProvider, e);
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify all bound listeners that an authentication attempt has failed.
|
||||
*
|
||||
* @param credentials
|
||||
* The credentials that failed to authenticate.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If thrown by a listener.
|
||||
*/
|
||||
private void fireAuthenticationFailedEvent(Credentials credentials)
|
||||
throws GuacamoleException {
|
||||
listenerService.handleEvent(new AuthenticationFailureEvent(credentials));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -292,61 +272,23 @@ public class AuthenticationService {
|
||||
* The AuthenticatedUser associated with the given session and
|
||||
* credentials.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* @throws GuacamoleAuthenticationProcessException
|
||||
* If an error occurs while authenticating or re-authenticating the
|
||||
* user.
|
||||
*/
|
||||
private AuthenticatedUser getAuthenticatedUser(GuacamoleSession existingSession,
|
||||
Credentials credentials) throws GuacamoleException {
|
||||
|
||||
try {
|
||||
|
||||
// Re-authenticate user if session exists
|
||||
if (existingSession != null) {
|
||||
AuthenticatedUser updatedUser = updateAuthenticatedUser(
|
||||
existingSession.getAuthenticatedUser(), credentials);
|
||||
fireAuthenticationSuccessEvent(updatedUser);
|
||||
return updatedUser;
|
||||
}
|
||||
|
||||
// Otherwise, attempt authentication as a new user
|
||||
AuthenticatedUser authenticatedUser = AuthenticationService.this.authenticateUser(credentials);
|
||||
fireAuthenticationSuccessEvent(authenticatedUser);
|
||||
|
||||
if (logger.isInfoEnabled())
|
||||
logger.info("User \"{}\" successfully authenticated from {}.",
|
||||
authenticatedUser.getIdentifier(),
|
||||
getLoggableAddress(credentials.getRequest()));
|
||||
|
||||
return authenticatedUser;
|
||||
Credentials credentials) throws GuacamoleAuthenticationProcessException {
|
||||
|
||||
// Re-authenticate user if session exists
|
||||
if (existingSession != null) {
|
||||
AuthenticatedUser updatedUser = updateAuthenticatedUser(
|
||||
existingSession.getAuthenticatedUser(), credentials);
|
||||
return updatedUser;
|
||||
}
|
||||
|
||||
// Log and rethrow any authentication errors
|
||||
catch (GuacamoleException e) {
|
||||
|
||||
fireAuthenticationFailedEvent(credentials);
|
||||
|
||||
// Get request and username for sake of logging
|
||||
HttpServletRequest request = credentials.getRequest();
|
||||
String username = credentials.getUsername();
|
||||
|
||||
// Log authentication failures with associated usernames
|
||||
if (username != null) {
|
||||
if (logger.isWarnEnabled())
|
||||
logger.warn("Authentication attempt from {} for user \"{}\" failed.",
|
||||
getLoggableAddress(request), username);
|
||||
}
|
||||
|
||||
// Log anonymous authentication failures
|
||||
else if (logger.isDebugEnabled())
|
||||
logger.debug("Anonymous authentication attempt from {} failed.",
|
||||
getLoggableAddress(request));
|
||||
|
||||
// Rethrow exception
|
||||
throw e;
|
||||
|
||||
}
|
||||
// Otherwise, attempt authentication as a new user
|
||||
AuthenticatedUser authenticatedUser = AuthenticationService.this.authenticateUser(credentials);
|
||||
return authenticatedUser;
|
||||
|
||||
}
|
||||
|
||||
@@ -371,15 +313,14 @@ public class AuthenticationService {
|
||||
* A List of all UserContexts associated with the given
|
||||
* AuthenticatedUser.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* @throws GuacamoleAuthenticationProcessException
|
||||
* If an error occurs while creating or updating any UserContext.
|
||||
*/
|
||||
private List<DecoratedUserContext> getUserContexts(GuacamoleSession existingSession,
|
||||
AuthenticatedUser authenticatedUser, Credentials credentials)
|
||||
throws GuacamoleException {
|
||||
throws GuacamoleAuthenticationProcessException {
|
||||
|
||||
List<DecoratedUserContext> userContexts =
|
||||
new ArrayList<DecoratedUserContext>(authProviders.size());
|
||||
List<DecoratedUserContext> userContexts = new ArrayList<>(authProviders.size());
|
||||
|
||||
// If UserContexts already exist, update them and add to the list
|
||||
if (existingSession != null) {
|
||||
@@ -392,7 +333,15 @@ public class AuthenticationService {
|
||||
|
||||
// Update existing UserContext
|
||||
AuthenticationProvider authProvider = oldUserContext.getAuthenticationProvider();
|
||||
UserContext updatedUserContext = authProvider.updateUserContext(oldUserContext, authenticatedUser, credentials);
|
||||
UserContext updatedUserContext;
|
||||
try {
|
||||
updatedUserContext = authProvider.updateUserContext(oldUserContext, authenticatedUser, credentials);
|
||||
}
|
||||
catch (GuacamoleException | RuntimeException | Error e) {
|
||||
throw new GuacamoleAuthenticationProcessException("User "
|
||||
+ "authentication aborted during UserContext update.",
|
||||
authProvider, e);
|
||||
}
|
||||
|
||||
// Add to available data, if successful
|
||||
if (updatedUserContext != null)
|
||||
@@ -415,7 +364,15 @@ public class AuthenticationService {
|
||||
for (AuthenticationProvider authProvider : authProviders) {
|
||||
|
||||
// Generate new UserContext
|
||||
UserContext userContext = authProvider.getUserContext(authenticatedUser);
|
||||
UserContext userContext;
|
||||
try {
|
||||
userContext = authProvider.getUserContext(authenticatedUser);
|
||||
}
|
||||
catch (GuacamoleException | RuntimeException | Error e) {
|
||||
throw new GuacamoleAuthenticationProcessException("User "
|
||||
+ "authentication aborted during initial "
|
||||
+ "UserContext creation.", authProvider, e);
|
||||
}
|
||||
|
||||
// Add to available data, if successful
|
||||
if (userContext != null)
|
||||
@@ -453,7 +410,7 @@ public class AuthenticationService {
|
||||
* If the authentication or re-authentication attempt fails.
|
||||
*/
|
||||
public String authenticate(Credentials credentials, String token)
|
||||
throws GuacamoleException {
|
||||
throws GuacamoleException {
|
||||
|
||||
// Pull existing session if token provided
|
||||
GuacamoleSession existingSession;
|
||||
@@ -462,25 +419,72 @@ public class AuthenticationService {
|
||||
else
|
||||
existingSession = null;
|
||||
|
||||
// Get up-to-date AuthenticatedUser and associated UserContexts
|
||||
AuthenticatedUser authenticatedUser = getAuthenticatedUser(existingSession, credentials);
|
||||
List<DecoratedUserContext> userContexts = getUserContexts(existingSession, authenticatedUser, credentials);
|
||||
|
||||
// Update existing session, if it exists
|
||||
AuthenticatedUser authenticatedUser;
|
||||
String authToken;
|
||||
if (existingSession != null) {
|
||||
authToken = token;
|
||||
existingSession.setAuthenticatedUser(authenticatedUser);
|
||||
existingSession.setUserContexts(userContexts);
|
||||
|
||||
try {
|
||||
|
||||
// Get up-to-date AuthenticatedUser and associated UserContexts
|
||||
authenticatedUser = getAuthenticatedUser(existingSession, credentials);
|
||||
List<DecoratedUserContext> userContexts = getUserContexts(existingSession, authenticatedUser, credentials);
|
||||
|
||||
// Update existing session, if it exists
|
||||
if (existingSession != null) {
|
||||
authToken = token;
|
||||
existingSession.setAuthenticatedUser(authenticatedUser);
|
||||
existingSession.setUserContexts(userContexts);
|
||||
}
|
||||
|
||||
// If no existing session, generate a new token/session pair
|
||||
else {
|
||||
authToken = authTokenGenerator.getToken();
|
||||
tokenSessionMap.put(authToken, new GuacamoleSession(environment, authenticatedUser, userContexts));
|
||||
logger.debug("Login was successful for user \"{}\".", authenticatedUser.getIdentifier());
|
||||
}
|
||||
|
||||
// Report authentication success
|
||||
try {
|
||||
listenerService.handleEvent(new AuthenticationSuccessEvent(authenticatedUser));
|
||||
}
|
||||
catch (GuacamoleException e) {
|
||||
throw new GuacamoleAuthenticationProcessException("User "
|
||||
+ "authentication aborted by event listener.", null, e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// If no existing session, generate a new token/session pair
|
||||
else {
|
||||
authToken = authTokenGenerator.getToken();
|
||||
tokenSessionMap.put(authToken, new GuacamoleSession(environment, authenticatedUser, userContexts));
|
||||
logger.debug("Login was successful for user \"{}\".", authenticatedUser.getIdentifier());
|
||||
// Log and rethrow any authentication errors
|
||||
catch (GuacamoleAuthenticationProcessException e) {
|
||||
|
||||
// Get request and username for sake of logging
|
||||
HttpServletRequest request = credentials.getRequest();
|
||||
String username = credentials.getUsername();
|
||||
|
||||
listenerService.handleEvent(new AuthenticationFailureEvent(credentials,
|
||||
e.getAuthenticationProvider(), e.getCause()));
|
||||
|
||||
// Log authentication failures with associated usernames
|
||||
if (username != null) {
|
||||
if (logger.isWarnEnabled())
|
||||
logger.warn("Authentication attempt from {} for user \"{}\" failed.",
|
||||
getLoggableAddress(request), username);
|
||||
}
|
||||
|
||||
// Log anonymous authentication failures
|
||||
else if (logger.isDebugEnabled())
|
||||
logger.debug("Anonymous authentication attempt from {} failed.",
|
||||
getLoggableAddress(request));
|
||||
|
||||
// Rethrow exception
|
||||
throw e.getCauseAsGuacamoleException();
|
||||
|
||||
}
|
||||
|
||||
if (logger.isInfoEnabled())
|
||||
logger.info("User \"{}\" successfully authenticated from {}.",
|
||||
authenticatedUser.getIdentifier(),
|
||||
getLoggableAddress(credentials.getRequest()));
|
||||
|
||||
return authToken;
|
||||
|
||||
}
|
||||
|
@@ -76,21 +76,29 @@ public class DecoratedUserContext extends DelegatingUserContext {
|
||||
* given AuthenticationProvider, or the original UserContext if the
|
||||
* given AuthenticationProvider originated the UserContext.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* @throws GuacamoleAuthenticationProcessException
|
||||
* If the given AuthenticationProvider fails while decorating the
|
||||
* UserContext.
|
||||
*/
|
||||
private static UserContext decorate(AuthenticationProvider authProvider,
|
||||
UserContext userContext, AuthenticatedUser authenticatedUser,
|
||||
Credentials credentials) throws GuacamoleException {
|
||||
Credentials credentials) throws GuacamoleAuthenticationProcessException {
|
||||
|
||||
// Skip the AuthenticationProvider which produced the UserContext
|
||||
// being decorated
|
||||
if (authProvider != userContext.getAuthenticationProvider()) {
|
||||
|
||||
// Apply layer of wrapping around UserContext
|
||||
UserContext decorated = authProvider.decorate(userContext,
|
||||
authenticatedUser, credentials);
|
||||
UserContext decorated;
|
||||
try {
|
||||
decorated = authProvider.decorate(userContext,
|
||||
authenticatedUser, credentials);
|
||||
}
|
||||
catch (GuacamoleException | RuntimeException | Error e) {
|
||||
throw new GuacamoleAuthenticationProcessException("User "
|
||||
+ "authentication aborted by decorating UserContext.",
|
||||
authProvider, e);
|
||||
}
|
||||
|
||||
// Do not allow misbehaving extensions to wipe out the
|
||||
// UserContext entirely
|
||||
@@ -130,13 +138,13 @@ public class DecoratedUserContext extends DelegatingUserContext {
|
||||
* given AuthenticationProvider, or the original UserContext if the
|
||||
* given AuthenticationProvider originated the UserContext.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* @throws GuacamoleAuthenticationProcessException
|
||||
* If the given AuthenticationProvider fails while decorating the
|
||||
* UserContext.
|
||||
*/
|
||||
private static UserContext redecorate(DecoratedUserContext decorated,
|
||||
UserContext userContext, AuthenticatedUser authenticatedUser,
|
||||
Credentials credentials) throws GuacamoleException {
|
||||
Credentials credentials) throws GuacamoleAuthenticationProcessException {
|
||||
|
||||
AuthenticationProvider authProvider = decorated.getDecoratingAuthenticationProvider();
|
||||
|
||||
@@ -145,8 +153,16 @@ public class DecoratedUserContext extends DelegatingUserContext {
|
||||
if (authProvider != userContext.getAuthenticationProvider()) {
|
||||
|
||||
// Apply next layer of wrapping around UserContext
|
||||
UserContext redecorated = authProvider.redecorate(decorated,
|
||||
userContext, authenticatedUser, credentials);
|
||||
UserContext redecorated;
|
||||
try {
|
||||
redecorated = authProvider.redecorate(decorated.getDelegateUserContext(),
|
||||
userContext, authenticatedUser, credentials);
|
||||
}
|
||||
catch (GuacamoleException | RuntimeException | Error e) {
|
||||
throw new GuacamoleAuthenticationProcessException("User "
|
||||
+ "authentication aborted by redecorating UserContext.",
|
||||
authProvider, e);
|
||||
}
|
||||
|
||||
// Do not allow misbehaving extensions to wipe out the
|
||||
// UserContext entirely
|
||||
@@ -181,13 +197,13 @@ public class DecoratedUserContext extends DelegatingUserContext {
|
||||
* The credentials associated with the request which produced the given
|
||||
* UserContext.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* @throws GuacamoleAuthenticationProcessException
|
||||
* If any of the given AuthenticationProviders fails while decorating
|
||||
* the UserContext.
|
||||
*/
|
||||
public DecoratedUserContext(AuthenticationProvider authProvider,
|
||||
UserContext userContext, AuthenticatedUser authenticatedUser,
|
||||
Credentials credentials) throws GuacamoleException {
|
||||
Credentials credentials) throws GuacamoleAuthenticationProcessException {
|
||||
|
||||
// Wrap the result of invoking decorate() on the given AuthenticationProvider
|
||||
super(decorate(authProvider, userContext, authenticatedUser, credentials));
|
||||
@@ -221,13 +237,13 @@ public class DecoratedUserContext extends DelegatingUserContext {
|
||||
* The credentials associated with the request which produced the given
|
||||
* UserContext.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* @throws GuacamoleAuthenticationProcessException
|
||||
* If any of the given AuthenticationProviders fails while decorating
|
||||
* the UserContext.
|
||||
*/
|
||||
public DecoratedUserContext(AuthenticationProvider authProvider,
|
||||
DecoratedUserContext userContext, AuthenticatedUser authenticatedUser,
|
||||
Credentials credentials) throws GuacamoleException {
|
||||
Credentials credentials) throws GuacamoleAuthenticationProcessException {
|
||||
|
||||
// Wrap the result of invoking decorate() on the given AuthenticationProvider
|
||||
super(decorate(authProvider, userContext, authenticatedUser, credentials));
|
||||
@@ -261,13 +277,13 @@ public class DecoratedUserContext extends DelegatingUserContext {
|
||||
* The credentials associated with the request which produced the given
|
||||
* UserContext.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* @throws GuacamoleAuthenticationProcessException
|
||||
* If any of the given AuthenticationProviders fails while decorating
|
||||
* the UserContext.
|
||||
*/
|
||||
public DecoratedUserContext(DecoratedUserContext decorated,
|
||||
UserContext userContext, AuthenticatedUser authenticatedUser,
|
||||
Credentials credentials) throws GuacamoleException {
|
||||
Credentials credentials) throws GuacamoleAuthenticationProcessException {
|
||||
|
||||
// Wrap the result of invoking redecorate() on the given AuthenticationProvider
|
||||
super(redecorate(decorated, userContext, authenticatedUser, credentials));
|
||||
@@ -303,13 +319,13 @@ public class DecoratedUserContext extends DelegatingUserContext {
|
||||
* The credentials associated with the request which produced the given
|
||||
* UserContext.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* @throws GuacamoleAuthenticationProcessException
|
||||
* If any of the given AuthenticationProviders fails while decorating
|
||||
* the UserContext.
|
||||
*/
|
||||
public DecoratedUserContext(DecoratedUserContext decorated,
|
||||
DecoratedUserContext userContext, AuthenticatedUser authenticatedUser,
|
||||
Credentials credentials) throws GuacamoleException {
|
||||
Credentials credentials) throws GuacamoleAuthenticationProcessException {
|
||||
|
||||
// Wrap the result of invoking redecorate() on the given AuthenticationProvider
|
||||
super(redecorate(decorated, userContext, authenticatedUser, credentials));
|
||||
|
@@ -23,7 +23,6 @@ import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.apache.guacamole.GuacamoleException;
|
||||
import org.apache.guacamole.net.auth.AuthenticatedUser;
|
||||
import org.apache.guacamole.net.auth.AuthenticationProvider;
|
||||
import org.apache.guacamole.net.auth.Credentials;
|
||||
@@ -65,12 +64,12 @@ public class DecorationService {
|
||||
* A new DecoratedUserContext which has been decorated by all
|
||||
* AuthenticationProviders.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* @throws GuacamoleAuthenticationProcessException
|
||||
* If any AuthenticationProvider fails while decorating the UserContext.
|
||||
*/
|
||||
public DecoratedUserContext decorate(UserContext userContext,
|
||||
AuthenticatedUser authenticatedUser, Credentials credentials)
|
||||
throws GuacamoleException {
|
||||
throws GuacamoleAuthenticationProcessException {
|
||||
|
||||
// Get first AuthenticationProvider in list
|
||||
Iterator<AuthenticationProvider> current = authProviders.iterator();
|
||||
@@ -119,12 +118,12 @@ public class DecorationService {
|
||||
* A new DecoratedUserContext which has been decorated by all
|
||||
* AuthenticationProviders.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* @throws GuacamoleAuthenticationProcessException
|
||||
* If any AuthenticationProvider fails while decorating the UserContext.
|
||||
*/
|
||||
public DecoratedUserContext redecorate(DecoratedUserContext decorated,
|
||||
UserContext userContext, AuthenticatedUser authenticatedUser,
|
||||
Credentials credentials) throws GuacamoleException {
|
||||
Credentials credentials) throws GuacamoleAuthenticationProcessException {
|
||||
|
||||
// If the given DecoratedUserContext contains further decorated layers,
|
||||
// redecorate those first
|
||||
|
@@ -0,0 +1,164 @@
|
||||
/*
|
||||
* 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.rest.auth;
|
||||
|
||||
import java.io.Serializable;
|
||||
import org.apache.guacamole.GuacamoleException;
|
||||
import org.apache.guacamole.GuacamoleServerException;
|
||||
import org.apache.guacamole.net.auth.AuthenticationProvider;
|
||||
import org.apache.guacamole.net.auth.credentials.CredentialsInfo;
|
||||
import org.apache.guacamole.net.auth.credentials.GuacamoleInvalidCredentialsException;
|
||||
import org.apache.guacamole.protocol.GuacamoleStatus;
|
||||
|
||||
/**
|
||||
* An exception that occurs during Guacamole's authentication and authorization
|
||||
* process, possibly associated with a specific AuthenticationProvider.
|
||||
*/
|
||||
public class GuacamoleAuthenticationProcessException extends GuacamoleException {
|
||||
|
||||
/**
|
||||
* Internal identifier unique to this version of
|
||||
* GuacamoleAuthenticationProcessException, as required by Java's
|
||||
* {@link Serializable} interface.
|
||||
*/
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* The AuthenticationProvider that caused the failure, or null if there is
|
||||
* no such specific AuthenticationProvider involved in this failure.
|
||||
*/
|
||||
private final transient AuthenticationProvider authProvider;
|
||||
|
||||
/**
|
||||
* A GuacamoleException representation of the failure that occurred. If
|
||||
* the cause provided when this GuacamoleAuthenticationProcessException
|
||||
* was created was a GuacamoleException, this will just be that exception.
|
||||
* Otherwise, this will be a GuacamoleServerException wrapping the cause
|
||||
* or a generic GuacamoleInvalidCredentialsException requesting a
|
||||
* username/password if there is no specific cause at all.
|
||||
*/
|
||||
private final GuacamoleException guacCause;
|
||||
|
||||
/**
|
||||
* Converts the given Throwable to a GuacamoleException representing the
|
||||
* failure that occurred. If the Throwable already is a GuacamoleException,
|
||||
* this will just be that Throwable. For all other cases, a new
|
||||
* GuacamoleException will be created that best represents the provided
|
||||
* failure. If no failure is provided at all, a generic
|
||||
* GuacamoleInvalidCredentialsException requesting a username/password is
|
||||
* created.
|
||||
*
|
||||
* @param message
|
||||
* A human-readable message describing the failure that occurred.
|
||||
*
|
||||
* @param cause
|
||||
* The Throwable cause of the failure that occurred, if any, or null if
|
||||
* the cause is not known to be a specific Throwable.
|
||||
*
|
||||
* @return
|
||||
* A GuacamoleException representation of the message and cause
|
||||
* provided.
|
||||
*/
|
||||
private static GuacamoleException toGuacamoleException(String message,
|
||||
Throwable cause) {
|
||||
|
||||
// Create generic invalid username/password exception if we have no
|
||||
// specific cause
|
||||
if (cause == null)
|
||||
return new GuacamoleInvalidCredentialsException(
|
||||
"Permission Denied.",
|
||||
CredentialsInfo.USERNAME_PASSWORD
|
||||
);
|
||||
|
||||
// If the specific cause is already a GuacamoleException, there's
|
||||
// nothing for us to do here
|
||||
if (cause instanceof GuacamoleException)
|
||||
return (GuacamoleException) cause;
|
||||
|
||||
// Wrap all other Throwables as generic internal errors
|
||||
return new GuacamoleServerException(message, cause);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new GuacamoleAuthenticationProcessException with the given
|
||||
* message, associated AuthenticationProvider, and cause.
|
||||
*
|
||||
* @param message
|
||||
* A human readable description of the exception that occurred.
|
||||
*
|
||||
* @param authProvider
|
||||
* The AuthenticationProvider that caused the failure, or null if there
|
||||
* is no such specific AuthenticationProvider involved in this failure.
|
||||
*
|
||||
* @param cause
|
||||
* The cause of this exception, or null if the cause is unknown or
|
||||
* there is no such cause.
|
||||
*/
|
||||
public GuacamoleAuthenticationProcessException(String message,
|
||||
AuthenticationProvider authProvider, Throwable cause) {
|
||||
super(message, cause);
|
||||
this.authProvider = authProvider;
|
||||
this.guacCause = toGuacamoleException(message, cause);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the AuthenticationProvider that caused the failure, if any. If
|
||||
* there is no specific AuthenticationProvider involved in this failure,
|
||||
* including if the failure is due to multiple AuthenticationProviders,
|
||||
* this will be null.
|
||||
*
|
||||
* @return
|
||||
* The AuthenticationProvider that caused the failure, or null if there
|
||||
* is no such specific AuthenticationProvider involved in this failure.
|
||||
*/
|
||||
public AuthenticationProvider getAuthenticationProvider() {
|
||||
return authProvider;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a GuacamoleException that represents the user-facing cause of
|
||||
* this exception. A GuacamoleException will be returned by this function
|
||||
* in all cases, including if no specific cause was given.
|
||||
*
|
||||
* @return
|
||||
* A GuacamoleException that represents the user-facing cause of this
|
||||
* exception.
|
||||
*/
|
||||
public GuacamoleException getCauseAsGuacamoleException() {
|
||||
return guacCause;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GuacamoleStatus getStatus() {
|
||||
return getCauseAsGuacamoleException().getStatus();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHttpStatusCode() {
|
||||
return getCauseAsGuacamoleException().getHttpStatusCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getWebSocketCode() {
|
||||
return getCauseAsGuacamoleException().getWebSocketCode();
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user