简而言之:在控制台(lingcode.dev/backends → Authentication)开启 Require MFA for all signed-in users。在应用中,用户登录后调用 client.auth.enrollMfa()(将返回的 otpauthUrl 渲染为二维码供用户用认证 App 扫描),再调用 client.auth.verifyMfa({ code })。启用后,数据 API 会拒绝未完成 TOTP 验证的会话请求。访问令牌有效期较短,SDK 会自动刷新。
仅凭密码,一次凭证泄露就可能酿成安全事故。MFA 增加了第二重验证——来自认证 App 的 6 位动态码(TOTP)——让泄露的密码不再足以入侵账户。在大多数技术栈上,这意味着要额外接入第三方认证服务;而在 LingCode Cloud 后端,用户系统已原生支持 MFA,开启只需一个开关加两行 SDK 调用。
本教程建立在已连接托管后端的基础上,假设用户已通过邮箱/密码、魔法链接、OTP 或社交登录完成注册。MFA 在此之上叠加了 TOTP 第二因素,后端会为每个会话跟踪一个安全等级:普通登录后为 aal1,通过 TOTP 验证后升至 aal2。
进入 lingcode.dev/backends → Authentication,打开 Require MFA for all signed-in users 开关。开启后,数据 API 会拒绝所有未达到 aal2 等级的用户会话请求,并返回 mfa_required 错误——你的应用捕获该错误后,引导用户完成注册/验证流程即可。(关闭时 MFA 为可选:用户仍可自行注册,但不强制执行。)匿名公共访问密钥不受影响——此设置仅限制用户会话,不影响由 RLS 规则管理的匿名读取权限。
用户登录后,提供"开启双重验证"入口。注册操作会返回一个共享密钥和一个 otpauth:// URL——将该 URL 渲染为二维码(任意小型二维码库均可),供用户用 Google Authenticator、1Password 等 App 扫码添加:
const { data } = await client.auth.enrollMfa();
// data.otpauthUrl → render as a QR; data.secret → manual-entry fallback
让用户输入 App 上显示的 6 位动态码并完成验证。首次验证成功即完成注册,并返回一个 aal2 会话,SDK 会自动保存:
const { error } = await client.auth.verifyMfa({ code: userTypedCode });
// no error → session is now aal2; data calls succeed
在后续访问中(或令牌刷新后降回 aal1),受保护的请求会返回 mfa_required;此时调用 client.auth.challengeMfa() 查看用户已注册的验证因素,提示输入动态码,再次调用 verifyMfa 即可。
会话使用短期访问令牌配合轮转刷新令牌。SDK 会在访问令牌过期时透明地自动刷新——如果刷新令牌被重复使用(这是盗用的信号),整个令牌家族将立即失效。你无需手动管理任何这些细节;正因如此,用户才能在无长期令牌暴露于浏览器的情况下保持登录状态。