# @faable/auth-js 中文文档

规范地址：https://npmcn.com/package/%40faable/auth-js/

版本：3\.2\.3
npm 元数据更新时间：2026-11-04T13:34:49.051Z
中文译文更新时间：2026-11-14T07:39:48.637Z
软件包许可：MIT

本文由上游 README 翻译，可能存在偏差，请结合原文核对 API、命令与配置。版权与许可归原作者所有。

原始 npm 页面：https://www.npmjs.com/package/%40faable/auth-js
原文对照：https://npmcn.com/package/%40faable/auth-js/?lang=original
项目主页：https://github.com/faablecloud/auth-js#readme
源码仓库：https://github.com/faablecloud/auth-js

## 关键信息（来自 npm 元数据）

- 包体积（解压后）：1.2 MB，49 个文件
- 模块格式：ES Module
- TypeScript 类型：包内自带
- 运行依赖：1 个
- peer 依赖：next \>=13
- 首次发布：2024-05-28T10:56:29.165Z
- 最新版本发布：2026-11-04T13:34:48.640Z
- 近 30 天下载量：2687（2026-10-14 至 2026-11-12，npm 官方下载统计）
- 已发布版本数：84（近 12 个月 68 个）

## 中文简介

[![](https://www.faable.com/assets/logo/Emblem.png)](https://faable.com/)

### [异类](https://faable.com/)

[](https://faable.com/)

## 安装

```sh
npm install @faable/auth-js
```

也可以使用：`pnpm add @faable/auth-js`、`yarn add @faable/auth-js`、`bun add @faable/auth-js`

## README

[![](https://www.faable.com/assets/logo/Emblem.png)](https://faable.com/)

### [异类](https://faable.com/)

[](https://faable.com/)

[](https://faable.com/)

# [授权-js](https://faable.com/)

[](https://faable.com/)

用于 Faable Auth 的异构 JavaScript 客户端 .

[![](https://img.shields.io/npm/v/@faable/auth-js.svg?style=for-the-badge&labelColor=000000)](https://www.npmjs.com/package/@faable/auth-js)

完整文档 [faable.com/docs (英语)](https://faable.com/docs)

## 特征

-   OAuth 社交连接( Google, GitHub, .) 与 PKCE 和 暗流
-   用户名+密码登录
-   无密码:电子邮件魔法链接和OTP代码
-   以跨 Tab 同步方式通过 `BroadcastChannel`
-   可插式存储适配器`localStorage`,饼干,或自定义)
-   Next.js 服务器侧会话助手

## 安装

```bash
npm install @faable/auth-js
```

需要节点.js `>=22.8` 促进发展。 已发布的捆绑在任意 现代浏览器和在节点/SSR环境中.

## 快开始

```ts
import { createClient } from '@faable/auth-js'

export const auth = createClient({
  domain: '<faableauth_domain>',
  clientId: '<client_id>',
  redirectUri: window.location.origin
})

// Trigger a social login
await auth.signInWithOauthConnection({ connection: 'google' })
```

## 配置

`createClient(config)` 接受:

| 选项 | 类型 | 说明 |
| --- | --- | --- |
| `domain` | `string` | **要求.** 你的法奥思租户领地。 议定书是任择性的—— `tenant.auth.faable.link` 财务报告和审定财务报表 `https://tenant.auth.faable.link` 等同起来. |
| `clientId` | `string` | **要求.** 应用程序客户端ID. |
| `redirectUri` | `string` | 默认回调 URL 。 倒计时 `window.location.origin`。 。 。 . |
| `scope` | `string` | 空相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相 默认为 `openid profile email`。 。 。 . |
| `storage` | `SupportedStorage` | 自定义存储适配器 。 默认为 `localStorage`。 。 。 . |
| `storageKey` | `string` | 存储密钥的前缀 。 最后键是 `${storageKey}-${clientId}`。 。 。 . |
| `cookieOptions` | `CookieOptions` | 设定时,将存储器切换到饼干适配器. |
| `lock` | `LockFunc` | 自定义锁定原始同时刷新 . |
| `debug` | `boolean` | 启用动词记录 . |

## 认证流量

### OAuth / 社会联系

```ts
// The tenant's hosted login (signs in silently with a live SSO session)
await auth.signIn()

// Or pick a specific provider (by name or connection_id)
await auth.signInWithOauthConnection({
  connection_id: 'conn_01HX…', // preferred when known; falls back to `connection` for legacy tenants
  redirectTo: 'https://app.example.com/callback',
  scopes: 'openid profile email',
  queryParams: { prompt: 'select_account' }
})
```

在浏览器中,SDK默认使用PKCE流并交换 `code` (单位:千美元) 在调用页面上。 第一个呼叫 `createClient` 自动 当用户返回重定向目标时处理 URL.

在重定向成功路径上,返回的承诺 **未解决** - 那个 浏览器已经导航了, 所以装入状态您会绑定到 `await` 直到页面卸下,而不是闪回闲置。 别 可在 `await` 在这条路上.

自行控制导航(例如自定义时间,或非重定向) 运行时间,通过 `skipBrowserRedirect: true`。然后,该呼吁与 授权 URL 并留给您导航 :

```ts
const { data, error } = await auth.signInWithOauthConnection({
  connection: 'google',
  skipBrowserRedirect: true
})
if (error) throw error
window.location.assign(data.url)
```

#### 当回程出现错误时

被拒绝的登录或链接( 行动拒绝, 身份已经与另一个连接) user...)返回到您的重定向目标 `?error=…`和承诺 左边的电话和导航器一起死了 每页装入一次 `getRedirectError()`它带有浏览器对往返的记忆 失败: 连接, 是否为 `linkOauthConnection`,则 `appState` 这是从开始的.

```ts
await auth.linkOauthConnection({
  connection_id: GOOGLE,
  appState: { provider: 'google' }
})

// Back on the page:
const err = await auth.getRedirectError()
if (err?.error_code === 'identity_already_linked') {
  toast(`That ${err.appState?.provider} account belongs to another user`)
}
```

每个客户端都有一个错误 `storageKey`,且仅限 一个呼叫者得到它: 第二个呼叫—— 另一个客户端实例, 或 React PrintMode 运行两次效果——获得 `null`。 。 。 .

### 用户名+密码

```ts
await auth.signInWithUsernamePassword({
  username: 'user@example.com',
  password: '••••••••',
  redirectTo: 'https://app.example.com/callback'
})
```

### 无密码(魔法链接或检察官办公室)

```ts
// Step 1 — request a code or link
await auth.signInWithPasswordless({
  email: 'user@example.com',
  type: 'code' // or "link"
})

// Step 2 — complete the login with the OTP the user received
const { data, error } = await auth.signInWithOtp({
  username: 'user@example.com',
  otp: '123456'
})
```

发送的代码会被记住直到它用完, 所以要求它的屏幕可以 重新装入后, 从另一个标签中取出, 或在应用中取出 浏览器登录在用户读取电子邮件时关闭打开 。 任意 签入或签出客户 忘了它.

```ts
const pending = await auth.getPendingPasswordless()
if (pending) showCodeStep(pending.email, pending.sent_at)

// "Change email"
await auth.clearPendingPasswordless()
```

`signInWithPasswordless` 还要 `authParams` (账户概况) 代码创建, `resumeUrl` (你的一页,代码电子邮件链接回,在一个 (a) 客户的注册籍)和 `appState` (按待决代码, 从未发送). `resumePasswordless({ email, sent_at })` 记录此代码 浏览器没有要求, 例如其电子邮件链接到 `resumeUrl`。 。 。 .

### 密码重置

```ts
await auth.changePassword({ email: 'user@example.com' })
```

### 账户:密码、配置、链接账户和会话

登录用户会话时, 不 `client_secret` 没有管理 API :

```ts
// "Set a password" or "Change password"?
const { data } = await auth.getCredentials()
// data: { has_password: false, connections: [{ id, name, type: 'google_oauth2' }] }

// Change it (the current password is required)…
await auth.setPassword({ password: next, current_password: current })

// …or set the first one. That needs a verified email and a recent sign-in
// (with the second factor, if the user has one); otherwise `reauth_required`.
const { error } = await auth.setPassword({ password: next })
if (error?.code === 'reauth_required') {
  await auth.authorize({ queryParams: { max_age: '0' } })
}

// Name, company and country, and the app's own profile fields (in
// user_metadata["faable.com/fields"]; only keys declared in the client's or
// tenant's `profile_fields` are accepted). Keys left out are not touched.
await auth.updateProfile({
  name: 'Ada Lovelace',
  country_iso: 'GB',
  fields: [{ key: 'profile', value: 'teacher' }]
})

// One field at a time (null removes it), and reading it back. The session's
// user is updated on the spot, so getSession() sees the new value too.
await auth.updateProfileField('profile', 'teacher')
const profile = await auth.getProfileField('profile') // 'teacher'

// Unlink a Google, GitHub or GitLab account (a connection id from
// getCredentials). Refused when it is the user's last way to sign in.
const { error: unlinkError } = await auth.unlinkIdentity(connection_id)
if (unlinkError?.code === 'last_sign_in_method') {
  // Ask them to set a password or link another account first.
}

// Where the user is signed in, and "sign out everywhere else".
const { data: sessions } = await auth.listSessions()
// sessions: { results: [{ id, user_agent, ip, last_seen_at, … }], current_session_id }
const { data: ended } = await auth.revokeOtherSessions() // { revoked: 2 }

// Delete the account. Permanent: confirm first. Clears the local session and
// emits SIGNED_OUT.
await auth.deleteAccount()
```

设置或更改密码将用户从每个密码中标记出去 **其他项目** 第二届会议 并发给他们一封安全邮件.

### 签字

默认 `signOut()` 签名用户退出 **仅此应用程序**:它的新鲜度 auth 服务器上撤销了指针并清除了存储,而不离开 页 次 租户的SSO会话会留下,所以用户的其他应用软件都一样 房客(你的仪表板,你的文件... ) 让他们签到,然后签到 这里不问就回来.

为了结束SSO会议,通过 `scope: 'global'`在浏览器中 **导航页面到认证服务器 `/logout`**因为SSO饼干 生活在认证域和跨源 `fetch` 既不能发出,又不能发出 这个.

```ts
await auth.signOut() // this app only; other apps of the tenant stay signed in
await auth.signOut({ scope: 'global' }) // + the SSO session: redirects to /logout
await auth.signOut({ scope: 'global', returnTo: 'https://app.example.com/bye' })
await auth.signOut({ scope: 'local' }) // only this device's storage, server not told
await auth.signOut({ scope: 'others' }) // every OTHER device; this one stays signed in
await auth.signOut({ scope: 'global', redirect: false }) // legacy: best-effort fetch
```

范围: `app` (默认)撤销了此应用程序的刷新令牌并清除了它的存储. `global` 结束 **此浏览器** 在 auth 服务器上进行会话, 所以每次刷新 从那时起,每个应用软件, 和浏览器, 导航到 `/logout`。 。 。 . `local` 只清除存储; 服务器未被告知. `others` 电话 `POST /me/sessions/revoke-others`: 其他届会 用户端, 本地端留下, 否 `SIGNED_OUT` 火灾.

> **从 2. x 升级 :** `signOut()` 曾经的意思 `scope: 'global'`时 退出按钮应结束SSO会话, 通过 `{ scope: 'global' }`。 。 。 .

`returnTo` 地图到 OIDC `post_logout_redirect_uri` 财务报告和审定财务报表 **必须登记 作为客户端的登录 URL**,或服务器响应 `400`。 。 。 .

在重定向路径上,返回的保证不能解析(浏览器是 导航)——在完成后不再重新启用UI `await`来驱动 自己导航, 以 `getLogoutUrl`数字 :

```ts
window.location.assign(
  auth.getLogoutUrl({ returnTo: 'https://app.example.com' })
)
```

### 没有登录屏幕的令牌

`getTokenSilently()` 返回实时访问符或无法存在的原因 一个 它首先刷新(`refresh_token` 给予, 不导航; 当刷新时 拒绝——没有会话,或者会话被别处的签出取消,a 管理员,或后通道登录——它发送浏览器通过 `/authorize?prompt=none` 作为 **顶级导航** (无iframe:第三方) 饼干阻断使一个不可靠。 认证服务器将用户签回 从它的SSO饼干 没有屏幕,降落在您身上 `redirectUri`,与 用户在 `returnTo`在这条道路上,承诺永远无法实现.

```ts
const { data, error } = await auth.getTokenSilently()
if (error) {
  // `login_required`: the SSO session is gone too — show a login.
  if (error.code === 'login_required') auth.authorize({ response_type: 'code' })
  return
}
fetch('/api/me', { headers: { Authorization: `Bearer ${data.access_token}` } })
```

过 `{ redirect: false }` 获取 `AuthLoginRequiredError` 代替 导航 页面负载本身是拒绝的默想返回 (单位:千美元)`?error=login_required`永远不再导航.

## 处理错误

客户有 **一项统一适用的错误合同**: 每个同步 方法解决方式 `{ data, error }` 财务报告和审定财务报表 **从不为预期投出 失败** (不良的资质,错误的OTP,缺失会话,网络错误. ). 打开 成功 `error` 实值 `null`; 失败时 `data` 实值 `null` 财务报告和审定财务报表 `error` 是一个 `AuthError`。总是检查 `error` 读取前 `data`数字 :

```ts
const { data, error } = await auth.signInWithOtp({ username, otp })
if (error) {
  showError(error.message)
  return
}
useSession(data.session)
```

唯一能抛出的东西是 `createClient` 本身,并且只为 配置错误( 缺失) `domain` 编号 : `clientId`)——你修补的编程错误 一次,不是一个运行时间条件 赶上.

这适用于 `signInWithOauthConnection`, (中文(简体) ), `signInWithUsernamePassword`, (中文(简体) ), `signup`, (中文(简体) ), `signupAndLogin`, (中文(简体) ), `signUp`, (中文(简体) ), `signInWithOtp`, (中文(简体) ), `signInWithPasswordless`, (中文(简体) ), `changePassword`, (中文(简体) ), `changeEmail`, (中文(简体) ), `signOut`, (中文(简体) ), `getSession`, (中文(简体) ), `getClaims`, (中文(简体) ), `setSession`, (中文(简体) ), `refreshSession`, (中文(简体) ), `initialize` 财务报告和审定财务报表 `handleRedirectCallback`他们 返回类型(`AuthResult<T>`, (中文(简体) ), `AuthResponse`, (中文(简体) ), `OAuthResponse`)都是变体 形状相同.

### 更喜欢投球吗? 使用 `unwrap`

如果您的代码路径宁愿让错误传播( 服务器处理器, a) `try/catch`将一切正常投放的包装纸 将呼叫包入 `unwrap` 而不是手写 `if (error) throw error`数字 :

```ts
import { unwrap } from '@faable/auth-js'

// returns data on success, throws the AuthError on failure
const { session } = unwrap(await auth.signInWithOtp({ username, otp }))
```

## 会话和状态变化

```ts
// Get the current session (refreshes if needed)
const {
  data: { session }
} = await auth.getSession()

// Subscribe to auth events
const {
  data: { subscription }
} = auth.onAuthStateChange((event, session) => {
  // event: INITIAL_SESSION | SIGNED_IN | SIGNED_OUT | TOKEN_REFRESHED | PASSWORD_RECOVERY | USER_UPDATED
})

// Stop listening
subscription.unsubscribe()

// Force a refresh
await auth.refreshSession()
```

使用标签播放认证事件 `BroadcastChannel`,所以一个登录或 在一个分页中签出,则在使用同一分页的其他分页中反映 `storageKey`。 。 。 .

### 读取令状索赔

习惯声称你的房客在访问符上贴上连接 `claims_mapping` 或动作 `api.accessToken.setCustomClaim` ——已有 两种方式:

-   在用户上 : `/me` 返回它们为顶级属性,所以 `session.user['ciapol.com/station_id']` 刚刚工作.
-   从符文中解码,没有请求:

```ts
// Typed by namespace; refreshes an expired session first, like getSession()
const { data } = await auth.getClaims<{ 'ciapol.com/station_id': string }>()
data.claims?.['ciapol.com/station_id'] // 'station_123456789'
data.claims?.scope // standard claims are typed too

// One claim, or null when signed out / absent
const station = await auth.getClaim<string>('ciapol.com/station_id')
```

令牌被解码,而不是签名验证:对UI和路由的使用要求 决定,绝不作为授权——这是资源服务器的工作. 自定义 权利主张在登录时被冻结,在刷新后幸存;在下一个时变化 注册.

### 角色和权限

用你的爱皮 `token_dialect` 设置为 `access_token_authz`,访问符 携带一个 `permissions` 索赔; 与 `include_roles_in_access_token`页:1 `roles` 索赔。 询问 Api 用 `audience` 当亚庇启用RBAC时, 请求作为范围所需的权限: 符号带有用户的 角色授予.

```ts
const auth = createClient({
  domain: 'https://my-tenant.auth.faable.link',
  clientId: '…',
  audience: 'https://api.example.com',
  scope: 'openid profile email invites:read invites:write'
})

if (await auth.hasPermission('invites:write')) showInviteButton()
const isStaff = await auth.hasRole('staff')
```

两者都要求 **全部** 你通过的价值。 喜欢 `getClaims`他们解码 符号而不验证: 显示 UI 的罚款, 但是您的 API 必须检查 符号本身( e)`verifyAccessToken` 财务报告和审定财务报表 `requirePermissions` 内 `@faable/auth-sdk`) (中文(简体) ). 纯洁的助手 `permissionsOf`, (中文(简体) ), `hasPermissions` 财务报告和审定财务报表 `hasRoles` 处理任何已解码的索赔.

## 存储适配器

### 权衡

刷新符号很敏感:任何读取它们的人都可以冒充用户 直到吊销该标志。 你选的仓库决定他们住在哪里:

-   **`localStorage` (默认)** – 简单并支持跨tab同步通过 `BroadcastChannel`,但运行在同一源代码上的任何脚本都可以读取. **A 类 单 XSS 允许攻击者去过滤刷新符.** 可接受 低风险应用程序和原型;当表面有第三方时不推荐 脚本,由用户生成的HTML,或严格的遵从要求.
-   **饼干** —— SSR(服务器在每次请求中都读取)和 只有适配器允许您使用 `Secure`, (中文(简体) ), `SameSite`,以及 `Domain`。请注意,这个库是从 JavaScript 写的 cookie,所以 无法标记 `HttpOnly`; XSS 还可以读取, 但 cookie 制作 CSRF 和以某种方式可执行的同一地点政策 `localStorage` 没有.
-   **自定义适配器** - 用于内存存储(在重新装入时丢失、最安全的纸箱) 针对XSS),Web Workers,或针对平台的密钥链.

如果您的应用程序被曝光到不可信内容, 则选择 cookie `Secure: true` 财务报告和审定财务报表 `SameSite: "Lax"` (或 `"Strict"`),治疗XSS预防(CSP,出逃, 框架保障)作为一个硬性要求,无论您是哪一个适配器 选择.

### 本地服务器( 默认)

在浏览器中自动使用. 不需要配置 .

### 饼干

用于服务器必须从请求中读取会话的 SSR 设置 .

```ts
import { createClient } from '@faable/auth-js'

export const auth = createClient({
  domain: '<faableauth_domain>',
  clientId: '<client_id>',
  storage: 'cookie'
})
```

就是这样。 适配器设置合理的默认值 : `Path=/`, (中文(简体) ), `SameSite=Lax`自动 `Secure` 和30天时间 `Max-Age` 所以用户在浏览器之间签名 重启 .

使用 `cookieOptions` 仅在您需要覆盖某样东西时——例如共享 跨子域的会话 :

```ts
createClient({
  domain: '<faableauth_domain>',
  clientId: '<client_id>',
  storage: 'cookie',
  cookieOptions: { domain: '.example.com' }
})
```

### 自定义适配器

提供执行对象 `getItem`, (中文(简体) ), `setItem`,以及 `removeItem` (同步) ),或者说Aync. 设定 `isServer: true` 如果数值可能来自不可信来源,则 作为请求饼干.

```ts
const memoryStorage = {
  store: new Map<string, string>(),
  getItem: (k: string) => memoryStorage.store.get(k) ?? null,
  setItem: (k: string, v: string) => void memoryStorage.store.set(k, v),
  removeItem: (k: string) => void memoryStorage.store.delete(k)
}

createClient({ domain, clientId, storage: memoryStorage })
```

## Next.js / 服务器侧

`@faable/auth-js/nextjs` 运行登录 **服务器**: App 路由器处理器 页:1 `login`, (中文(简体) ), `callback`, (中文(简体) ), `logout` 财务报告和审定财务报表 `backchannel-logout`,一个 `HttpOnly` 无法读取的加密会话 cookie, `id_token` 财务报告和审定财务报表 `logout_token` 由租户JWKS核实`jose`页:1 `getAccessToken()` 那个 在服务器上刷新 。 需要节点 20+ 或边缘运行时间,以及 `next` 13+ (英语).

```ts
// lib/faable-auth.ts
import { createFaableAuth } from '@faable/auth-js/nextjs'

export const faableAuth = createFaableAuth({
  domain: process.env.FAABLE_AUTH_DOMAIN!, // your-tenant.auth.faable.link
  clientId: process.env.FAABLE_AUTH_CLIENT_ID!,
  clientSecret: process.env.FAABLE_AUTH_CLIENT_SECRET, // confidential clients only
  secret: process.env.FAABLE_AUTH_SECRET!, // ≥ 32 chars; encrypts the cookie
  baseUrl: process.env.FAABLE_AUTH_BASE_URL! // https://app.example.com
})
// Every field also reads the FAABLE_AUTH_* environment variable of the same name.
```

```ts
// app/auth/[...faable]/route.ts
import { faableAuth } from '@/lib/faable-auth'

export const { GET, POST } = faableAuth.handlers
```

登记册 `https://app.example.com/auth/callback` 作为允许召回的 URL, `https://app.example.com/` (或你的电话) `returnTo` 页面)作为登录 URL,以及 `https://app.example.com/auth/backchannel-logout` 作为客户的 `backchannel_logout_uri`。然后链接到 `/auth/login?returnTo=/dashboard` 财务报告和审定财务报表 `/auth/logout`。 。 。 .

```tsx
// app/dashboard/page.tsx — Server Component
import { redirect } from 'next/navigation'
import { faableAuth } from '@/lib/faable-auth'

export default async function Dashboard() {
  const session = await faableAuth.getSession()
  if (!session) redirect('/auth/login?returnTo=/dashboard')
  return <h1>Hello {session.user.email}</h1>
}
```

```ts
// app/api/orders/route.ts — call an API on the user's behalf
export async function GET() {
  const token = await faableAuth.getAccessToken() // refreshes when needed
  if (!token) return new Response(null, { status: 401 })
  return fetch('https://api.example.com/orders', {
    headers: { Authorization: `Bearer ${token.accessToken}` }
  })
}
```

```ts
// middleware.ts — keep the session fresh, gate a section
import type { NextRequest } from 'next/server'
import { faableAuth } from '@/lib/faable-auth'

export const middleware = (req: NextRequest) =>
  faableAuth.middleware(req, {
    protect: req => req.nextUrl.pathname.startsWith('/dashboard')
  })
export const config = { matcher: ['/((?!_next|favicon.ico).*)'] }
```

检查服务器上的权限 **已核实** 访问符 (JWKS, `iss`, (中文(简体) ), `aud`, (中文(简体) ), `exp`),这样他们就可以打开页面和动作. 他们需要 `authorizationParams.audience` 设置到您的 Api 标识符( 并使用 RBAC 在 Api, 请求的权限 `authorizationParams.scope`:

```ts
// Server Component / Server Action
if (!(await faableAuth.hasPermission('invites:write'))) notFound()

// middleware.ts — anonymous → login, signed in without the permission → 403
faableAuth.middleware(req, {
  permissions: req =>
    req.nextUrl.pathname.startsWith('/admin') ? ['admin:read'] : undefined
})
```

当用户在同一 SSO 会话中从另一个应用程序中签名时, 认证服务器 职位a `logout_token` 改为 `/auth/backchannel-logout`援助者证实它 从那时起, `getSession()` 返回时 `null` 虽然这届会议 浏览器仍然发送饼干。 记录存在于 `SessionStore` 内 默认内存( 一个进程); 当应用程序运行时, 将自己的内存传递给 Redis 有几个例子.

### 遗产 : `getSessionFromCookies` (折旧)

浏览器 SDK 带有 `storage: 'cookie'` 写入服务器可以解析的饼干 与 `getSessionFromCookies`这是 **没有 `HttpOnly` 未核实** - 任何 页面上的脚本,或伪造的请求,可以放入任意会话——所以 使用它只是为了方便, 从来没有作为授权。 新应用程序使用 `@faable/auth-js/nextjs` 条目.

## 文档

完整导游、API参考和仪表板设置的走行道访问 [faable.com/docs (英语)](https://faable.com/docs)。 。 。 .

## 许可证

麻省理工学院——见 [自由主义](https://npmcn.com/package/%40faable/auth-js/LICENSE)。 。 。 .

## 常见问题

### @faable/auth-js 是什么？

异类

### 如何安装 @faable/auth-js？

在项目目录运行 npm install @faable/auth-js，或使用 pnpm add / yarn add / bun add。

### @faable/auth-js 支持 TypeScript 吗？

支持。包内自带 TypeScript 类型声明（package\.json 声明了 types 入口），安装后即可获得类型提示，无需再安装 @types 包。

### @faable/auth-js 支持 ESM 还是 CommonJS？

以 ES Module 形式发布，推荐使用 import 引入。在 CommonJS 项目中，Node\.js 20\.19\+ / 22\.12\+ 可以直接 require\(\) 不含顶层 await 的 ES Module，更早的版本需要改用动态 import\(\)。

### @faable/auth-js 可以商用吗？

@faable/auth-js 使用 MIT 许可。宽松许可：允许商业使用、修改和再分发，通常只需在分发时保留原版权与许可声明。以上为概括，不构成法律意见，请以许可原文为准。

### @faable/auth-js 的下载量有多少？

根据 npm 官方下载统计，@faable/auth-js 在 2026/10/14 – 2026/11/12 这 30 天内被下载 2,687 次，日均约 90 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入，适合横向比较热度，不能直接等同于使用人数。

### @faable/auth-js 还在维护吗？

最新版本 3\.2\.3 发布于 2026/11/04（9 天前）；至今共发布 84 个版本，其中过去 12 个月发布了 68 个；首次发布于 2024/05/28。发布频率只是参考信号：功能稳定的工具可能很少需要更新，建议结合源码仓库的 issue 和提交记录判断。

