Skip to content

Auth ​

@tripo3d/auth · 基于 Ory Kratos 的统一认证 SDK。v2 把登录流程、UI 组件、跨端登录信号、token 缓存收敛成 6 个稳定的 namespace,浏览器端按需引入即用。

特性 ​

🔑

Namespace 化 API

一个 TripoAuth 实例下挂 login / oidc / reset / settings / signal / token 六个 namespace + 顶层 logout,调用形态统一为 auth.{ns}.{verb}()。

🚦

自动分流登录

login.sendCode / submitCode 内部自动判定 login / registration,业务一套表单覆盖两种身份。

🪟

4 种 OIDC 模式

popup × dialog/standalone × pc/mobile 组合:startOidc({ mode }) 一键切换;mobile 自动降级 redirect。

📡

Cookie 登录信号

跨标签 / 跨子域统一通过 __tripo_login_signal__ cookie 竞争认领;onLogin(handler) 注册实例回调,无 postMessage 跨域协议。

🎨

开箱即用 UI

子路径 /ui 暴露 LoginPage / OidcCompletePage / OidcEdgePage 三个页面组件 + 命令式入口 showLogin()(内部挂 LoginDialog,不直接对外);i18n 11 语言内置。

🎫

可定制 Token

默认走 ory toSession({ tokenizeAs: 'default_jwt' });业务方传 fetchToken 即可走自家 BFF 网关;过期前 60s 自动续期,logout 自动清缓存。

安装 ​

请先完成 GitHub Packages 认证配置。

bash
pnpm add @tripo3d/auth

快速开始 ​

ts
import { TripoAuth } from '@tripo3d/auth';

const auth = new TripoAuth({
  basePath: 'https://auth.tripo3d.ai',
  onError: (err) => { /* 可选:监控 SDK 非阻塞运营错误 */ },
});

// 业务方注册当前实例的登录回调;登录信号通过 cookie 在同根域竞争认领
// SDK 在派发前已确保 token 就绪,handler 跑起来 token 直接可用
auth.signal.onLogin(async ({ signal, context }) => {
  console.log('用户已登录', signal.provider, '冷启路径=', context.isRedirect);
  await initUser();
});

// 退出登录订阅;auth.logout() 成功后自动派发(token 已 clear)
auth.signal.onLogout(() => clearLocalUserStore());

// 唤起登录对话框(来自 /ui 子路径);params 通过信号 cookie 透传给 onLogin handler
// showLogin 返回 void —— 登录完成统一靠上面的 onLogin handler 收尾
import { showLogin } from '@tripo3d/auth/ui';
showLogin(auth, {
  completeUrl: 'https://www.tripo3d.ai/login/oidc',  // 必填:OIDC 完成页绝对 URL
  params: { fromBanner: 'home_v2' },
});

// 后续请求拦截器里按需读 token(默认实现 = 调 ory toSession,过期前 60s 自动续期)
const token = await auth.token.get();

➡️ 更多接入细节看 5 分钟接入。

业务面一览 ​

业务侧实际只面对 6 个 namespace + 1 个顶层方法。

ts
class TripoAuth {
  readonly login:    LoginApi      // sendCode / submitCode / submitPassword / startOidc
  readonly signal:   SignalApi     // onLogin/onLogout / emitLogin/emitLogout / publishLogin/consumeSignal / readSignal/readSignalRecord/writeSignal/clearSignal
  readonly oidc:     OidcApi       // handleComplete / loadEdgeFlow / promptGoogleOneTap / submitIdToken
  readonly reset:    ResetApi      // 未登录恢复:sendCode / verifyCode / submitNewPassword
  readonly settings: SettingsApi   // 已登录改密码:sendVerifyCode / verifyCode / updatePassword
  readonly token:    TokenApi      // peek / set / clear / get / refresh

  logout(): Promise<void>          // 失效 ory session + clearSignal + emitLogout(内部 token.clear)
}

UI 部分作为独立子路径 @tripo3d/auth/ui 导出,业务方可选用:

