Sign in with Vimine
Members of an association sign in to your site with their Vimine account and authorise you, with an explicit consent, to use some of their data. It is OAuth 2.1 with PKCE: the password is only ever typed on the Vimine page, never on yours; your site receives tokens limited to the permissions granted.
The flow
Section titled “The flow”- From a member’s click, your site sends the browser (the top window, never an iframe) to the
authorization page:
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
- The member signs in (if not already) and sees who is being granted what. They confirm or cancel.
- Vimine sends the browser back to your
redirect_uriwithcodeandstate(orerror=access_denied). - Your site exchanges the code at
POST https://api.vimine.network/v1/oauth/token(grant_type=authorization_code,code,code_verifier,client_id,redirect_uri) and receives an access token (10 minutes) and a refresh token (rotating; 30 days, 14 of inactivity).
The SDK does all of this for you.
The page’s look
Section titled “The page’s look”The page stays Vimine’s (the address, the logotype, the words and the controls are its own), but it shows your
association: on the left, or at the top on a phone, its logo and its name, your app’s name and the site the member
goes back to, that is the host of your redirect_uri.
In Developers › your app › Look choose:
- a colour: it tints the association’s half and fades into Vimine’s; on the sign-in card it colours only the primary button and the links, darkened or lightened until it reads;
- a typeface, among those Vimine serves itself, for the association’s half.
Light or dark, and the palette, are the member’s: what they chose in Vimine on that device, otherwise Vimine’s palette in their browser’s light or dark. That is why the preview shows both versions and the authorization address carries neither.
If the association’s logo is made for one background only, say so in Association › Details › Logo made for: on the other scheme the page puts it on a plate.
With the SDK
Section titled “With the SDK”import { Vimine } from '@vimine/sdk';
const vimine = new Vimine({ clientId: 'vmc_…', redirectUri: 'https://www.example.org/vimine/callback', scopes: ['profile:read', 'membership:read']});
// from a click: `returnTo` is your own state, you get it back after the callbackdocument.querySelector('#sign-in').addEventListener('click', () => vimine.signIn({ returnTo: location.pathname }));const result = await vimine.handleRedirect(); // null when the URL carries no sign-in parametersif (result) location.replace(result.returnTo || '/');signIn() options:
| Option | Effect |
|---|---|
scopes |
the permissions to ask for in this sign-in (default: the constructor’s, or profile:read membership:read) |
prompt: 'login' |
forces the credential form even with a live Vimine session |
prompt: 'consent' |
always shows the consent screen |
returnTo |
your own state (for instance the page the member started from), kept locally and returned by handleRedirect() |
handleRedirect() throws a VimineError with code access_denied when the member
cancelled, state_mismatch or no_flow when the return does not match a sign-in started from this browser.
The session
Section titled “The session”- Tokens live in
sessionStorage(per tab).storage: 'local'shares them across tabs and syncs sign-out;'memory'never persists them. You can pass an adapter of your own. vimine.getAccessToken()refreshes by itself 30 seconds before expiry; a call that receives 401 is retried once after the refresh. A reused refresh token (a copied one, say) revokes the whole session family.vimine.onChange(session => …)notifies sign-in, refresh and sign-out.vimine.getSession().subis the member’s identifier for your association (vms_…): stable over time, different in every association, never an internal id.vimine.getSession().apsis the association the member signed in to (slug,name,picture_url): show its name and logo beside the member without another call.
What you can ask for
Section titled “What you can ask for”await vimine.me.get(); // profile:readawait vimine.me.update({ phone: '+39 …' }); // profile:writeawait vimine.membership.get(); // membership:read — status, verdict, expires_at, statuto, cardawait vimine.membership.events({ limit: 20 }); // status historyawait vimine.membership.statuto(); // the in-force statuto and whether the member accepted itawait vimine.membership.acceptStatuto({ version: 3 }); // statuto:acceptawait vimine.membership.request({ accept_statuto: { version: 3 }, privacy_notice: { version: 2 } }); // membership:request → pending cardawait vimine.membership.card(); // the card token (QR) and its windowawait vimine.legal.acceptances(); // legal:read → what they accepted and what is still pendingawait vimine.legal.record({ kind: 'privacy_notice', version: 2 }); // legal:accept → acknowledge the association's noticeawait vimine.connections.list(); await vimine.connections.revoke('vmc_…');verdict is what matters at the door: valid, expired, statuto_required (re-acceptance overdue) or
inactive. Someone who is not a member yet can still sign in and use membership.request: consent to the
enrolment permissions is allowed to non-members too; the other permissions require a card in that association.
Every method is detailed in Vimine; the responses in Types.
Signing out
Section titled “Signing out”await vimine.signOut(); // revokes the API session and forgets itawait vimine.signOut({ everywhere: true }); // also ends the member's Vimine session and comes back to your siteWith everywhere the browser goes through
https://app.vimine.network/oauth/logout?client_id=…&post_logout_redirect_uri=…; the return address must be
on an origin registered for the client. When the member signs out of Vimine, every API session of their apps
is revoked (single sign-out); the same happens when they revoke an app from Connected apps or reset their
password.
Without the SDK
Section titled “Without the SDK”If you cannot use the SDK (another language, a low-code platform) the flow is standard OAuth 2.1.
Authorization — GET https://app.vimine.network/authorize
| Parameter | |
|---|---|
client_id |
your vmc_… |
redirect_uri |
one of the registered ones, identical |
response_type |
code |
state |
random value, to compare on return |
code_challenge, code_challenge_method |
PKCE, S256 only |
scope |
space-separated permissions |
prompt |
optional: login, consent |
ui_locales |
optional: one of Vimine’s languages — it (default), en, zh-Hans, zh-Hant, fr, es, de, pt-BR |
Exchange — POST https://api.vimine.network/v1/oauth/token, body application/x-www-form-urlencoded:
grant_type=authorization_code&code=…&code_verifier=…&client_id=vmc_…&redirect_uri=…{ "access_token": "…", "token_type": "Bearer", "expires_in": 600, "refresh_token": "…", "scope": "profile:read membership:read", "sub": "vms_…" }Refresh — same endpoint with grant_type=refresh_token&refresh_token=…&client_id=…: the response carries
a new refresh token (the old one stays valid for 15 seconds for concurrent requests, then reusing it revokes
the whole family).
Revoke — POST /v1/oauth/revoke with token=…&token_type_hint=refresh_token (RFC 7009).
Discovery — GET https://api.vimine.network/.well-known/oauth-authorization-server (RFC 8414) lists
endpoints, scopes and supported methods.
Errors of these endpoints use the OAuth format: { "error": "invalid_grant", "error_description": "…" }.