« Documentation de l'API Jeuxvideo.com » : différence entre les versions

Aucun résumé des modifications
Ligne 1 : Ligne 1 :
L''''API de [[Jeuxvideo.com]]''', utilisée à l'origine par les applications mobiles de Jeuxvideo.com, permet de développer plus facilement des applications, sites web, et autres scripts en rapport avec Jeuxvideo.com.
L''''API de [[Jeuxvideo.com]]''', utilisée à l'origine par les applications mobiles de jeuxvideo.com, permet de développer plus facilement des applications, sites Web, et autres scripts en rapport avec jeuxvideo.com.


L'API est hébergée sur le sous-domaine "api", et est actuellement à sa quatrième version (v4). Les anciennes versions sont toujours exploitables avec les tokens qui leurs sont propres, mais certains endpoints retournent des erreurs HTTP 403, visiblement retournées directement par le serveur HTTP de JV (HAProxy).
L'API est hébergée sur le sous-domaine ''api'', et est actuellement à sa quatrième version (v4). Les anciennes versions sont toujours exploitables avec les tokens qui leurs sont propres, mais certains ''endpoints'' retournent des erreurs HTTP 403, visiblement retournées directement par le serveur HTTP de JVC (HAProxy).
 
L'API actuelle est privée et ne peut être documentée que par rétro-ingéniérie.
 
