Playground
可切换区域 / 环境的真实接口测试台。本页演示 @tripo3d/auth v2 的完整接入面:
- showLogin 一键唤起:QuickStartFlow(v2 主推入口)
- 验证码登录 / 注册:CodeFlow(sendCode 自动分流,UI 不再切按钮)
- OIDC 4 模式:OidcFlow(popup / redirect × PC / Mobile)
- Google One Tap 一键登录:OneTapFlow(
promptGoogleOneTap,fire-and-forget 全程静默) - 登录信号 cookie:SignalFlow(实时观察
__tripo_login_signal__+ onLogin handler) - Token 管理:TokenFlow(5 API + in-flight 合并 + 默认/自定义 fetchToken 切换)
- 密码重置:ResetFlow(
auth.reset.sendCode+submitNewPassword)
真实接口
本页直接调用 Tripo 的 Ory 服务(国内 / 海外,多环境可切),操作会真实创建 / 修改账号,请勿对生产环境做随手测试。日志里的密码 / 验证码字段已被打码。
使用要点
区域 / 环境切换 cn / oversea + 4 个 basePath;TripoAuth 整体重建,onLogin / onLogout handler 自动重新注册Session 状态调 auth.token.refresh() 强制拉一次当前 cookie session;显示 JWT 过期倒计时9 张 demo 卡QuickStart / Code / OIDC / One Tap / Signal / Logout / Token / Reset / Settings,每张卡的 handler 都是 v2 最佳实践示范日志面板统一 track() 包装每次 SDK 调用,打印入参、成功结果和错误分类(业务侧不需要 track 包装)
业务可参考的最佳实践
每张 flow 卡片的 handler 可直接照搬到业务侧,下面列出最关键的几条片段(去掉了 playground 的 track 包装)。
1. 一行 showLogin 唤起
import { showLogin } from '@tripo3d/auth/ui';
// v2 的 showLogin 返回 void —— 登录完成统一靠 auth.signal.onLogin(handler) 收尾,
// 业务方不需要 await,也不需要处理 outcome 分支。
showLogin(auth, {
completeUrl: 'https://www.tripo3d.ai/login/oidc', // 必填:OIDC 完成页绝对 URL
locale: 'zh', // 可选:宿主当前语言,playground 演示中文;缺省回落 'en'
params: { fromBanner: 'home_v2' }, // 透传到 signal cookie,onLogin handler 也会拿到
});2. 验证码自动分流
// v2:sendCode 返回 void,SDK 内部 checkIdentifier 自动分流;UI 不再切按钮文案
await auth.login.sendCode({ email });
// submitCode 复用同会话;附带 params 可透传业务字段(来源、邀请码等)
await auth.login.submitCode(
{ code, email },
{ params: { source: 'banner-home' } },
);3. OIDC 发起(4 模式)
// completeUrl 必填(OIDC 完成页绝对 URL);mode 不传 —— SDK 内部按 isMobileUA 推导(mobile→redirect / pc→popup)
// 业务方按返回值 mode 决定开窗策略,不要再自己做 UA 判断
const { url, mode } = await auth.login.startOidc('google', {
completeUrl: 'https://www.tripo3d.ai/login/oidc',
returnTo: `${window.location.origin}/dashboard`,
params: { source: 'banner-home' },
});
if (mode === 'popup') {
window.open(url, 'oidc', 'popup=yes,width=500,height=600');
} else {
window.location.assign(url);
}
// 不需要 await 任何 done Promise——v2 完成靠下面的 onLogin handler 收尾4. Google One Tap 一键登录
// fire-and-forget:用户无感知,失败已在 SDK 内部静默处理(不 report、不 throw)
// 完成同样靠 onLogin handler 收尾(handler 里 signal.provider === 'google')
onMounted(() => {
if (typeof window === 'undefined') return; // SSR 守卫
if (auth.token.peek()) return; // 已登录不打扰
void auth.oidc.promptGoogleOneTap(
{ clientId: GOOGLE_CLIENT_ID }, // Web 类型 OAuth client id,匹配该环境 Kratos 的 google provider
{ params: { traceKey: 'home_one_tap' } }, // 透传到 onLogin handler
).catch(() => {});
});前置条件:
clientId为 Web 类型且匹配环境 google provider、当前页面 origin 已加入该 client 的 Authorized JavaScript origins、浏览器已登录 Google 账号——任一不满足卡不弹(静默,不报错)。常驻卡片(
cancelOnTapOutside: false)在用户改走自家登录入口 / 登录成功后,用auth.oidc.cancelOneTap()主动关闭(同步、fire-and-forget,未弹卡时为安全 no-op)。
5. 全局 onLogin / onLogout handler
// 在 app 启动时注册一次;所有登录路径(code / password / oidc / showLogin)都会经过它
// SDK 在派发前已 await token.refresh(),handler 跑起来 token 直接可用
const unsubLogin = auth.signal.onLogin(({ signal, context }) => {
// signal: { v:1, provider: 'code' | 'password' | 'google' | ..., ts, params? }
// context.isRedirect: 业务页冷启路径 = true;popup / dialog 路径 = false
userStore.markLoggedIn(signal);
void refreshDashboard();
});
// 退出登录:auth.logout() 成功后自动派发,此时 token 已 clear
const unsubLogout = auth.signal.onLogout(() => {
userStore.markLoggedOut();
});
// 业务退出时反订阅(一般不需要)
onUnmounted(() => { unsubLogin(); unsubLogout(); });6. Token 拦截器
// HTTP 拦截器统一这么写就行:临期自动续 + 并发 inflight 合并
fetch.interceptors.request.use(async (config) => {
const token = await auth.token.get();
if (token) config.headers.Authorization = `Bearer ${token}`;
return config;
});
// 401 时刷一次再重试;refresh 失败保留旧 cache,业务侧拿到 undefined 再决定降级
fetch.interceptors.response.use(undefined, async (error) => {
if (error.response?.status === 401) {
await auth.token.refresh();
return fetch.request(error.config);
}
throw error;
});环境配置
预置 4 套环境(在 auth-store.ts 的 ENV_OPTIONS 里维护):
| 环境 | basePath | 说明 |
|---|---|---|
国内测试(cn) | https://auth-cn-test.tripo3d.com | 国内测试集群 |
国内生产(cn) | https://auth-cn.tripo3d.com | 国内正式集群,谨慎操作 |
海外 Staging(oversea) | https://auth-staging.tripo3d.ai | 海外预发布 |
海外生产(oversea) | https://auth.tripo3d.ai | 海外正式集群,谨慎操作 |
浏览器侧通过同源反代访问(${origin}/api/${env.value}/),与 vitepress dev server 的 proxy 配置对齐。v2 已删除全局 loginOrigin:OIDC 完成页地址改为在发起处显式传 completeUrl(绝对 URL)。playground 把 completeUrl 指向自挂的 /auth/playground/oidc-complete。
端到端测试链路
本 playground 已经把 SDK 的三个内置页面都挂成真实路由,OidcFlow 卡会真实开窗 / 跳转,端到端跑通后回到 playground 可在「登录信号」卡看到 onLogin 触发:
| 路由 | 组件 | 说明 |
|---|---|---|
/auth/playground/login?locale=zh | LoginPage | Standalone 登录页(模式 #2/#4);右上角浮层可切 env;?locale=zh 让 LoginPage 渲染中文(缺省回落 'en')。这条链路与「playground 里 showLogin」是两种不同接入。 |
/auth/playground/oidc-complete | OidcCompletePage | OIDC 完成页;completeUrl 指向这里。popup 模式写 cookie 后 window.close(),redirect 模式 location.assign(returnTo)。 |
/login/oidc/edge | OidcEdgePage | OIDC 中间页(continue / merge)。路径由 ory 服务端配置决定,不可改,所以挂在站点根而非 /auth/playground/ 下。 |
这三条路由是 playground 为了端到端联调自挂的;业务方接入时同样需要在自己站点挂
OidcCompletePage(地址即传给 SDK 的completeUrl),OidcEdgePage则挂在与 ory 后台配置一致的路径上。接入细节见 UI 子路径 /ui。
源码参考
Playground.vueQuickStartFlow.vueCodeFlow.vueOidcFlow.vueOneTapFlow.vueSignalFlow.vueTokenFlow.vueResetFlow.vueauth-store.ts
文档侧公开示范
本 playground 是 v2 SDK 的"最佳实践示范",每个 demo 卡的 handler 可直接照搬到业务侧;测试 harness(日志面板、track 包装、env 切换)需要去掉。