docs: def verify_token_string(self,
                              token_string,
                              action=None,
                              timeout=None,
                              current_time=None):
          """Generate a hash of the given token contents that can be verified.
  
          :param token_string:
              A string containing the hashed token (generated by
              `generate_token_string`).
          :param action:
              A string containing the action that is being verified.
          :param timeout:
              An int or float representing the number of seconds that the token
              is valid for. If None then tokens are valid forever.
          :current_time:
              An int representing the number of seconds since the epoch. Will be
              used by to check for token expiry if `timeout` is set. If `None`
              then the current time will be used.
          :raises:
              XSRFTokenMalformed if the given token_string cannot be parsed.
              XSRFTokenExpiredException if the given token string is expired.
              XSRFTokenInvalid if the given token string does not match the
              contents of the `XSRFToken`. 
          """
          try:
            decoded_token_string = base64.urlsafe_b64decode(token_string)
          except TypeError:
            raise XSRFTokenMalformed()
  
          split_token = decoded_token_string.split(self._DELIMITER)
          if len(split_token) != 2:
            raise XSRFTokenMalformed()
  
          try:
            token_time = int(split_token[1])
          except ValueError:
            raise XSRFTokenMalformed()
  
          if timeout is not None:
            if current_time is None:
              current_time = time.time()
            # If an attacker modifies the plain text time then it will not match
            # the hashed time so this check is sufficient.
            if (token_time + timeout) < current_time:
              raise XSRFTokenExpiredException()
  
          expected_token = XSRFToken(self.user_id, self.secret, token_time)
          expected_token_string = expected_token.generate_token_string(action)
  
          if len(expected_token_string) != len(token_string):
            raise XSRFTokenInvalid()
  
          # Compare the two strings in constant time to prevent timing attacks.
          different = 0
          for a, b in zip(token_string, expected_token_string):
            different |= ord(a) ^ ord(b)
          if different:
            raise XSRFTokenInvalid()