跳转到内容

使用 Vimine 登录

查看 Markdown

协会的会员使用自己的 Vimine 账户登录您的网站,并通过明确的同意,授权您使用他们的部分数据。这就是 OAuth 2.1 加 PKCE:密码只在 Vimine 的页面上输入,绝不会在您的页面上输入;您的网站收到的令牌仅限于已授予的权限。

  1. 会员点击后,您的网站把浏览器(顶层窗口,绝不能是 iframe)送到授权页面:
    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. 会员登录(如果尚未登录),并看到谁将获得什么权限。会员确认或取消。
  3. Vimine 把浏览器送回您的 redirect_uri,并带上 code 和 state(或 error=access_denied)。
  4. 您的网站在 POST https://api.vimine.network/v1/oauth/token 交换授权码(grant_type=authorization_code、code、code_verifier、client_id、redirect_uri),获得一个访问令牌(10 分钟)和一个刷新令牌(轮换;30 天,闲置 14 天即失效)。

SDK 会为您完成以上全部步骤。

任意页面
import { Vimine } from '@vimine/sdk';
const vimine = new Vimine({
clientId: 'vmc_…',
redirectUri: 'https://www.example.org/vimine/callback',
scopes: ['profile:read', 'membership:read']
});
// 由点击触发:`returnTo` 是您自己的状态,回调之后会原样交还给您
document.querySelector('#sign-in').addEventListener('click', () => vimine.signIn({ returnTo: location.pathname }));
回调页面
const result = await vimine.handleRedirect(); // URL 中没有登录参数时返回 null
if (result) location.replace(result.returnTo || '/');

signIn() 的选项:

选项 作用
scopes 本次登录要申请的权限(默认:构造函数中的权限,或 profile:read membership:read)
prompt: 'login' 即使存在有效的 Vimine 会话,也强制显示登录表单
prompt: 'consent' 始终显示授权同意页面
returnTo 您自己的状态(例如会员开始登录时所在的页面),保存在本地,由 handleRedirect() 返回

会员取消时,handleRedirect() 抛出 code 为 access_denied 的 VimineError;当返回与本浏览器发起的登录不匹配时,抛出 state_mismatch 或 no_flow。

  • 令牌保存在 sessionStorage 中(每个标签页各自独立)。storage: 'local' 让多个标签页共享令牌并同步退出登录;'memory' 则从不持久保存。您也可以传入自己的适配器。
  • vimine.getAccessToken() 会在令牌到期前 30 秒自动刷新;收到 401 的调用会在刷新后重试一次。重复使用的刷新令牌(例如被复制的令牌)会撤销整个会话家族。
  • vimine.onChange(session => …) 会通知登录、刷新和退出登录。
  • vimine.getSession().sub 是会员在您的协会中的标识(vms_…):长期稳定,在每个协会中都不同,绝不是内部 id。

您可以请求的内容

章节“您可以请求的内容”
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 }); // 状态历史
await vimine.membership.statuto(); // 现行章程,以及会员是否已接受
await vimine.membership.acceptStatuto({ version: 3 }); // statuto:accept
await vimine.membership.request({ accept_statuto: { version: 3 }, privacy_notice: { version: 2 } }); // membership:request → 待处理的会员卡
await vimine.membership.card(); // 会员卡令牌(二维码)及其时间窗口
await vimine.legal.acceptances(); // legal:read → 已接受的内容和尚待确认的内容
await vimine.legal.record({ kind: 'privacy_notice', version: 2 }); // legal:accept → 确认已阅读协会的隐私声明
await vimine.connections.list(); await vimine.connections.revoke('vmc_…');

verdict 是入场时真正要看的结果:valid、expired、statuto_required(重新接受章程已逾期)或 inactive。尚未入会的人也可以登录并使用 membership.request:非会员同样可以同意入会相关的权限;其他权限则要求在该协会持有会员卡。

每个方法的详细说明见 Vimine;响应结构见类型。

await vimine.signOut(); // 撤销 API 会话并将其清除
await vimine.signOut({ everywhere: true }); // 同时结束会员的 Vimine 会话,然后回到您的网站

使用 everywhere 时,浏览器会经过 https://app.vimine.network/oauth/logout?client_id=…&post_logout_redirect_uri=…;返回地址必须位于为该客户端登记的来源上。当会员退出 Vimine 时,其所有应用的 API 会话都会被撤销(单点退出);当会员在已连接的应用中撤销某个应用或重置密码时,也是如此。

如果您无法使用 SDK(其他编程语言、低代码平台),该流程就是标准的 OAuth 2.1。

授权——GET https://app.vimine.network/authorize

参数
client_id 您的 vmc_…
redirect_uri 已登记的地址之一,必须完全一致
response_type code
state 随机值,返回时用于比对
code_challenge、code_challenge_method PKCE,仅支持 S256
scope 以空格分隔的权限
prompt 可选:login、consent
ui_locales 可选:Vimine 支持的语言之一——it(默认)、en、zh-Hans、zh-Hant、fr、es、de、pt-BR

交换——POST https://api.vimine.network/v1/oauth/token,请求体为 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_…" }

刷新——同一端点,使用 grant_type=refresh_token&refresh_token=…&client_id=…:响应中带有一个新的刷新令牌(旧令牌为并发请求再保持有效 15 秒,此后再使用它会撤销整个会话家族)。

撤销——POST /v1/oauth/revoke,参数为 token=…&token_type_hint=refresh_token(RFC 7009)。

发现——GET https://api.vimine.network/.well-known/oauth-authorization-server(RFC 8414)列出端点、scope 和支持的方法。

这些端点的错误采用 OAuth 格式:{ "error": "invalid_grant", "error_description": "…" }。