=Rétro-ingénierie de l'application mobile JVC=
Pour connaître les endpoints de l'API, il faut décompiler l'[https://apkpure.fr/fr/jeuxvideo-com-pc-et-consoles/com.jeuxvideo application mobile JVC] ou intercepter les requêtes qu'elle envoie.
 
== Décompilation ==
=== Mise en place du processus de décompilation ===
Pour pouvoir décompiler l'application mobile, vous aurez besoin des outils suivants :
# [https://www.java.com/en/download/ Java 8 ou plus]
# [https://apktool.org/ apktool]
# [https://github.com/skylot/jadx JADX]
 
Il faut également le fichier ''.apk'' de l'application mobile, téléchargeable [https://apkpure.fr/fr/jeuxvideo-com-pc-et-consoles/com.jeuxvideo ici] (privilégiez les versions supérieures à la 5.4.3, sans quoi vous devrez extraire le fichier ''.xapk'' et appliquer le processus de décompilation sur le fichier ''.apk'' principal).
 
Il vaut mieux renommer le fichier ''.apk'' obtenu pour éviter d'avoir à être embarassé par de trops longs noms de fichiers. Ici, nous l'avons enregistré sous ''jeuxvideo.apk''.
 
Suivez les étapes ci-dessous (en remplaçant ''jeuxvideo.apk'' par le nom du fichier ''.apk'' à votre disposition) :
# Dans un terminal ouvert au dossier de l'APK, exécutez la commande suivante :
$ apktool d jeuxvideo.apk jeuxvideo-decompiled
# Ouvrez JADX, activez l'option ''Show flatten packages'' (dans la barre d'outils), dans les préférences du logiciel veillez à avoir changé l'option ''Code comments level'' sur ''DEBUG''.
# Importez les fichiers ''.dex'' dans JADX.
 
=== JvApiService ===
Une fois le code Java disponible, on peut ouvrir la classe '''JvApiService''' (située dans ''com.jeuxvideo.api.web''), qui contient tous les ''endpoints''. L'application utilise le bibliothèque [https://square.github.io/retrofit/ Retrofit 2.x] pour gérer l'API, et la classe contient tous les ''endpoints'' formels de l'API.
 
''Exemple de code dans l'interface '''JvApiService'''''
<pre>
    @POST("contents/{contentID}/comments")
    Call<UserComment> addComment(@Path("contentID") String str, @Body UserComment.Body body);
 
    @POST("contents/{contentID}/comments/{commentID}/vote")
    Call<UserComment> addCommentVote(@Path("contentID") String str, @Path("commentID") String str2, @Body UserComment.Vote vote);
</pre>
 
=== ApiLogin ===
La classe ''com.jeuxvideo.utils.'''ApiLogin''''' (nom de la classe donné arbitrairement car perdu lors de la compilation), permet de déduire la valeur du ''header Jvc-Authorization'' à envoyer dans les requêtes à l'API.
<pre>
    public static String f(String str, String str2, String str3, String str4, String str5) {
        StringBuilder sb2 = new StringBuilder();
        sb2.append("550c04bf5cb2b\n");
        sb2.append(str);
        sb2.append("\n");
        sb2.append(str2);
        sb2.append("\n");
        sb2.append(str3);
        sb2.append("\n");
        sb2.append(str4);
        sb2.append("\n");
        if (str5 == null) {
            str5 = "";
        }
        sb2.append(str5);
        String b10 = j5.f.b("d84e9e5f191ea4ffc39c22d11c77dd6c", sb2.toString());
        return "PartnerKey=550c04bf5cb2b, Signature=" + b10 + ", Timestamp=" + str;
    }
</pre>
 
=== JVApi et UserAgentInterceptor ===
''JVApi'' (du package arbitrairement nommé ''p379s3'' car nom perdu lors de la compilation) et ''UserAgentInterceptor'' (du package ''com.jeuxvideo.api.utils'') permettent de déduire le ''user-agent'' et la valeur des ''headers'' contenant des informations sur la version et la plateforme.
 
=== JVApiManager ===
La classe ''JVApiManager'' (du package arbitrairement nommé ''p379s3'' car nom perdu lors de la compilation) est celle qui envoie les requêtes à l'API. Elle permet de savoir quelles variables sont passées à la requête vers tel ''endpoint''.
 
=== Le cas Jvc-Auth-Header ===
''Jvc-Auth-Header'' est le ''header'' envoyé à l'''endpoint'' nommé ''accounts/register''. Cet ''endpoint'' est crucial en ce qu'il représente l''''unique manière de créer un compte JVC sans le système reCaptcha'''.
 
Il est actuellement impossible que la requête soit validée par l'API sans ce ''header''.
 
Il s'avère que ''Jvc-Auth-Header'' contient le [https://stackoverflow.com/questions/37671380/what-is-fcm-token-in-firebase token FCM], un token créé par la plateforme ''FireBase'' de Google et utilisé par l'application mobile pour accéder aux bases de données. Ce token est unique à chaque appareil et est créé à chaque installation de l'application mobile. En outre, il permet à l'API de savoir si l'application a déjà effectué une requête d'inscription dans les dernières 24 heures et, le cas échéant, de bloquer les requêtes d'inscription.
 
Il semble malheureusement impossible de générer de tels tokens « à la demande », en tout cas sans connaître les noms et clés des services FireBase dédiés à l'application.
 
== Interception du trafic ==
 
Il est possible d'intercepter le trafic émis par l'application mobile lorsqu'elle est exécutée sur un appareil afin de connaître en détail les requêtes envoyées à l'API.
 
Cette méthode est indépendante de la précédente qui nécessitait de décompiler l'APK. Ici, vous aurez besoin du fichier APK original.
 
=== Mise en place du processus d'interception ===
Pour pouvoir intercepter le trafic de l'application mobile, vous aurez besoin des outils suivants :
# [https://developer.android.com/studio?hl=fr Android Studio]
# [https://httptoolkit.com/ HTTP Toolkit]
 
Il faut également le fichier ''.apk'' de l'application mobile, téléchargeable [https://apkpure.fr/fr/jeuxvideo-com-pc-et-consoles/com.jeuxvideo ici].
 
Pour commencer, il vous faut créer un appareil virtuel avec Android Studio : suivez pour cela le tutoriel disponible à [https://developer.android.com/studio/run/managing-avds?hl=fr cette adresse]. Pour que HTTP Toolkit puisse intercepter le trafic de l'application, il faut choisir un appareil ne disposant pas de ''Google Play''. Nous vous conseillons de choisir le téléphone Pixel 6 Pro et l'image système Tiramisu (niveau d'API 33, Android 13.0). Une fois l'appareil virtuel créé, lancez-le.
 
Une fois ceci fait, ouvrez le logiciel HTTP Toolkit puis dans le menu principal choisissez l'option ''Android Device via ADB'' qui devrait désormais être accessible. HTTP Toolkit va automatiquement installer tous les logiciels nécessaires sur l'appareil ; vous serez invités, sur l'appareil, à autoriser une connextion VPN à HTTP Toolkit : appuyez sur « OK ».
 
Ensuite, vous devrez utiliser ADB pour installer l'APK sur l'appareil virtuel. Premièrement, il vous faut ajouter ADB à la variable PATH de votre ordinateur ; consultez la section « How to use ADB from any directory on your PC or Mac » de [https://www.xda-developers.com/install-adb-windows-macos-linux/ cet article], qui contient les étapes à suivre sur Windows, MacOS et Linux.
 
Ouvrez un terminal de commande dans le dossier où se trouve l'APK et exécutez <code>adb install jeuxvideo.apk</code> (remplacez ''jeuxvideo.apk'' par le nom du fichier APK téléchargé). Une fois la commande exécutée, vous n'avez plus qu'à lancer l'application mobile et observez quelles requêtes sont envoyées dans le panel ''View'' de HTTP Toolkit.
 
Vous pouvez désormais voir quelles requêtes sont passées à l'API, ainsi que les ''headers'' et ''body'' associés. Par exemple lorsque l'on se connecte :
[[File:http_toolkit.png|400px]]


=API v4=
=API v4=


===Utilisation ===
==Utilisation ==
L'API v4 utilise une sécurité, l'en-tête HTTP <code>Jvc-Authorization</code> , sa valeur dépend d'une clé fixe <code>partner_key</code>, d'une <code>signature</code>  et de la <code>date</code> .
L'API v4 utilise une sécurité, l'en-tête HTTP <code>Jvc-Authorization</code> , sa valeur dépend d'une clé fixe <code>partner_key</code>, d'une <code>signature</code>  et de la <code>date</code> .


Le ''header'' de vos requêtes devra toujours être de la forme:
Le ''header'' de vos requêtes devra toujours être de la forme :
<pre>
<pre>
"Jvc-Authorization " : "header"
"Jvc-Authorization" : header,
"User-Agent" : "JeuxVideo-Android/267"
"User-Agent" : "JeuxVideo-Android/338",
"Jvc-App-Platform" : "Android",
"Jvc-App-Version" : 338,
"Content-Type" : "application/json"
"Content-Type" : "application/json"
</pre>
</pre>
'''''header''''' est égal à une chaîne de caractères de cette forme: ''"PartnerKey='''<u>partner_key</u>''', Signature='''<u>signature</u>''', Timestamp='''<u>date</u>'''".''
Où ''header'' est égal à une chaîne de caractères de la forme ''"PartnerKey=partner_key, Signature=signature, Timestamp=timestamp".


'''Voici un script [https://www.python.org/ python] qui construit "''header''"'''
Voici un script [https://www.python.org/ python] qui construit la valeur de ''Jvc-Authorization'' :
<pre>
<pre>
import hmac
import hmac
Ligne 47 : Ligne 145 :


===Connexion===
===Connexion===
Comme pour l'ancienne API, le cookie '''''coniunctio''''' est toujours le cookie de session utilisateur. Il doit être récupéré avec l'appel au point d'entrée ''login'' (voir tableau POST) puis il doit être envoyé dans une en-tête HTTP "Cookie": "'''''coniunctio'''''" pour chaque appel.
Comme pour l'ancienne API, le cookie ''coniunctio'' est toujours le cookie de session utilisateur. Il doit être récupéré avec l'appel au point d'entrée ''accounts/login'' (voir tableau POST) puis il doit être envoyé dans une en-tête HTTP <code>"Cookie" : "coniunctio"</code> pour chaque appel.
 
 
 
== Comportement du sous-domaine ==
Il est intéressant de remarquer que l'API se comporte souvent en véritable sous-domaine, de manière similaire au site www.jeuxvideo.com de base : par exemple, si vous êtes sur un [[topic]] ou un [[forum]], il vous suffit de remplacer dans l'URL « www » par « api » et vous vous trouverez sur une page aux informations identiques quoique présentées de manière différente. Ainsi, les URL seront de la forme <code>https://api.jeuxvideo.com/forums/0-51-0-1-0-1-0-blabla-18-25-ans.htm</code>.


==API endpoints==
[[File:forum_api.png|vignette|250px|Le forum [[Blabla 18-25 ans]] sur le site de l'API.]]
'''URL de base de l'API''': ''<nowiki>https://api.jeuxvideo.com/v4/</nowiki>''  
 
L'API ne fonctionne donc pas que par ''endpoints''.
 
{{clear}}
 
==Endpoints « formels » ==
Il s'agit des ''endpoints'' « documentés » dans le code de l'application mobile et qui se comportent différemment des services de l'API qui ne se content que de « copier » le contenu JVC (voir sous-section précédente).
 
'''URL de base''': ''<nowiki>https://api.jeuxvideo.com/v4/</nowiki>''  


*'''URL''': URL de l'endpoint
*'''URL''': URL de l'endpoint
*'''PARAMS''': Variable entre accolades à remplacer dans l'URL, suivi de son type ''str'' ou ''int''.  
*'''PARAMS''': variable entre accolades à remplacer dans l'URL, suivi de son type ''str'' ou ''int''.  
**<code>contents/{contentID}/comments</code> doit être appelé comme suivant <code>contents/someID1234/comments</code>
**<code>contents/{contentID}/comments</code> doit être appelé comme suivant <code>contents/someID1234/comments</code>
*'''QUERY''': Par exemple pour les deux query '''''page''''' int, '''''perPage''''' int, l'URL devra être: <code>api.jeuxvideo.com/v4/contents/1234ID/comments?page=1&perPage=30</code>
*'''QUERY''': par exemple pour les deux query ''page'', ''perPage'' int, l'URL devra être: <code>api.jeuxvideo.com/v4/contents/1234ID/comments?page=1&perPage=30</code>
*'''BODY''': Corps de la requête au format JSON
*'''BODY''': Corps de la requête au format JSON
Le fichier JSON avec les <code>ids</code> pour les ''params'' et les ''query strings'' <code>chronicles</code> <code>modes</code> <code>genres</code> <code>events</code> <code>machine</code> <code>categories</code> (obtenu via la requête '''GET''' ''config'') https://pastebin.com/L1DXfP0C
Le fichier JSON contenant les <code>id</code> des ''params'' et des ''query strings'' <code>chronicles</code> <code>modes</code> <code>genres</code> <code>events</code> <code>machine</code> <code>categories</code> (obtenu via la requête ''GET config'') est disponible [https://pastebin.com/L1DXfP0C ici].
{| class="wikitable sortable"
{| class="wikitable sortable"
|+POST
|+POST
Ligne 115 : Ligne 226 :
|register
|register
|accounts/register  
|accounts/register  
''l'<nowiki/>'''Header''' doit inclure'' : "Jvc-Auth-Token" : str
''le header doit inclure'' <code>"Jvc-Auth-Token" : str</code>
|
|
|<pre>"email": "email",
|<pre>"email": "email",
Ligne 643 : Ligne 754 :
|'''accountId''' str
|'''accountId''' str
|}
|}
==Rétro-ingénierie de l'API et de l'application JVC==
Pour connaître les endpoints de l'API, il faut décompiler l'appli JVC.
#Décompresser l'APK de l'application avec 7zip/Winrar/etc.
#Utiliser un décompilateur Dex vers Java, comme '''[https://github.com/skylot/jadx Jadx]''' .
====JvApiService====
Une fois le code Java disponible, on peut ouvrir l'interface ''com.jeuxvideo.api.web.'''JvApiService''''', qui contient tous les endpoints. L'appli utilise le bibliothèque [https://square.github.io/retrofit/ Retrofit 2.x] pour gérer l'API, on peut facilement parcourir la documentation de cette bibliothèque pour découvrir ce qu'il faut faire comme requête aux différentes URL de l'API.
''Exemple de code dans l'interface '''JvApiService'''''
<pre>
    @POST("contents/{contentID}/comments")
    Call<UserComment> addComment(@Path("contentID") String str, @Body UserComment.Body body);
    @POST("contents/{contentID}/comments/{commentID}/vote")
    Call<UserComment> addCommentVote(@Path("contentID") String str, @Path("commentID") String str2, @Body UserComment.Vote vote);
</pre>
==== ApiLogin ====
La classe ''com.jeuxvideo.utils.'''ApiLogin''''' (nom de la classe donné arbitrairement car perdu lors de la compilation), permet de déduire qu'il faut mettre dans le header de la requête à l'API ''Jvc-Authorization : '''header''''' ainsi que l'algorithme permettant de trouver ce qu'il faut mettre à la place de '''''header'''''. (Voir code ci-dessous)
<pre>
    public static String f(String str, String str2, String str3, String str4, String str5) {
        StringBuilder sb2 = new StringBuilder();
        sb2.append("550c04bf5cb2b\n");
        sb2.append(str);
        sb2.append("\n");
        sb2.append(str2);
        sb2.append("\n");
        sb2.append(str3);
        sb2.append("\n");
        sb2.append(str4);
        sb2.append("\n");
        if (str5 == null) {
            str5 = "";
        }
        sb2.append(str5);
        String b10 = j5.f.b("d84e9e5f191ea4ffc39c22d11c77dd6c", sb2.toString());
        return "PartnerKey=550c04bf5cb2b, Signature=" + b10 + ", Timestamp=" + str;
    }
</pre>


==Ressources==
==Ressources==
Ligne 688 : Ligne 759 :
*Classe PHP exploitant l'API : https://pastebin.com/LWNDQDKy (Cette classe est incomplète et sera possiblement rendue obsolète dans le temps).
*Classe PHP exploitant l'API : https://pastebin.com/LWNDQDKy (Cette classe est incomplète et sera possiblement rendue obsolète dans le temps).


=Ancienne API=
=Ancienne API (dépréciée) =
{{Bannière Note|Contenu=Le contenu qui va suivre concerne l'ancienne API qui n'existe plus.}}
{{Bannière Note|Contenu=Le contenu qui va suivre concerne l'ancienne API qui n'existe plus.}}
==Identification ==
==Identification ==
Ligne 958 : Ligne 1 029 :
|}
|}


==Reverse-engineering==
== Ancienne rétro-ingéniérie ==
===Décompilation===
===Décompilation===
Cette section concerne la décompilation de l'application Android de JVC sous Linux.
Cette section concerne la décompilation de l'application Android de JVC sous Linux.