# @commercelayer/js-auth 中文文档

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

版本：8\.1\.0
npm 元数据更新时间：2026-11-02T08:58:35.320Z
中文译文更新时间：2026-11-10T11:59:48.868Z
软件包许可：MIT

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

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

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

- 包体积（解压后）：289 kB，9 个文件
- 模块格式：ESM + CJS
- TypeScript 类型：包内自带
- Node.js 要求：\>=20\.0\.0
- 运行依赖：0 个
- 首次发布：2019-11-29T15:10:41.959Z
- 最新版本发布：2026-11-02T08:58:34.972Z
- 近 30 天下载量：31045（2026-10-11 至 2026-11-09，npm 官方下载统计）
- 已发布版本数：71（近 12 个月 11 个）

## 中文简介

一个JavaScript库,旨在与商务地层API互动时简化认证.

## 安装

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

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

## README

# 商业层

轻量级 JavaScript 库,旨在简化 [认证](https://docs.commercelayer.io/developers/authentication) 当与商业层 API 交互时。 它提供了一种坚固的箱外缓存系统,支持可配置的持续存储、复合存储策略和专用的客户令牌管理.

它在任何地方都有作用——在你的浏览器,服务器上,或者在边缘.

## 什么是商业层?

[商业层](https://commercelayer.io/) 是一个多市场商业API和订单管理系统,它允许您在任何网站,移动应用程序,聊天机,可穿戴,语音,或IoT设备中加入全局购物能力,轻松地. 用你已经掌握和热爱的最好的工具来整理你的堆叠. 通过一个快速的 企业级的 安全的API.

## 目录

-   [开始](https://npmcn.com/package/%40commercelayer/js-auth/#readme-getting-started)
-   [API 证书](https://npmcn.com/package/%40commercelayer/js-auth/#readme-api-credentials)
    -   [储存战略](https://npmcn.com/package/%40commercelayer/js-auth/#readme-storage-strategy)
        -   [客户存储](https://npmcn.com/package/%40commercelayer/js-auth/#readme-customer-storage)
        -   [调试和存储名称](https://npmcn.com/package/%40commercelayer/js-auth/#readme-debugging-and-storage-names)
            -   [将日志转发到日志采集器](https://npmcn.com/package/%40commercelayer/js-auth/#readme-forwarding-logs-to-a-log-collector)
        -   [使用未储存](https://npmcn.com/package/%40commercelayer/js-auth/#readme-using-unstorage)
    -   [销售渠道](https://npmcn.com/package/%40commercelayer/js-auth/#readme-sales-channel)
        -   [基于密码的客户认证](https://npmcn.com/package/%40commercelayer/js-auth/#readme-password-based-customer-authentication)
        -   [JWT 无记名认证](https://npmcn.com/package/%40commercelayer/js-auth/#readme-jwt-bearer-authentication)
            -   [来自外部身份提供者的授权登录](https://npmcn.com/package/%40commercelayer/js-auth/#readme-delegated-login-from-an-external-identity-provider)
    -   [一体化](https://npmcn.com/package/%40commercelayer/js-auth/#readme-integration)
-   [其他流动](https://npmcn.com/package/%40commercelayer/js-auth/#readme-other-flows)
    -   [有授权代码流的 Webapp 应用程序](https://npmcn.com/package/%40commercelayer/js-auth/#readme-webapp-application-with-authorization-code-flow)
    -   [规定适用](https://npmcn.com/package/%40commercelayer/js-auth/#readme-provisioning-application)
    -   [客户证书流程](https://npmcn.com/package/%40commercelayer/js-auth/#readme-client-credentials-flow)
-   [公用事业](https://npmcn.com/package/%40commercelayer/js-auth/#readme-utilities)
    -   [撤销一个符号](https://npmcn.com/package/%40commercelayer/js-auth/#readme-revoking-a-token)
    -   [解码访问符](https://npmcn.com/package/%40commercelayer/js-auth/#readme-decoding-an-access-token)
    -   [正在验证访问符](https://npmcn.com/package/%40commercelayer/js-auth/#readme-verifying-an-access-token)
    -   [获取核心 API 基准终点](https://npmcn.com/package/%40commercelayer/js-auth/#readme-getting-the-core-api-base-endpoint)
    -   [获取提供 API 基端点](https://npmcn.com/package/%40commercelayer/js-auth/#readme-getting-the-provisioning-api-base-endpoint)
-   [贡献者指南](https://npmcn.com/package/%40commercelayer/js-auth/#readme-contributors-guide)
-   [需要帮忙吗?](https://npmcn.com/package/%40commercelayer/js-auth/#readme-need-help)
-   [许可证](https://npmcn.com/package/%40commercelayer/js-auth/#readme-license)

* * *

## 开始

要开始商业层 JS Auth 你需要安装它 并添加到您的项目中.

[![NPM](https://img.shields.io/npm/v/%40commercelayer%2Fjs-auth?style=for-the-badge&labelColor=%23C90501&color=173B4A)](https://www.npmjs.com/package/@commercelayer/js-auth) [![JSR](https://img.shields.io/jsr/v/%40commercelayer/js-auth?style=for-the-badge&labelColor=E2CB23&color=173B4A)](https://jsr.io/@commercelayer/js-auth) ![Lightway](https://img.shields.io/bundlejs/size/%40commercelayer%2Fjs-auth?style=for-the-badge)     [![Discord](https://img.shields.io/badge/discord-5865F2?style=for-the-badge&logo=discord&logoColor=ffffff)](https://discord.gg/commercelayer)

### 安装

商业层 Auth 作为 npm 软件包可用 .

```bash
# npm
npm install @commercelayer/js-auth

# yarn
yarn add @commercelayer/js-auth

# pnpm
pnpm add @commercelayer/js-auth

# deno
deno add jsr:@commercelayer/js-auth

# bun
bun add @commercelayer/js-auth
```

## API 证书

商业层执行工业标准 [OAuth 2.0 数据](https://oauth.net/2/) 管理客户授权的协议。 它定义了不同类型的API证书. 哪一个要使用取决于你的具体需要.

> \[注\] 检查我们 [API 证书文件](https://docs.commercelayer.io/core/api-credentials) 了解如何通过商业层仪表板创建这些证书.

要使用商务层 API,您首先需要获得授权 。 这意味着你需要获得有效的访问符.

```mermaid
flowchart TB
  %% Default style for nodes
  classDef node stroke-width:2px;

  %% Main nodes
  auth("<b>Auth API</b><br/><br/>https://<b>auth</b>.commercelayer.io")

  dashboard("JWT Dashboard")
  user("JWT User")
  sales_channel("JWT Sales Channel")
  integration("JWT Integration")
  webapp("JWT WebApp")

  provisioningAPI("<b>Provisioning API</b><br/><br/>https://<b>provisioning</b>.commercelayer.io")
  coreAPI("<b>Core API</b><br/><br/>https://#lt;<b>slug</b>#gt;.commercelayer.io")
  metricsAPI("<b>Metrics API</b><br/><br/>https://#lt;<b>slug</b>#gt;.commercelayer.io/metrics")
  comingSoon("<b>Metrics API</b> (coming soon)<br/><br/>https://<b>metrics</b>.commercelayer.io")

  %% Node styles
  style dashboard fill:#FFE6CC,stroke:#D79B00,color:#000
  style user fill:#F8CECC,stroke:#B85450,color:#000
  style sales_channel fill:#D5E8D4,stroke:#82B366,color:#000
  style integration fill:#DAE8FC,stroke:#6C8EBF,color:#000
  style webapp fill:#E1D5E7,stroke:#9673A6,color:#000
  style comingSoon opacity:.3

  %% Connections
  auth --> dashboard
  auth --> user
  auth --> sales_channel
  auth --> integration
  auth --> webapp

  dashboard --> provisioningAPI
  user --> provisioningAPI
  user --> comingSoon
  sales_channel --> coreAPI
  integration --> coreAPI
  integration --> metricsAPI
  webapp --> coreAPI
  webapp --> metricsAPI

  %% Arrow Styles
  linkStyle default stroke-width:2px;
  linkStyle 5 stroke:#D79B00
  linkStyle 6 stroke:#B85450
  linkStyle 7 stroke:#B85450,stroke-dasharray: 5 5,opacity:.3
  linkStyle 8 stroke:#82B366
  linkStyle 9 stroke:#6C8EBF
  linkStyle 10 stroke:#6C8EBF
  linkStyle 11 stroke:#9673A6
  linkStyle 12 stroke:#9673A6
```

认证呼叫必须服从 [费率限制](https://docs.commercelayer.io/core/rate-limits#authentication-endpoint)。为了避免击中这些限制,您应当将认证符缓存到存储器中(如cookie,Redis,KV等). 这无法为每次API呼叫请求新令牌 .

这个库提供了一个强大的符号缓存系统出箱,支持您选择的任何存储解决方案. 它包括用于编组多存储机制(如内存+Redis)的工具来减少基础配置存储上的负载,并提供专门的客户符管理.

> \[注\] 对于高级使用时需要直接控制符管理的情况,可以绕过内置缓存辅助器(`makeSalesChannel` 财务报告和审定财务报表 `makeIntegration`和 [使用该 `authenticate` 直接方法](https://npmcn.com/package/%40commercelayer/js-auth/#readme-client-credentials-flow)。 。 。 .

### 储存战略

-   **单一存储** ——提供能活过页面再装入的临时或持续存储. 您可以执行任何存储解决方案 .
-   **复合储存** -使用 `createCompositeStorage` 帮助器,可以结合多个存储机制(例如内存+Redis)来优化性能并减少基础所配置存储上的负载.
-   **[客户存储](https://npmcn.com/package/%40commercelayer/js-auth/#readme-customer-storage)** (单位:千美元)_仅销售渠道_)——可选客户认证信使专用存储,与来宾信使分离.

下面的示例显示带有内存的基本设置 :

```ts
import {
  makeSalesChannel,
  type Storage,
  type StorageValue,
} from "@commercelayer/js-auth"

/**
 * A valid storage must implement the `Storage` interface
 */
function memoryStorage(): Storage {
  const store = new Map<string, StorageValue>()
  return {
    name: "in-memory",
    async getItem(key) {
      return store.get(key) ?? null
    },
    async setItem(key: string, value: StorageValue) {
      store.set(key, value)
    },
    async removeItem(key: string) {
      store.delete(key)
    },
  }
}

const salesChannel = makeSalesChannel(
  {
    clientId: "<your_client_id>",
    scope: "market:code:europe",
    debug: {
      logLevel: "info"
    },
  },
  {
    storage: memoryStorage(),
  },
)

/**
 * At the beginning, you'll get a guest token
 */
const authorization1 = await salesChannel.getAuthorization()

console.log("Guest access token:", authorization1.accessToken)

/**
 * For consecutive calls, you'll get the previous guest token
 * from the storage or a new one if expired
 */
const authorization2 = await salesChannel.getAuthorization()

console.log("Customer access token:", authorization2.accessToken)
```

授权使用来自客户身份和范围的密钥存储,其中 `type` 是授权类型( y)`guest` 或者说 `customer`:

```
cl_${type}-${clientId}-${scope}
```

如果您需要不同的密钥( 例如自定义前缀, 或额外的标识符), 您可以自行提供 `getKey` 函数 :

```ts
const salesChannel = makeSalesChannel(
  {
    clientId: "<your_client_id>",
    scope: "market:code:europe"
  },
  {
    storage: memoryStorage(),
    getKey: async ({ clientId, scope }, type) =>
      `myprefix_${type}-${clientId}-${scope}`,
  },
)
```

以下流程图说明了库如何管理符号缓存、验证和刷新流程:

```mermaid
flowchart TB
  %% Default style for nodes
  classDef node stroke-width:2px,color:#000;

  GetAuthorization(".getAuthorization()") --> CheckCustomerStorage{"Check <b>Customer</b><br/>in storage"}

  CheckCustomerStorage -->|Found| ValidateCustomerToken{"Is token<br/>still valid?"}
  CheckCustomerStorage -->|Not Found| CheckGuestStorage{"Check <b>Guest</b><br/>in storage"}

  ValidateCustomerToken -->|Yes| ReturnCustomerToken(["Return <b>Customer</b> Token"])
  ValidateCustomerToken -->|No| HasRefreshToken{"<b>Customer</b> has<br/>refresh token?"}

  HasRefreshToken -->|Yes| RefreshToken["Refresh <b>Customer</b> token"]
  HasRefreshToken -->|No| CheckGuestStorage

  RefreshToken --> StoreNewToken["Store new <b>Customer</b> token"]
  StoreNewToken --> ReturnCustomerToken

  %% CheckGuestMemory -->|Found| ValidateGuestToken{"Is token<br/>still valid?"}
  %% CheckGuestMemory -->|Not Found| CheckGuestStorage{"Check <b>Guest</b><br/>in storage"}

  ValidateGuestToken -->|Yes| ReturnGuestToken(["Return <b>Guest</b> token"])
  ValidateGuestToken -->|No| CreateNewGuest["Create new <b>Guest</b> token"]

  CheckGuestStorage -->|Found| ValidateGuestToken{"Is token<br/>still valid?"}
  CheckGuestStorage -->|Not Found| CreateNewGuest

  CreateNewGuest --> StoreNewGuestToken["Store new <b>Guest</b> token"]
  StoreNewGuestToken --> ReturnGuestToken

  classDef process fill:#DAE8FC,stroke:#6C8EBF
  classDef condition fill:#FFE6CC,stroke:#D79B00
  classDef code fill:#FFF,stroke:#000,font-family:monospace
  classDef startState fill:#FFF,stroke:#000
  classDef endState fill:#FFF,stroke:#000

  class GetAuthorization code;
  class Start startState;
  class CheckCustomerMemory,CheckCustomerStorage,CheckGuestMemory,CheckGuestStorage condition;
  class ValidateCustomerToken,ValidateGuestToken,HasRefreshToken condition;
  class RefreshToken,StoreCustomerTokenInMemory,CreateNewGuest,StoreNewToken,StoreNewGuestToken process;
  class ReturnCustomerToken,ReturnGuestToken endState;
```

#### 客户存储

销售渠道处理两种标志: **来宾** 符号,与任何身份无关,可以安全分享,以及 **客户** 这是私人恩怨 可选 `customerStorage` 选项允许您将客户代号与来宾代号分开存储。 客户代币是否保持被隔离,取决于两件事:它们被写入的存储,以及它们被存储在下面的密钥.

在浏览器中,一切都在外出工作:存储(例如. `localStorage`)已标注为单一访客.

> \[尖叫声\] 默认密钥是 **没有** 包括任何客户身份。 如果客户代币被缓存在默认密钥下由所有访客共享的存储中(例如Redis或服务器上的内映映射),则一个客户代币将送达 **每个** 来客.

在服务器上安全存储客户代币有两种方式:

1.  **使用每个访客 `customerStorage`。 。 。 .** 当客户存储被设定为访问者范围(如cookie)时,默认密钥是完美无缺的,因为存储本身属于单一访问者. 这对自然与服务器侧制成的店面对齐,其中单一的来宾符可以被缓存服务器侧并被所有访客共享:
    
    ```ts
    const salesChannel = makeSalesChannel(
      {
        clientId: "<your_client_id>",
        scope: "market:code:europe"
      },
      {
        // The guest token carries no identity:
        // one token, cached server-side, serves all visitors...
        storage: memoryStorage(),
        // ...while the customer token is personal
        // and lives in a per-visitor storage (e.g. cookies).
        customerStorage: cookieStorageAdapter,
      },
    )
    ```
    
2.  **使用自定义密钥共享存储 .** 如果您宁愿在共享服务器侧存储器中缓存客户签名( 例如 Redis), 请使用 `getKey` 函数可以在密钥中包含客户端或会话标识符。 自兹 `getKey` 仅接收客户身份、范围和授权类型,必须通过关闭获取请求上下文。 创建每个请求的助手, 同时保留存储后端 :
    
    ```ts
    import {
      createCompositeStorage,
      makeSalesChannel,
    } from "@commercelayer/js-auth"
    
    // Shared, process-level storage (this is where tokens are actually cached).
    const sharedStorage = createCompositeStorage({
      name: "bff",
      storages: [memoryStorage(), redisStorage],
    })
    
    // Per-request helper: creating it is cheap (no network calls, no timers).
    function salesChannelFor(customerId: string) {
      return makeSalesChannel(
        {
          clientId: "<your_client_id>",
          scope: "market:code:europe"
        },
        {
          storage: sharedStorage,
          getKey: async ({ clientId, scope }, type) =>
            type === "customer"
              ? `cl_customer-${clientId}-${scope}-${customerId}`
              : `cl_guest-${clientId}-${scope}`,
        },
      )
    }
    ```
    

> \[注\] 帮手们回来了 `makeSalesChannel` 财务报告和审定财务报表 `makeIntegration` 轻量级工厂:它们自己没有象征性的状态(在配置的仓库里住着),在施工时没有I/O。 只要存储后端是共享的,每个请求创建一个是安全的. 唯一长寿的例子就是飞行中同时分解 `getAuthorization()` 打电话.

#### 调试和存储名称

您可以启用调试, 并为您的存储实例指定自定义名称, 以便更好的可见度 :

-   **`debug`** - 接受一个 `DebugConfig` 有两个选项的对象:
    -   `logLevel: "info"` ——只记录有意义的事件:缓存丢失,令牌刷新,授权存储/撤销,以及出错. 常规缓存点击是沉默的,所以设置调用 `getAuthorization()` 每一次API请求都不要淹没日志.
    -   `logLevel: "verbose"` ——还记录稳态操作(每个存储读取和缓存被击中).
    -   `maskToken` ——是否在日志输出中掩盖访问符并刷新符(例如. `eyJh...A9Xz`) (中文(简体) ). 默认为 `true`设置为 `false` 以查看完整的代号,例如用于在 [jwt.io (英语)](https://jwt.io/)。 。 。 .
    -   `logger` ——每个条目的写法. 无论是 `"console"` (默认)或诸如 `jsonLogger`。见 [将日志转发到日志采集器](https://npmcn.com/package/%40commercelayer/js-auth/#readme-forwarding-logs-to-a-log-collector)。 。 。 .
-   **`name`** ——您存储实例的自定义标识符,在使用多个存储或复合存储配置时有用. 这个 `name` 是存储本身的一个属性(如 [`memoryStorage` 以上实例](https://npmcn.com/package/%40commercelayer/js-auth/#readme-storage-strategy)) (中文(简体) ).

这个 `createCompositeStorage` 帮助者接受自己的 `debug` 选项,遵循同样的规则:对第一个(快速)存储的命中状态是稳定的,而返回较慢存储则是值得记录的有意义的事件.

> \[尖叫声\] 何时 `maskToken` 设置为 `false`完全进入信号 和刷新信号 登录到控制台。 仅用于本地开发——在无服务器/对接环境中,可以将日志传输到外部日志汇总服务.

```diff
 const salesChannel = makeSalesChannel(
   {
     clientId: "<your_client_id>",
     scope: "market:code:europe",
+    debug: {
+      logLevel: "info"
+    },
   },
   {
     storage: {
+      name: "storage-name",
+      debug: {
+        logLevel: "info"
+      },
       async getItem(key) {
         // implementation
       },
       // ...
     }
   },
 )
```

#### 使用未储存

这个 `Storage` 接口与 [`unstorage`](https://unstorage.unjs.io/) 图书馆。 不过, `unstorage` 不包括一个 `name` 默认财产。 为启用调试并识别日志中使用的存储, 将 `createStorage` 使用此助手 :

```ts
import type { Storage } from "@commercelayer/js-auth"
import type { CreateStorageOptions } from "unstorage"
import { createStorage as unstorageCreateStorage } from "unstorage"

// Helper to create storage with explicit naming support
function createStorage(
  options: CreateStorageOptions & { name?: string },
): Storage {
  return {
    name: options.name ?? options.driver?.name,
    ...unstorageCreateStorage(options),
  }
}
```

```ts
// Usage example
import redisDriver from "unstorage/drivers/redis"

const redisStorage = createStorage({
  name: "redis-persistent",
  driver: redisDriver({
    url: "<your_redis_connection_string>",
  }),
})
```

当调试被启用时,日志会包含存储名,从而更容易追踪哪个存储层正在处理每个操作.

##### 将日志转发到日志采集器

默认( E)`logger: "console"`)每个条目均用 `console.log(message, ...data)`,因此对象可以在浏览器devtools中保持可扩展并可以在终端中读取. 在Node.js,虽然, `console.log` 打印整个对象 **多行**,以及读取 stdout (Datadog, Cloud Watch, Google Cloud Looking, Loki,.) 的日志收集器将其中每一行作为单独的日志条目来摄取.

`logger` 也接受接收每个条目的函数。 这个 `jsonLogger` 帮助器是一个这样的功能:它每个条目写一个单行的JSON对象. 你可以选择每个环境:

```ts
import { jsonLogger, makeSalesChannel } from "@commercelayer/js-auth"

const salesChannel = makeSalesChannel({
  clientId: "<your_client_id>",
  scope: "<your_scope>",
  debug: {
    logLevel: "info",
    logger: process.env.NODE_ENV === "production" ? jsonLogger : "console",
  },
})
```

```json
{"name":"@commercelayer/js-auth","level":"info","source":"sales_channel","storageName":"memory","message":"Stored \"customer\" authorization to storage","data":[{"accessToken":"eyJh...A9Xz","scope":"market:all"}]}
```

`Error` 数值扩展为 `{ name, message, stack, cause }` 加上任何自定义属性,包含自身对象被替换为 `"[Circular]"`所以伐木从不扔.

要将条目传送到您自己的日志机( pino, winston,...), 请通过您自己的功能 :

```ts
import pino from "pino"

const log = pino()

const salesChannel = makeSalesChannel({
  clientId: "<your_client_id>",
  scope: "<your_scope>",
  debug: {
    logLevel: "info",
    logger: ({ level, message, ...entry }) => {
      log[level === "verbose" ? "debug" : "info"](entry, message)
    },
  },
})
```

在登录器到达之前, 使用托肯口罩, 所以 `maskToken` 跟每个伐木工一起工作 一个日志函数所抛出的错误会被忽略,所以一个失败的日志永远不会中断认证.

### 销售渠道

[销售渠道](https://docs.commercelayer.io/core/api-credentials#sales-channel) 用于构建任何客户触点(例如,您的商店前端带有一个功能完备的购物车和取出流程).

以下是一个完整的例子

```ts
import { authenticate, makeSalesChannel } from "@commercelayer/js-auth"

// The `Storage` interface is fully-compatible with the `unstorage` library.
import { createStorage } from "unstorage"
import localStorageDriver from "unstorage/drivers/localstorage"

const salesChannel = makeSalesChannel(
  {
    clientId: "<your_client_id>",
    scope: "market:code:europe",
  },
  {
    /**
     * You can use any storage implementation you prefer or implement your own.
     * In this example we use `unstorage` with the `localStorage` driver
     */
    storage: createStorage({
      driver: localStorageDriver({}),
    }),
  },
)

/**
 * Get the current authorization state which includes the access token.
 * This method handles caching and token refresh automatically.
 */
const guestAuthorization = await salesChannel.getAuthorization()

console.log("Guest access token:", guestAuthorization.accessToken)

/**
 * Authenticate a customer using their email and password, or
 * though the JWT bearer flow.
 */
const customerCredentials = await authenticate("password", {
  clientId: "<your_client_id>",
  scope: "market:code:europe",
  username: "john@example.com",
  password: "secret",
})

/**
 * Set the customer credentials in the storage.
 */
await salesChannel.setCustomer({
  accessToken: customerCredentials.accessToken,
  scope: customerCredentials.scope,

  /**
   * When `refreshToken` is provided, it'll be used to automatically
   * refresh the customer access token when it expires.
   */
  refreshToken: customerCredentials.refreshToken,
})

/**
 * Get the current customer authorization.
 */
const customerAuthorization = await salesChannel.getAuthorization()

console.log("Customer access token:", customerAuthorization.accessToken)

/**
 * Logout the current customer.
 * This will remove the customer authorization from the storage, and revoke the access token.
 */
await salesChannel.logoutCustomer()

/**
 * You can also clear stored authorizations without revoking the tokens,
 * e.g. to force a fresh authorization on the next `getAuthorization()` call.
 */
await salesChannel.removeAuthorization("all") // or "customer" / "guest"
```

客户认证通过两个OAuth 2.0赠款类型得到支持: [密码](https://npmcn.com/package/%40commercelayer/js-auth/#readme-password-based-customer-authentication) 财务报告和审定财务报表 [JWT 无记名者](https://npmcn.com/package/%40commercelayer/js-auth/#readme-jwt-bearer-authentication)。两种流动返回 `accessToken`, (中文(简体) ), `scope`,以及 `refreshToken` 可使用 `setCustomer` 方法.

#### 基于密码的客户认证

销售渠道可以使用 [密码](https://docs.commercelayer.io/developers/authentication/password) 用于交换客户证书的赠款类型,以获取访问令牌(即获取"登录"访问令牌).

```ts
import { authenticate } from "@commercelayer/js-auth"

const auth = await authenticate("password", {
  clientId: "<your_client_id>",
  scope: "market:code:europe",
  username: "john@example.com",
  password: "secret"
})

console.log("My access token:", auth.accessToken)
console.log("Expiration date:", auth.expires)
console.log("My refresh token:", auth.refreshToken)
```

销售渠道可以使用 [刷新符号](https://docs.commercelayer.io/developers/authentication/refresh-token) 用“ 记住我” 选项刷新客户访问符的赠款类型 :

```ts
import { authenticate } from "@commercelayer/js-auth"

const newToken = await authenticate("refresh_token", {
  clientId: "<your_client_id>",
  scope: "market:code:europe",
  refreshToken: "<your_refresh_token>"
})
```

> \[注\] 使用时 `makeSalesChannel` 帮助者, 自动处理符号刷新 。 帮助器监视符过期后无缝地刷新了背景中的客户符,消除了手动刷新呼叫的需要.

#### JWT 无记名认证

商业层支持 OAuth 2. 0 [JWT 缓冲器](https://docs.commercelayer.io/core/authentication/jwt-bearer) 通过交换JWT断言,使应用程序能够获取访问令. 这对于执行授权认证流程特别有用,因为应用程序需要代表客户发出API呼叫,而不需要其直接互动. 流动包括两个步骤:

1.  开具附有客户索赔的JWT签名断言
    
    ```ts
    import { createAssertion } from "@commercelayer/js-auth"
    
    const assertion = await createAssertion({
      payload: {
        "https://commercelayer.io/claims": {
          owner: {
            type: "Customer",
            id: "4tepftJsT2"
          },
          custom_claim: {
            customer: {
              first_name: "John",
              last_name: "Doe"
            }
          }
        }
      }
    })
    ```
    
2.  将此断言交换为访问符
    
    ```ts
    import { authenticate } from "@commercelayer/js-auth"
    
    const auth = await authenticate("urn:ietf:params:oauth:grant-type:jwt-bearer", {
      clientId: "<your_client_id>",
      clientSecret: "<your_client_secret>",
      scope: "market:code:europe",
      assertion
    })
    
    console.log("My access token:", auth.accessToken)
    console.log("Expiration date:", auth.expires)
    console.log("My refresh token:", auth.refreshToken)
    ```
    

销售渠道和网络app都可以使用JWT无记名流执行安全授权认证.

#### 来自外部身份提供者的授权登录

当客户通过外部身份提供商(如:Okta, Auth0)认证时,您的后端可以使用JWT无记名流量交换其身份来换取商业层客户代币,并将其交给 `salesChannel` 帮助器( 由于此流运行服务器侧, 请参见 [客户存储](https://npmcn.com/package/%40commercelayer/js-auth/#readme-customer-storage) 适合设置的章节 :

```ts
import {
  authenticate,
  createAssertion,
} from "@commercelayer/js-auth"

// 1. Validate the external identity (e.g. verify the IdP-issued JWT)
//    and resolve it to a Commerce Layer customer ID.
const customerId = await resolveCustomerId(idpToken)

// 2. Create the signed assertion and exchange it for a customer token.
//    This step requires the client secret, so it must run server-side.
const assertion = await createAssertion({
  payload: {
    "https://commercelayer.io/claims": {
      owner: {
        type: "Customer",
        id: customerId
      },
    },
  },
})

const customerCredentials = await authenticate("urn:ietf:params:oauth:grant-type:jwt-bearer", {
  clientId: "<your_client_id>",
  clientSecret: "<your_client_secret>",
  scope: "market:code:europe",
  assertion,
})

// 3. Hand the customer token over to the `salesChannel` helper
//    created with `makeSalesChannel`.
//    From now on, `getAuthorization()` returns the customer authorization
//    and refreshes it automatically when it expires.
await salesChannel.setCustomer({
  accessToken: customerCredentials.accessToken,
  scope: customerCredentials.scope,
  refreshToken: customerCredentials.refreshToken,
})
```

### 一体化

[一体化](https://docs.commercelayer.io/core/api-credentials#integration) 用于开发与任何三党制的后端集成.

```ts
import {
  createCompositeStorage,
  makeIntegration,
} from "@commercelayer/js-auth"

// The `Storage` interface is fully-compatible with the `unstorage` library.
import { createStorage } from "unstorage"
import memoryDriver from "unstorage/drivers/memory"
import redisDriver from "unstorage/drivers/redis"

const memoryStorage = createStorage({
  driver: memoryDriver(),
})

const redisStorage = createStorage({
  driver: redisDriver({
    url: "<your_redis_connection_string>",
  }),
})

const compositeStorage = createCompositeStorage({
  name: "composite-storage",
  storages: [
    memoryStorage,
    redisStorage,
  ]
})

const integration = makeIntegration(
  {
    clientId: "<your_client_id>",
    clientSecret: "<your_client_secret>",
    debug: {
      logLevel: "info"
    },
  },
  {
    storage: compositeStorage,
  },
)

/**
 * If you already requested an access token before, now you'll probably get it from Redis if not expired.
 * Otherwise, a new one will be requested.
 * 
 * This method handles caching and token refresh automatically.
 */
const authorization1 = await integration.getAuthorization()

console.log("Integration access token #1:", authorization1.accessToken)

/**
 * Subsequent calls will return the cached token from memory storage.
 */
const authorization2 = await integration.getAuthorization()

console.log("Integration access token #2:", authorization2.accessToken)

/**
 * Revoke the current integration authorization.
 * This will remove the authorization from memory and storage, and revoke the access token.
 */
await integration.revokeAuthorization()

/**
 * Disposes all mounted storages to ensure there are no open-handles left.
 * Call it before exiting process.
 */
await compositeStorage.dispose?.()
```

## 其他流动

### 有授权代码流的 Webapp 应用程序

> 仅供浏览器应用程序使用

网络应用程序使用 [授权代码](https://docs.commercelayer.io/developers/authentication/authorization-code) 授权类型以交换访问符的授权代码.

#### 步骤

在此情况下,首先需要获得授权代码,然后用访问符交换:

1.  创建商务层上的网络应用程序,并注意API证书(客户ID,客户端秘密,召回 URL,基端点,以及您想要设置范围的市场ID)
    
2.  使用此 URL 授权您在商业层上的网络应用 :
    

```bash
https://dashboard.commercelayer.io/oauth/authorize?client_id={{your_client_id}}&redirect_uri={{your_redirect_uri}}&scope=market:id:xYZkjABcde&response_type=code&state=1a2b3c
```

3.  一旦你授权了Webapp,你就会被重新定向到回调 URL:
    
    ![Callback URL with Authorization Code](https://github.com/commercelayer/commercelayer-js-auth/assets/1681269/2a167283-a3a9-4d16-bb8f-a962a5fe8900)
    
    使用此代码获取访问令牌 :
    

```ts
import { authenticate } from "@commercelayer/js-auth"

const auth = await authenticate("authorization_code", {
  clientId: "<your_client_id>",
  clientSecret: "<your_client_secret>",
  callbackUrl: "<https://yourdomain.com/callback>",
  code: "<your_auth_code>"
})

console.log("My access token: ", auth.accessToken)
console.log("Expiration date: ", auth.expires)
```

### 规定适用

提供应用程序使用 [客户证书](https://docs.commercelayer.io/developers/authentication/client-credentials) 获取访问符的赠款类型.

#### 步骤

1.  访问您的个人 [供给](https://dashboard.commercelayer.io/user/provisioning_api) 在商务层仪表板上应用,并注意您提供的 API 证书(客户身份、客户秘密)
    
2.  使用此代码获取访问令牌 :
    

```ts
import { authenticate } from "@commercelayer/js-auth"

const auth = await authenticate("client_credentials", {
  clientId: "<your_client_id>",
  clientSecret: "<your_client_secret>"
})

console.log("My access token: ", auth.accessToken)
console.log("Expiration date: ", auth.expires)
```

### 客户证书流程

对于高级使用时需要直接控制符管理的情况,可以绕过内置缓存辅助器(`makeSalesChannel` 财务报告和审定财务报表 `makeIntegration`并使用 `authenticate` 直接方法.

> \[尖叫声\] 请注意,在这种情况下,你将负责 执行你自己的活塞 和刷新逻辑.

销售频道应用程序使用 [客户证书](https://docs.commercelayer.io/developers/authentication/client-credentials) 获得“客人”访问符的赠款类型.

```ts
import { authenticate } from "@commercelayer/js-auth"

const auth = await authenticate("client_credentials", {
  clientId: "<your_client_id>",
  scope: "market:code:europe"
})

console.log("My access token: ", auth.accessToken)
console.log("Expiration date: ", auth.expires)
```

集成应用程序使用 [客户证书](https://docs.commercelayer.io/developers/authentication/client-credentials) 获取访问符的赠款类型.

```ts
import { authenticate } from "@commercelayer/js-auth"

const auth = await authenticate("client_credentials", {
  clientId: "<your_client_id>",
  clientSecret: "<your_client_secret>",
})

console.log("My access token: ", auth.accessToken)
console.log("Expiration date: ", auth.expires)
```

## 公用事业

### 撤销一个符号

任何先前产生的访问令牌(包括新鲜令牌)都可以是 [已撤销](https://docs.commercelayer.io/core/authentication/revoking-a-token) 在其自然到期日之前:

```ts
import { revoke } from "@commercelayer/js-auth"

await revoke({
  clientId: "<your_client_id>",
  clientSecret: "<your_client_secret>",
  token: "<a_generated_access_token>"
})
```

### 解码访问符

我们提供一种帮助方法 解码一个访问符。 返回已全部输入 .

> \[大 您不应将此用于不可信信件, 因为此帮助方法不会验证签名是否有效 。 如果你需要的话 [验证访问符](https://npmcn.com/package/%40commercelayer/js-auth/#readme-verifying-an-access-token) 在解码前可以使用 `jwtVerify` 换句话说.

```ts
import { authenticate, jwtDecode, jwtIsSalesChannel } from "@commercelayer/js-auth"

const auth = await authenticate("client_credentials", {
  clientId: "<your_client_id>",
  scope: "market:code:europe"
})

const decodedJWT = jwtDecode(auth.accessToken)

if (jwtIsSalesChannel(decodedJWT.payload)) {
  console.log("organization slug is", decodedJWT.payload.organization.slug)
}
```

### 正在验证访问符

我们提供一种帮助方法来验证一个访问符.

它验证了JWT的完整性和真实性. 它通过对照用于创建的公用钥匙验证签名,来检查该令牌是否有效.

这对确保信使没有被篡改和出自"商业地层"很有用.

返回已全部输入 :

```ts
import { authenticate, jwtVerify, jwtIsSalesChannel } from "@commercelayer/js-auth"

const auth = await authenticate("client_credentials", {
  clientId: "<your_client_id>",
  scope: "market:code:europe"
})

const decodedJWT = await jwtVerify(auth.accessToken, {
  ignoreExpiration: true
})

if (jwtIsSalesChannel(decodedJWT.payload)) {
  console.log("organization slug is", decodedJWT.payload.organization.slug)
}
```

### 获取核心 API 基准终点

传导 [核心 API 基准终点](https://docs.commercelayer.io/core/api-specification#base-endpoint) 提供了有效的访问符.

```ts
import { getCoreApiBaseEndpoint } from "@commercelayer/js-auth"

getCoreApiBaseEndpoint("<a_valid_access_token>") //= "https://yourdomain.commercelayer.io"
```

该方法需要一个有效的访问符,并带有 `organization` 在有效载荷。 当组织没有设置时(例如,提供信使),它会发出一个 `InvalidTokenError` 除外.

### 获取提供 API 基端点

它还原 [提供 API 基准终点](https://docs.commercelayer.io/provisioning/getting-started/api-specification#base-endpoint) 提供了有效的访问符.

```ts
import { getProvisioningApiBaseEndpoint } from "@commercelayer/js-auth"

getProvisioningApiBaseEndpoint("<a_valid_access_token>") //= "https://provisioning.commercelayer.io"
```

该方法需要有效的访问令牌(该令牌可与提供API一起使用). 当符号无效时(例如核心活字符号),它会扔出一个 `InvalidTokenError` 除外.

* * *

## 贡献者指南

1.  叉头 [此寄存器](https://github.com/commercelayer/commercelayer-js-auth) (学习如何做到这一点) [这里](https://help.github.com/articles/fork-a-repo)) (中文(简体) ).
    
2.  像这样砍掉叉子仓库:
    

```bash
git clone https://github.com/<your username>/commercelayer-js-auth.git && cd commercelayer-js-auth
```

3.  更改并创建拉动请求( R)[学着怎么做](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/creating-a-pull-request)) (中文(简体) ).
    
4.  有人会照顾你的拉力请求 并提供一些反馈.
    

## 需要帮忙吗?

-   联合 [商业层的迪斯科德社区](https://discord.gg/commercelayer)。 。 。 .
-   让我们继续 [布鲁斯基](https://bsky.app/profile/commercelayer.io), (中文(简体) ), [页:1](https://x.com/commercelayer),或 [链接](https://www.linkedin.com/company/commerce-layer)。 。 。 .
-   有虫子吗? 创建一个 [问题](https://github.com/commercelayer/commercelayer-js-auth/issues) 。在此仓库上.

## 许可证

此寄存器在 [麻省理工学院](https://npmcn.com/package/%40commercelayer/js-auth/LICENSE) 执照.

## 常见问题

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

一个JavaScript库,旨在与商务地层API互动时简化认证\.

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

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

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

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

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

同时提供 ES Module 与 CommonJS 入口，import 和 require\(\) 都可以使用，打包工具会自动选择合适的版本。

### @commercelayer/js-auth 需要什么版本的 Node\.js？

package\.json 的 engines 字段要求 Node\.js \>=20\.0\.0。版本不符时 npm 默认只给出警告，开启 engine-strict 后会拒绝安装。

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

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

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

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

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

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

