Validates the passed ticket, , raises a TicketError
        on failure

        Args:
            ticket: String value (possibly generated by new function)
            client_ip: Optional IPAddress of client, should be passed if the
                ip address was passed on ticket creation.
            now: Optional (defaults to time.time()) time to use when
                validating ticket date

        Returns:
            Ticket a TicketInfo tuple containing the users authentication details on
            success

        Raises:
            TicketParseError: Invalid ticket format
            TicketDigestError: Digest is incorrect (ticket data was modified)
            TicketExpired: Ticket has passed expiration date

def validate(self, ticket, client_ip=None, now=None, encoding='utf-8'):
        """Validates the passed ticket, , raises a TicketError
        on failure

        Args:
            ticket: String value (possibly generated by new function)
            client_ip: Optional IPAddress of client, should be passed if the
                ip address was passed on ticket creation.
            now: Optional (defaults to time.time()) time to use when
                validating ticket date

        Returns:
            Ticket a TicketInfo tuple containing the users authentication details on
            success

        Raises:
            TicketParseError: Invalid ticket format
            TicketDigestError: Digest is incorrect (ticket data was modified)
            TicketExpired: Ticket has passed expiration date

        """
        parts = self.parse(ticket)

        # Check if our ticket matches
        new_ticket = self.new(*(parts[1:]), client_ip=client_ip, encoding=encoding)

        if new_ticket[:self._hash.digest_size * 2] != parts.digest:
            raise TicketDigestError(ticket)

        if now is None:
            now = time.time()

        if parts.valid_until <= now:
            raise TicketExpired(ticket)

        return parts