Se connecter avec VDM
Avec « Se connecter avec VDM », votre app obtient le jeton d'un membre sans jamais voir son mot de passe : le membre se connecte sur viedemerde.fr et accepte que votre app agisse en son nom. C'est OAuth 2 (code d'autorisation avec PKCE), comme « Se connecter avec Google ». Pour une app destinée à d'autres que vous, préférez-le à la connexion par mot de passe.
1. Activer la connexion pour votre clé
Dans Mes clés, activez « Se connecter avec VDM » sur la clé de votre app et indiquez ses adresses de retour (redirect_uri) : https, http://localhost pour le développement, ou un schéma d'app mobile comme com.monapp:/oauth. Vous obtenez un client_id et, pour une app avec serveur, un client_secret, affiché une seule fois. Une app mobile ou JavaScript ne peut pas garder de secret : cochez l'option sans secret, PKCE suffit.
2. Envoyer le membre sur VDM
Créez un code_verifier aléatoire (43 à 128 caractères) et un state, gardez-les pour l'étape suivante, puis ouvrez cette adresse dans le navigateur. Le code_challenge est le SHA-256 du verifier, encodé en base64url. Le redirect_uri doit être exactement l'une des adresses enregistrées.
https://www.viedemerde.fr/oauth/authorize
?response_type=code
&client_id=$CLIENT_ID
&redirect_uri=https%3A%2F%2Fmonapp.fr%2Fauth%2Fcallback
&state=$STATE
&code_challenge=$CODE_CHALLENGE
&code_challenge_method=S256Sur mobile, ouvrez-la dans le navigateur du système (ASWebAuthenticationSession sur iOS, Custom Tabs sur Android), jamais dans une WebView : le membre doit voir qu'il est bien sur viedemerde.fr.
3. Récupérer le code
Le membre se connecte s'il ne l'est pas, puis accepte ou refuse. VDM le renvoie sur votre redirect_uri, avec le même state : vérifiez-le avant toute chose.
https://monapp.fr/auth/callback?code=…&state=$STATE
https://monapp.fr/auth/callback?error=access_denied&state=$STATE4. Échanger le code contre un jeton
Le code vaut 10 minutes et ne sert qu'une fois. Envoyez-le en formulaire avec le verifier. client_secret est obligatoire pour une app avec serveur, et absent pour une app sans secret (vous pouvez aussi l'envoyer en HTTP Basic).
curl "https://www.viedemerde.fr/oauth/token" \
-d grant_type=authorization_code \
-d code=$CODE \
-d redirect_uri=https%3A%2F%2Fmonapp.fr%2Fauth%2Fcallback \
-d client_id=$CLIENT_ID \
-d client_secret=$CLIENT_SECRET \
-d code_verifier=$CODE_VERIFIERLa réponse contient le jeton du membre et son identité :
{
"access_token": "3f1c9b0e8d7a6f5e4d3c2b1a09f8e7d6",
"token_type": "Bearer",
"scope": "api",
"user": { "id": 123456, "username": "Pseudo" }
}5. Appeler l'API au nom du membre
Envoyez le jeton dans Authorization: Bearer (ou X-VDM-Api-Token), avec votre clé : il ne vaut qu'avec elle. Tous les endpoints de la référence marqués « Jeton membre obligatoire » sont alors accessibles.
curl "https://www.viedemerde.fr/api/v2/user/123456/favorites" \
-H "X-VDM-Api-Key: $API_KEY" \
-H "Authorization: Bearer $ACCESS_TOKEN"Durée et révocation
- Le jeton n'expire pas : gardez-le de façon sûre (trousseau de l'appareil, base chiffrée), comme un mot de passe.
- Il cesse de marcher si le membre se déconnecte de votre app (GET /user/logout), change son mot de passe, ou si vous révoquez votre clé.
- Une réponse 401 sur un endpoint qui demande un jeton : renvoyez le membre à l'étape 2.
Erreurs
/oauth/token répond au format OAuth 2 : {"error": "…", "error_description": "…"}. invalid_client (401) : mauvais client_id ou client_secret, ou clé révoquée. invalid_grant (400) : code expiré, déjà utilisé, ou qui ne correspond pas au verifier ou au redirect_uri. Sur /oauth/authorize, un client_id ou un redirect_uri inconnu s'affiche au membre au lieu de le renvoyer chez vous.
Exemple complet (Node.js)
import { createHash, randomBytes } from "node:crypto";
// 1. Avant de rediriger le membre : un verifier et un state, gardés en session
const verifier = randomBytes(32).toString("base64url");
const state = randomBytes(16).toString("base64url");
const challenge = createHash("sha256").update(verifier).digest("base64url");
const url = new URL("https://www.viedemerde.fr/oauth/authorize");
url.search = new URLSearchParams({
response_type: "code",
client_id: process.env.CLIENT_ID,
redirect_uri: "https://monapp.fr/auth/callback",
state,
code_challenge: challenge,
code_challenge_method: "S256",
}).toString();
// rediriger le navigateur vers url
// 2. Sur redirect_uri : vérifier le state, puis échanger le code
const response = await fetch("https://www.viedemerde.fr/oauth/token", {
method: "POST",
body: new URLSearchParams({
grant_type: "authorization_code",
code,
redirect_uri: "https://monapp.fr/auth/callback",
client_id: process.env.CLIENT_ID,
client_secret: process.env.CLIENT_SECRET, // pas pour une app sans secret
code_verifier: verifier,
}),
});
const { access_token, user } = await response.json();