public SSOAuthenticatedUser validateTicket(String ticket,
            Credentials credentials) throws GuacamoleException {

        // Create a ticket validator that uses the configured CAS URL
        URI casServerUrl = confService.getAuthorizationEndpoint();
        Cas20ProxyTicketValidator validator = new Cas20ProxyTicketValidator(casServerUrl.toString());
        validator.setAcceptAnyProxy(true);
        validator.setEncoding("UTF-8");

        // Attempt to validate the supplied ticket
        Assertion assertion;
        try {
            URI confRedirectURI = confService.getRedirectURI();
            assertion = validator.validate(ticket, confRedirectURI.toString());
        }
        catch (TicketValidationException e) {
            throw new GuacamoleException("Ticket validation failed.", e);
        }

        // Pull user principal and associated attributes
        AttributePrincipal principal =  assertion.getPrincipal();
        Map<String, Object> ticketAttrs = new HashMap<>(principal.getAttributes());

        // Retrieve user identity from principal
        String username = principal.getName();
        if (username == null)
            throw new GuacamoleSecurityException("No username provided by CAS.");

        // Canonicalize username as lowercase
        username = username.toLowerCase();

        // Retrieve password, attempt decryption, and set credentials.
        Object credObj = ticketAttrs.remove("credential");
        if (credObj != null) {
            String clearPass = decryptPassword(credObj.toString());
            if (clearPass != null && !clearPass.isEmpty())
                credentials.setPassword(clearPass);
        }

        Set<String> effectiveGroups;

        // Parse effective groups from principal attributes if a specific
        // group attribute has been configured
        String groupAttribute = confService.getGroupAttribute();
        if (groupAttribute != null) {
            effectiveGroups = toStringSet(ticketAttrs.get(groupAttribute)).stream()
                    .map(confService.getGroupParser()::parse)
                    .collect(Collectors.toSet());
        }

        // Otherwise, assume no effective groups
        else
            effectiveGroups = Collections.emptySet();

        // Convert remaining attributes that have values to Strings
        Map<String, String> tokens = new HashMap<>(ticketAttrs.size());
        ticketAttrs.forEach((key, value) -> {
            if (value != null) {
                String tokenName = TokenName.canonicalize(key, CAS_ATTRIBUTE_TOKEN_PREFIX);
                tokens.put(tokenName, value.toString());
            }
        });

        SSOAuthenticatedUser authenticatedUser = authenticatedUserProvider.get();
        authenticatedUser.init(username, credentials, effectiveGroups, tokens);
        return authenticatedUser;

    }
Validates and parses the given ID ticket, returning a map of all
available tokens for the given user based on attributes provided by the
CAS server.  If the ticket is invalid an exception is thrown.

@param ticket
    The ID ticket to validate and parse.

@param credentials
    The Credentials object to store retrieved username and
    password values in.

@return
    A CASAuthenticatedUser instance containing the ticket data returned by the CAS server.

@throws GuacamoleException
    If the ID ticket is not valid or guacamole.properties could
    not be parsed.
extensions/guacamole-auth-sso/modules/guacamole-auth-sso-cas/src/main/java/org/apache/guacamole/auth/cas/ticket/TicketValidationService.java