docs: def _unpack_token_json(token):
      """
      Unpack a JSON-serialized JWT
      Returns (headers, payload, signatures) on success
      Raises DecodeError on bad input
      """
      if not isinstance(token, dict):
          raise DecodeError("Not a dict")
  
      if not token.has_key('payload'):
          raise DecodeError("Missing 'payload' field")
  
      for k in ['header', 'signature']:
          if not token.has_key(k):
              raise DecodeError("Missing '{}' field".format(k))
  
          if not isinstance(token[k], list):
              raise DecodeError("Field '{}' is not a string".format(k))
  
      headers = []
      signatures = []
      signing_inputs = []
      payload = None
  
      try:
          headers = [base64url_decode(str(h)) for h in token['header']]
      except (TypeError, binascii.Error):
          raise DecodeError("Invalid header padding")
  
      try:
          payload_data = base64url_decode(str(token['payload']))
      except (TypeError, binascii.Error):
          raise DecodeError("Invalid payload padding")
  
      try:
          payload = json.loads(payload_data.decode('utf-8'))
      except ValueError as e:
          raise DecodeError('Invalid payload string: {}'.format(e))
  
      try:
          signatures = [base64url_decode(str(s)) for s in token['signature']]
      except (TypeError, binascii.Error):
          raise DecodeError("Invalid crypto padding")
  
      for header_b64 in token['header']:
          signing_inputs.append( b'{}.{}'.format(header_b64, token['payload']) )
  
      return (headers, payload, signatures, signing_inputs)