public AuthenticatedUser authenticateUser(Credentials credentials)
            throws GuacamoleException {

        // Ignore anonymous users
        if (credentials.getUsername() == null || credentials.getUsername().isEmpty())
            return null;

        // Password is required
        if (credentials.getPassword() == null || credentials.getPassword().isEmpty())
            return null;

        // Grab HTTP request object and a response to a challenge.
        String challengeResponse = credentials.getParameter(CHALLENGE_RESPONSE_PARAM);

        // RadiusPacket object to store response from server.
        RadiusPacket radPack;

        // No challenge response, proceed with username/password authentication.
        if (challengeResponse == null) {

            try {
                radPack = radiusService.authenticate(credentials.getUsername(),
                                                credentials.getPassword(),
                                                credentials.getRemoteAddress(),
                                                null);
            }
            catch (GuacamoleException e) {
                logger.error("Cannot configure RADIUS server: {}", e.getMessage());
                logger.debug("Error configuring RADIUS server.", e);
                throw new GuacamoleInvalidCredentialsException("Authentication error.", CredentialsInfo.USERNAME_PASSWORD);
            }
        }

        // This is a response to a previous challenge, authenticate with that.
        else {
            try {
                String stateString = credentials.getParameter(RadiusStateField.PARAMETER_NAME);
                if (stateString == null) {
                    logger.warn("Expected state parameter was not present in challenge/response.");
                    throw new GuacamoleInvalidCredentialsException("Authentication error.", CredentialsInfo.USERNAME_PASSWORD);
                }

                byte[] stateBytes = BaseEncoding.base16().decode(stateString);
                radPack = radiusService.sendChallengeResponse(credentials.getUsername(),
                                                              challengeResponse,
                                                              credentials.getRemoteAddress(),
                                                              stateBytes);
            }
            catch (IllegalArgumentException e) {
                logger.warn("Illegal hexadecimal value while parsing RADIUS state string: {}", e.getMessage());
                logger.debug("Encountered exception while attempting to parse the hexidecimal state value.", e);
                throw new GuacamoleInvalidCredentialsException("Authentication error.", CredentialsInfo.USERNAME_PASSWORD);
            }
            catch (GuacamoleException e) {
                logger.error("Cannot configure RADIUS server: {}", e.getMessage());
                logger.debug("Error configuring RADIUS server.", e);
                throw new GuacamoleInvalidCredentialsException("Authentication error.", CredentialsInfo.USERNAME_PASSWORD);
            }
        }

        // No RadiusPacket is returned, we've encountered an error.
        if (radPack == null) {
            logger.debug("Nothing in the RADIUS packet.");
            throw new GuacamoleInvalidCredentialsException("Authentication error.", CredentialsInfo.USERNAME_PASSWORD);
        }

        // Received AccessReject packet, login is denied.
        else if (radPack instanceof AccessReject) {
            logger.debug("Login has been rejected by RADIUS server.");
            throw new GuacamoleInvalidCredentialsException("Authentication failed.", CredentialsInfo.USERNAME_PASSWORD);
        }

        // Received AccessAccept, authentication has succeeded
        else if (radPack instanceof AccessAccept) {
            AuthenticatedUser authenticatedUser = authenticatedUserProvider.get();
            authenticatedUser.init(credentials);
            return authenticatedUser;
        }

        // Received AccessChallenge packet, more credentials required to complete authentication
        else if (radPack instanceof AccessChallenge) {
            GuacamoleRadiusChallenge challenge = getRadiusChallenge(radPack);

            if (challenge == null)
                throw new GuacamoleInvalidCredentialsException("Authentication error.", CredentialsInfo.USERNAME_PASSWORD);

            throw new GuacamoleInsufficientCredentialsException(
                    challenge.getChallengeText(),
                    challenge.getExpectedCredentials());
        }

        // Something unanticipated happened, so panic and go back to login.
        else {
            logger.error("Unexpected failure authenticating with RADIUS server.");
            throw new GuacamoleInvalidCredentialsException("Unknown error trying to authenticate.", CredentialsInfo.USERNAME_PASSWORD);
        }

    }
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.
extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/AuthenticationProviderService.java