VDMDéveloppeurs

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.

URL
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=S256

Sur 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.

URL
https://monapp.fr/auth/callback?code=…&state=$STATE
https://monapp.fr/auth/callback?error=access_denied&state=$STATE

4. É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).

Shell
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_VERIFIER

La réponse contient le jeton du membre et son identité :

JSON
{
  "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.

Shell
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)

JavaScript
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();