Aller au contenu

net.HTTPclient et cookies


vravolta

Messages recommandés

Après avoir cherché un weekend complet, je n'arrive pas à trouver un tuto ou un exemple correctement documenté relatif à la gestion des cookies.

 

Le contexte est le suivant: je me lance dans le fait d'attaquer l'API Tesla. Pour cela, je dois envoyer une commande GET au server d'authentification. J'ai réussi sans souci à générer une requête qui fonctionne correctement avec Postman. Mais quand je la donne à net.HTTPclient, je récupère une erreur 403 de la part du server qui donc comprend ma requête (logique, il la comprend aussi via postman) mais refuse d'y répondre. Je suspecte que la cause est liée au fait que quand cette requête est envoyée au serveur, celui ci retourne un certain nombre de cookie. Je les vois apparaitre dans postman. Mais comme je ne trouve nulle part d'option pour gérer les cookies pour net.httpclient, j'imagine que c'est paramétré par défaut pour refuser les cookies ce qui doit entrainer le refus de la part du serveur tesla de fournir une réponse. 

 

Donc concrètement, j'aimerais pouvoir paramétrer le client http pour qu'il accepte les cookies que lui retournera le server tesla puis ensuite pour pouvoir les manipuler car je devrai ensuite pouvoir les réutiliser pour les requêtes suivantes.

 

La seule chose que j'ai trouvée, mais ca remonte à 2015 pour le dernier update, c'était un package en lua qui créait une fonction request modifiée qui semblait pouvoir gérer les cookies. Mais de ce que j'en ai compris en la lisant, c'était pour envoyer un cookie, pas pour en recevoir et c'est du code pour HC2 aors que je suis sur une HC3. Donc si une bonne âme pouvait éclairer ma lanterne, ce serait top.

 

Dans le même style, même si c'est moins problématique car je peux contourner, si je voulais faire propre dans la gestion de ma borne de recharge, je ne devrais pas récupérer son adresse mac manuellement sur l'app qui la gère mais via une interrogation via UDP en multicast qui devrait selon moi retourner en unicast une réponse. Je pense, sans pouvoir le vérifier, que j'ai réussi à envoyer le message d'interrogation en UDP, mais il me faudrait faire tourner un listener dans mon QA pour récupérer la réponse vu qu'elle arrivera en unicast qui est, selon ce que j'ai compris, du TCP.

 

Toute aide ou piste serait vivement appréciée ;-)

Lien vers le commentaire
Partager sur d’autres sites

Regarde ici :

 

 

Les cookies font partie des en-têtes HTTP de la réponse renvoyée par le serveur, donné en paramètre de la fonction success()

Donc si tu reprends le début du code donné dans le 1er exemple :