ts
import {
  showLogin,             // 命令式:挂载 LoginDialog 弹出登录
  LoginPage,             // 独立登录页(standalone 模式);:auth prop 传入 TripoAuth
  OidcCompletePage,      // OIDC 完成页;:auth prop 同上
  OidcEdgePage,          // OIDC 中间页(continue / merge);:auth prop 同上
  DEFAULT_LOCALE,        // 默认 locale 'en'
  SUPPORTED_LOCALES,     // 11 个 locale 列表
} from '@tripo3d/auth/ui';

import type { LocaleInput } from '@tripo3d/auth/ui';
// LocaleInput = LoginLocale | (string & {})  // showLogin({ locale }) 的参数类型;详见 UI 指南

推荐接入模型 ​

1. 命令式唤起登录对话框 ​

ts
// 在业务任意位置一键弹出登录 dialog;返回 void,登录完成走 onLogin 通知
// dialog 显示语言取 options.locale(宿主显式传入,缺省 'en'),params 透传到 onLogin handler
showLogin(auth, {
  completeUrl: 'https://www.tripo3d.ai/login/oidc',  // 必填:OIDC 完成页绝对 URL
  locale: 'ja',                                      // 可选:宿主当前 i18n locale;缺省回落 'en'
  params: { fromBanner: 'home_v2' },
});

2. 验证码登录(自动分流) ​

ts
// SDK 内部 checkIdentifier 决定走 login 还是 registration
await auth.login.sendCode({ email: 'user@example.com' });

// submitCode 复用 sendCode 的活跃会话;transientPayload 透传给本次提交(与构造期 deviceId 合并,deviceId 优先)
await auth.login.submitCode(
  { code: '123456', email: 'user@example.com' },
  { transientPayload: { receiveMarketing: true } },
);

3. OIDC 登录(4 种模式) ​

ts
// mode 由 SDK 内部按 isMobileUA 推导,业务方不用自己选;按返回值 mode 决定开窗策略
const { url, mode } = await auth.login.startOidc('google', {
  completeUrl: 'https://www.tripo3d.ai/login/oidc',  // 必填,绝对 URL
  returnTo: 'https://studio.tripo3d.ai/dashboard',
});

if (mode === 'popup') {
  window.open(url, '_blank', 'popup,width=500,height=600');
} else {
  window.location.assign(url);
}

不论哪种模式,OIDC 三方回调后落到 OidcCompletePage,SDK 自动写 cookie 信号;主窗的 onLogin(handler) 收到信号触发业务侧 refresh token / 关 dialog。

4. 全局监听登录信号 ​

ts
const unsubscribe = auth.signal.onLogin(async ({ signal, context }) => {
  // SDK 在派发前已 await token.refresh() 兜底;业务侧 token.get() 直接拿得到
  await fetchCurrentUser();
  if (context.isRedirect) {
    // 业务页冷启路径(独立页 / OIDC redirect 跳回来的)
  }
});

onLogin 通过 cookie polling + 启动时 cookie 捕获双通道:

  • 同标签登录立即触发
  • 跨标签共享同一 cookie 待办,由其中一个实例认领;不保证每个 tab 都触发
  • 跨子域(如独立登录页 → 业务子域)通过同 site cookie 触发
  • 业务页冷启时构造期 readSignalRecord() 捕获未派发信号;有效窗口内每个晚注册的 onLogin handler 都通过 microtask 收到一次定向补偿(context.isRedirect=true)

若需要所有已打开 tab 立即刷新用户态,请在收到 onLogin 后由宿主通过 BroadcastChannel 或 storage 事件二次广播;否则其他 tab 会在后续 session/token 请求中自然感知。

5. Token 自定义来源(业务自家网关) ​

ts
const auth = new TripoAuth({
  basePath,
  // 默认走 ory toSession;业务有自家 BFF 网关时覆盖
  fetchToken: async (fetcher) => {
    const res = await fetcher(`${apiUrl}/whoami?tokenizeAs=default_jwt`, { method: 'GET' });
    return res.ok ? (await res.json()).tokenized : undefined;
  },
});

下一步 ​

基于 MIT 协议发布(内部使用)