<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:

def decrypt_token(self, username, token):
        '''
        Decrypt a token.
        '''
        version, user_type, _from = self._parse_username(username)
        if (version > self.maximum_token_version or
                version < self.minimum_token_version):
            raise TokenValidationError('Unacceptable token version.')
        try:
            token_key = '{0}{1}{2}{3}'.format(
                hashlib.sha256(ensure_bytes(token)).hexdigest(),
                _from,
                self.to_auth_context,
                user_type
            )
        except Exception:
            raise TokenValidationError('Authentication error.')
        if token_key not in self.TOKENS:
            try:
                token = base64.b64decode(token)
                # Ensure normal context fields override whatever is in
                # extra_context.
                context = copy.deepcopy(self.extra_context)
                context['to'] = self.to_auth_context
                context['from'] = _from
                if version > 1:
                    context['user_type'] = user_type
                data = self.kms_client.decrypt(
                    CiphertextBlob=token,
                    EncryptionContext=context
                )
                # Decrypt doesn't take KeyId as an argument. We need to verify
                # the correct key was used to do the decryption.
                # Annoyingly, the KeyId from the data is actually an arn.
                key_arn = data['KeyId']
                if user_type == 'service':
                    if not self._valid_service_auth_key(key_arn):
                        raise TokenValidationError(
                            'Authentication error (wrong KMS key).'
                        )
                elif user_type == 'user':
                    if not self._valid_user_auth_key(key_arn):
                        raise TokenValidationError(
                            'Authentication error (wrong KMS key).'
                        )
                else:
                    raise TokenValidationError(
                        'Authentication error. Unsupported user_type.'
                    )
                plaintext = data['Plaintext']
                payload = json.loads(plaintext)
                key_alias = self._get_key_alias_from_cache(key_arn)
                ret = {'payload': payload, 'key_alias': key_alias}
            except TokenValidationError:
                raise
            except (ConnectionError, EndpointConnectionError):
                logging.exception('Failure connecting to AWS endpoint.')
                raise TokenValidationError(
                    'Authentication error. Failure connecting to AWS endpoint.'
                )
            # We don't care what exception is thrown. For paranoia's sake, fail
            # here.
            except Exception:
                logging.exception('Failed to validate token.')
                raise TokenValidationError(
                    'Authentication error. General error.'
                )
        else:
            ret = self.TOKENS[token_key]
        now = datetime.datetime.utcnow()
        try:
            not_before = datetime.datetime.strptime(
                ret['payload']['not_before'],
                TIME_FORMAT
            )
            not_after = datetime.datetime.strptime(
                ret['payload']['not_after'],
                TIME_FORMAT
            )
        except Exception:
            logging.exception(
                'Failed to get not_before and not_after from token payload.'
            )
            raise TokenValidationError(
                'Authentication error. Missing validity.'
            )
        delta = (not_after - not_before).seconds / 60
        if delta > self.auth_token_max_lifetime:
            logging.warning('Token used which exceeds max token lifetime.')
            raise TokenValidationError(
                'Authentication error. Token lifetime exceeded.'
            )
        if (now < not_before) or (now > not_after):
            logging.warning('Invalid time validity for token.')
            raise TokenValidationError(
                'Authentication error. Invalid time validity for token.'
            )
        self.TOKENS[token_key] = ret
        return self.TOKENS[token_key]