http:request("http://1.2.3.4/url", {
	success = function(response)

C'est dans la variable response que tu vas trouver tes cookies, à coté de tout le reste (le status, et les data)

 

response est une variable de type table qui contient diverses variables.

Tu peux parcourir response avec :

for key, value in pairs(response) do
	print(key .. " = " .. tostring(value))
end

Après il faut continuer à parcourir les tables imbriquées, de tête je pense que les cookies seront dans response.headers

 

Une fois que tu les as récupéré, tu les mémorises dans une variable locale, puis tu les renvoies au serveur Web lors de la requête suivante, en les mettant dans la variables headers des options de la fonction http:request().

(voir les exemples suivants)

Il te faudra juste chercher un peu la syntaxe exacte pour formater correctement les cookies dans les headers.

Lien vers le commentaire
Partager sur d’autres sites

Merci pour l’info, je vais creuser dans ce sens. Mais ne faut il pas autoriser avant quelque part les cookies? 
l’autre point est que quand j’affiche via self:debug ka variable response, je n’ai rien sachant que c’est supposé retourner du html. Et à ce sujet, au meme titre qu’il y a des fonctions natives pour decoder du json, est ce qu’il existe quelque chose pour le html?

Lien vers le commentaire
Partager sur d’autres sites

Il y a 4 heures, vravolta a dit :

Mais ne faut il pas autoriser avant quelque part les cookies

Non, les cookies sont envoyés dans l'entête de la réponse par le serveur Web avec qui tu échanges.
Après c'est à toi de les exploiter ou non. Et dans ton cas, tu as besoin de les exploiter.
La notion d'acceptation des cookies n'existe pas d'un point de vue technique.
C'est juste une invention des navigateurs Web grand publics, pour rassurer / protéger les utilisateurs.

 

Il y a 4 heures, vravolta a dit :

l’autre point est que quand j’affiche via self:debug ka variable response, je n’ai rien sachant que c’est supposé retourner du html

response est une variable de type "table" au sens LUA du terme.
Comme indiqué, il faut parcourir les éléments de la table.

Ces éléments sont des variables de différents types : "number", "string", etc.
La variable data de type string (chaine de caractères) contient le contenu de la page Web, donc du HTML.

Je t'ai indiqué comment parcourir la variable response pour explorer tout son contenu, et notamment ce dont tu as besoin pour commencer, les headers.
Pour aller plus loin, il y a pas mal d'exemple sur Internet.

 

Il y a 4 heures, vravolta a dit :

au meme titre qu’il y a des fonctions natives pour decoder du json, est ce qu’il existe quelque chose pour le html

Le HTML, c'est du format XML.
Et malheureusement non, Fibaro ne propose pas de librairie XML en LUA sur la HC3.

Quand on a juste 1 ou 2 informations à extraire d'une page Web, on s'en sort avec string.match(), mais c'est plus de la bidouille qu'autre chose.
Normalement les fournisseurs sérieux proposent une API au format JSON, bien plus exploitable que de la manipulation de pages HTML au format XML.

 

Lien vers le commentaire
Partager sur d’autres sites

Alors pour la question de la reponse en html, en fait, l’API Tesla est non officielle et lors du premier step d’interrogation, un de ses moyens de protection est de renvoyer une page html qui trompera un navigateur (avec de la recirection vers un site non existant ) mais qui contient dans ses cookies et des sections cachées des infos pour la suite de l’authentification qui elle se termine ensuite par du json que je sais facilement manipuler.

Et donc toute mon problème actuel, c’est de comprendre pourquoi ma requete lancée via lua qui est la meme en termes d’url que celle de postman donne un resultat different. Hormis le contenu du header, je ne vois pas trop ce qui peut changer. Je me demande si ce n’est pas lié au fait que c’est du https et pas du http et que le client http du lua de la HC3 ne saurait pas le gerer et en ferait du simple http pas s? Bref, je vais creuser toutes ces pistes!

Lien vers le commentaire
Partager sur d’autres sites

OK je vois.

J'aurais cru que Tesla proposait déjà une vraie API.

 

En tout cas tu peux tout à faire du https avec le LUA de la HC3, avec la même fonction request().

Il te suffit juste de mettre https dans l'URL.
Mais si tu as des redirections, c'est la galère, car tu dois gérer les codes status 3xx, puis faire de nouvelles requêtes, etc...

Bref pas mal de travail d'analyse des requêtes effectuées avec Postman pour les reproduire en LUA.

 

J'ai fait un truc similaire avec l'API de PSA, c'est la même galère, car ils ne proposent pas d'API officielle. Tout est documenté et prêt, mais l'API n'est juste pas ouverte au public... du coup j'ai reproduit les échanges comme le fait l'API de l'application mobile... et c'est ce que font aussi les autres solutions domotiques, Home Assistant, Jeedom, etc.

Lien vers le commentaire
Partager sur d’autres sites

Alors j'ai eu une petite avancée ce soir: ce qu'il me manquait dans le header par rapport à Postman était le paramètre Host. Je ne comprends pas trop à quoi ca sert de le préciser car de facto, si j'envoie une requete à https:// tesla.com, ca me semble assez clair que le host souhaité est www.tesla.com. Mais bon, en ajoutant cette info, je suis passé d'une erreur 401 à une erreur 301, ce qui est un vrai bon signe car désormais Tesla non seulement comprend ma requête mais ne refuse pas d'y répondre.

 

Je dois desormais comprendre comment faire pour que NET.httpclient ne suive pas la redirection. En effet, apparemment, c'est un piège de tesla selon la doc non officielle de l'API (et je confirme que si je saisis l'uri de redirection dans postman, ca retourne une erreur 404). Ce que je ne comprends pas, c'est que postman arrive à avoir un statut 200, qui ait le paramètre de suivi auto des redirections en cas d'erreur 3xx activé ou non.

 

Donc je continue d'investiguer. Pour comprendre ce que Postman fait pour arriver au statut 200 plutot qu'au 301. Sinon, super merci pour les boucles qui permettent de lire l'entier de ce qui se trouve dans response. J'ai désormais une boucle sur response elle même qui me retourne status (301), data (vide) et le header puis une boucle sur le header qui est lui même une table pour lire ce qu'il contient (et c'est là que je trouve l'adresse fake de redirection). Si vous avez des idées de comment gérer cette erreur 301 (à mon avis, il faudrait que je puisse dire à mon code de ne pas la suivre et mais en même, s'il la suivait, il devrait être en erreur 404 et pas 301. Donc il y a un truc que j'ai du zapper dans cette histoire.

Lien vers le commentaire
Partager sur d’autres sites

Apparemment dans les options de la requête tu peux mettre une variable redirect = true/false, et la valeur par défaut semble être true d'après le forum officiel, ce qui correspond à tes constatations.

Essaye de positionner redirect = false

 

https://forum.fibaro.com/topic/51532-httpclient-with-redirect/

https://forum.fibaro.com/topic/50487-nethttpclient-scene-issue-with-port/

 

Modifié par Lazer
Lien vers le commentaire
Partager sur d’autres sites

Alors il accepte l'option redirect= true/false (pas dans le header mais dans les paramètres d'appel de NET.HTPclient naturellement), mais ca ne change rien, même erreur.

 

J'ai tendance à penser que je suis dans la situation suivante: je dois initialement me connecter à www.auth.tesla.com: c'est ce que dit de faire la doc non officielle de l'API et c'est le seul domaine qui fonctionne (= pas d'erreur 4xx) dans le paramètre host. Face à cela, je recois une erreur 301 avec une location pour la redirection qui est https://www.tesla.com/?

Si je regarde mes cookies postman sur la requête qui fonctionne, j'ai un cookie de auth.tesla.com qui s'appelle tesla-auth.sid qui contient une valeur du même nom. Puis j'ai 5 cookies qui proviennent de tesla.com (sans le auth devant et donc du site vers lequel il y a redirection). Je subodore donc que la logique est de se connecter à auth.tesla.com, de recevoir une erreur 301 et le cookie tesla-auth.sid, de se laisser rediriger alors vers tesla.com en fournissant alors dans le header le cookie tesla-auth.sid qui ouvrira la porte pour recevoir la page HTML que je vais ensuite devoir parser pour récupérer les infos des steps suivants de l'authentification pour transformer mon login/password en token directement utilisable. A noter que si dans postman, je prends l'uri de redirection sans fournir le cookie = dans une requête séparée, j'obtiens une page html mais qui n'est pas celle avec les sections cachées qui contiennent la bonne info. Donc il y a bien un truc à comprendre avec ce cookie. Le hic, c'est que dans le header de retour sur la requête qui retourne l'erreur 301 en lua, je n'ai rien qui ressemble à un cookie et donc je ne peux pas le récupérer pour le réinjecter lors d'un appel à l'uri de redirection. A priori ce cookie n'est caché nulle part dans la réponse que je recois de l'erreur 301 car je la scanne sur toutes les tables et je ne trouve rien.

 

A noter un truc bizarre que j'ai noté au passage: à chaque appel de ma fonction, je génère 2 chaines de caractère supposées aléatoires à base de math.random (et à chaque génération, je remet la variable à ""). Mais pourtant, mes chaines sont toujours les mêmes, comme si math.random donnait toujours la même série de résultat aboutissant donc à une chaine pas du tout aléatoire.

Lien vers le commentaire
Partager sur d’autres sites

Le random est calculé à partir du lancement du programme, donc du QuickApp.. et comme il démarre toujours à la même vitesse, tu as un random toujours identique.

Le random est une notion qui n'existe pas en informatique, malheureusement... et le pseudo-random calculé par différentes méthodes imparfaites a été à l'origine de pas mal de failles de sécurité dans le passé... car prédictif.

Lien vers le commentaire
Partager sur d’autres sites

Sinon, en copiant le cookie de auth.tesla.com recu dans postman et en le passant en dur en paramètre du header d'une nouvelle requête avec comme url l'url de redirection, j'obtiens enfin un statut 200 avec un body pas vide. Il est illisible car a priori codé en gzip (aucune idée de s'il existe un moyen en lua de décoder le gzip mais avec un peu de chance, comme c'est moi qui signale dans les options que j'accepte le gzip, si je ne spécifie rien, il m'enverra le résultat non zippé). Ce qui est fou, c'est que là, je peux voir les cookies dans le header (donc ceux de www.tesla.com). Donc reste à comprendre comment je faire pour récupérer le cookie de auth.tesla.com dans la première requête et je serai arrivée à avoir le statut 200 du premier step de l'authentification. Mais là, j'avoue ne pas avoir d'idée de comment le trouver ou, si je ne le trouve pas, comment paramétrer la requête http initiale pour que quand elle fait la redirection, elle passe le cookie qu'elle recoit.

 

Pour math.random, c'est ce que je suspectais. N'y a t il pas un moyen de forcer math.random à débuter à un endroit pseudo aléatoire genre en se basant sur l'heure du moment où il est appelé?

Lien vers le commentaire
Partager sur d’autres sites

Compliqué cette histoire....

 

Pour le random, tu peux essayer avec un truc du genre :

math.randomseed(os.time())

C'est du pseudo random car c'est prédictif par rapport à l'heure courante, mais suffisant pour ton besoin je pense.

 

Lien vers le commentaire
Partager sur d’autres sites

×
×
  • Créer...