Aller au contenu

Se connecter avec Vimine

Afficher en Markdown

Les membres d’une association se connectent à votre site avec leur compte Vimine et vous autorisent, par un consentement explicite, à utiliser certaines de leurs données. C’est OAuth 2.1 avec PKCE : le mot de passe n’est jamais saisi ailleurs que sur la page Vimine, jamais sur la vôtre ; votre site reçoit des jetons limités aux autorisations accordées.

  1. À partir d’un clic du membre, votre site envoie le navigateur (la fenêtre principale, jamais une iframe) vers la page d’autorisation :
    https://app.vimine.network/authorize
    ?client_id=vmc_…&redirect_uri=https://www.example.org/vimine/callback
    &response_type=code&state=…&code_challenge=…&code_challenge_method=S256
    &scope=profile:read%20membership:read
  2. Le membre se connecte (s’il ne l’est pas déjà) et voit à qui il accorde quoi. Il confirme ou annule.
  3. Vimine renvoie le navigateur vers votre redirect_uri avec code et state (ou error=access_denied).
  4. Votre site échange le code sur POST https://api.vimine.network/v1/oauth/token (grant_type=authorization_code, code, code_verifier, client_id, redirect_uri) et reçoit un jeton d’accès (10 minutes) et un jeton de rafraîchissement (qui change à chaque usage ; 30 jours, 14 d’inactivité).

Le SDK fait tout cela pour vous.

n’importe quelle page
import { Vimine } from '@vimine/sdk';
const vimine = new Vimine({
clientId: 'vmc_…',
redirectUri: 'https://www.example.org/vimine/callback',
scopes: ['profile:read', 'membership:read']
});
// depuis un clic : `returnTo` est votre propre état, vous le récupérez après le callback
document.querySelector('#sign-in').addEventListener('click', () => vimine.signIn({ returnTo: location.pathname }));
page de callback
const result = await vimine.handleRedirect(); // null quand l’URL ne porte aucun paramètre de connexion
if (result) location.replace(result.returnTo || '/');

Options de signIn() :

Option Effet
scopes les autorisations à demander pour cette connexion (par défaut : celles du constructeur, ou profile:read membership:read)
prompt: 'login' force le formulaire d’identifiants même avec une session Vimine active
prompt: 'consent' affiche toujours l’écran de consentement
returnTo votre propre état (par exemple la page d’où le membre est parti), conservé localement et renvoyé par handleRedirect()

handleRedirect() lève une VimineError avec le code access_denied quand le membre a annulé, state_mismatch ou no_flow quand le retour ne correspond pas à une connexion lancée depuis ce navigateur.

  • Les jetons vivent dans sessionStorage (par onglet). storage: 'local' les partage entre les onglets et synchronise la déconnexion ; 'memory' ne les conserve jamais. Vous pouvez passer un adaptateur à vous.
  • vimine.getAccessToken() rafraîchit de lui-même 30 secondes avant l’expiration ; un appel qui reçoit 401 est réessayé une fois après le rafraîchissement. Un jeton de rafraîchissement réutilisé (copié, par exemple) révoque toute la famille de sessions.
  • vimine.onChange(session => …) signale la connexion, le rafraîchissement et la déconnexion.
  • vimine.getSession().sub est l’identifiant du membre pour votre association (vms_…) : stable dans le temps, différent dans chaque association, jamais un identifiant interne.
await vimine.me.get(); // profile:read
await vimine.me.update({ phone: '+39 …' }); // profile:write
await vimine.membership.get(); // membership:read — status, verdict, expires_at, statuto, card
await vimine.membership.events({ limit: 20 }); // historique des états
await vimine.membership.statuto(); // le statuto en vigueur et si le membre l’a accepté
await vimine.membership.acceptStatuto({ version: 3 }); // statuto:accept
await vimine.membership.request({ accept_statuto: { version: 3 }, privacy_notice: { version: 2 } }); // membership:request → carte en attente
await vimine.membership.card(); // le jeton de la carte (QR) et sa fenêtre
await vimine.legal.acceptances(); // legal:read → ce qu’il a accepté et ce qui reste en attente
await vimine.legal.record({ kind: 'privacy_notice', version: 2 }); // legal:accept → prendre acte de la notice de l’association
await vimine.connections.list(); await vimine.connections.revoke('vmc_…');

verdict est ce qui compte à l’entrée : valid, expired, statuto_required (nouvelle acceptation en retard) ou inactive. Une personne qui n’est pas encore membre peut tout de même se connecter et utiliser membership.request : le consentement aux autorisations d’adhésion est permis aussi aux non-membres ; les autres autorisations exigent une carte dans cette association.

Chaque méthode est détaillée dans Vimine ; les réponses dans Types.

await vimine.signOut(); // révoque la session API et l’oublie
await vimine.signOut({ everywhere: true }); // met aussi fin à la session Vimine du membre et revient sur votre site

Avec everywhere, le navigateur passe par https://app.vimine.network/oauth/logout?client_id=…&post_logout_redirect_uri=… ; l’adresse de retour doit se trouver sur une origine enregistrée pour le client. Quand le membre se déconnecte de Vimine, toutes les sessions API de ses applications sont révoquées (déconnexion unique) ; il en va de même quand il révoque une application depuis Applications connectées ou qu’il réinitialise son mot de passe.

Si vous ne pouvez pas utiliser le SDK (un autre langage, une plateforme low-code), le flux est de l’OAuth 2.1 standard.

Autorisation — GET https://app.vimine.network/authorize

Paramètre
client_id votre vmc_…
redirect_uri l’une de celles enregistrées, à l’identique
response_type code
state valeur aléatoire, à comparer au retour
code_challenge, code_challenge_method PKCE, S256 uniquement
scope autorisations séparées par des espaces
prompt facultatif : login, consent
ui_locales facultatif : une des langues de Vimine — it (par défaut), en, zh-Hans, zh-Hant, fr, es, de, pt-BR

Échange — POST https://api.vimine.network/v1/oauth/token, corps application/x-www-form-urlencoded :

grant_type=authorization_code&code=…&code_verifier=…&client_id=vmc_…&redirect_uri=…
réponse
{ "access_token": "…", "token_type": "Bearer", "expires_in": 600, "refresh_token": "…",
"scope": "profile:read membership:read", "sub": "vms_…" }

Rafraîchissement — même endpoint avec grant_type=refresh_token&refresh_token=…&client_id=… : la réponse porte un nouveau jeton de rafraîchissement (l’ancien reste valable 15 secondes pour les requêtes concurrentes, puis le réutiliser révoque toute la famille).

Révocation — POST /v1/oauth/revoke avec token=…&token_type_hint=refresh_token (RFC 7009).

Découverte — GET https://api.vimine.network/.well-known/oauth-authorization-server (RFC 8414) liste les endpoints, les scopes et les méthodes prises en charge.

Les erreurs de ces endpoints suivent le format OAuth : { "error": "invalid_grant", "error_description": "…" }.