M2M 认证机制:通用原理与 Clerk M2M Tokens 实践

8月 13, 2026
Auth, 密码学, 系统设计, HTTP, ByAI

AI 参与说明(Agent:/root/root/m2m_standards/root/clerk_m2m/root/repo_inspection):本文由 Agent 根据 IETF RFC、Clerk 官方文档、官方 OpenAPI 与 @clerk/backend 当前源码辅助整理,重点核对 M2M、OAuth 2.0 Client Credentials 与 Clerk M2M Tokens 的概念边界。资料核验于 2026-08-13,代码接口按 @clerk/backend 3.16.4 检查;Clerk 的 API、价格和产品行为可能变化,实施前请重新核对文末一手资料与项目锁定版本。

先说结论#

  1. M2M(Machine-to-Machine)不是一套独立、统一的认证协议,而是“没有终端用户参与,机器或工作负载直接通信”这一问题域。API Key、mTLS、签名请求和 OAuth 2.0 都可以用于 M2M。
  2. OAuth 2.0 Client Credentials grant 是 M2M 场景中常用的标准化方案之一。OAuth 2.0 本质上是授权框架;Client Credentials 流程包含 Client Authentication,但最终得到的 access token 表达的是一段受限授权,而不是一张通用的“机器身份证”。
  3. Clerk M2M Tokens 是 Clerk 的产品方案,不等同于 OAuth 2.0 Client Credentials。截至 2026-08-13,Clerk 官方仍明确写着尚未支持 Client Credentials。Clerk 的 Machine、Machine Secret Key、以目标 Machine ID 表达的 scope、/m2m_tokens API 及其计费都属于 Clerk。
  4. Clerk 替应用完成了机器注册、凭据签发、服务间信任关系、token 创建与验证、Opaque/JWT 格式、撤销、密钥轮换、SDK 和用量统计;业务操作权限、租户隔离、网络安全、秘密存储和审计策略仍由应用负责

最容易记住的一句话是:

M2M 是场景,OAuth 2.0 Client Credentials 是标准化实现之一,Clerk M2M Tokens 是解决同一类问题的 Clerk 专有实现。

1. 先把概念所有权分开#

同样的词经常被不同层次复用。先分清归属,后面的协议与代码才不会串台。

概念或能力所有权 / 来源准确含义
M2M、Machine Authentication、Workload Identity通用问题域非人类主体之间建立身份与信任,不指向唯一协议。
OAuth 2.0、Client Credentials grant、Client Authentication、access token、scopeIETF OAuth 标准体系定义客户端如何取得并使用受限授权。
Bearer tokenIETF RFC 6750持有者即可使用的 token;泄漏后可被重放。
JWTIETF RFC 7519一种可签名的 claims 容器与 token 表示格式,不等于 M2M,也不等于 OAuth。
Opaque token通用 token 形态;OAuth 可用 Introspection 标准化验证客户端无法从字符串本身理解内容,接收方通常查本地状态或调用验证服务。
resource / audience、mTLS、DPoPIETF OAuth 扩展与安全最佳实践分别限制 token 的目标服务,或把 token 与发送方密钥绑定。
Machine、Machine Secret Key、Clerk M2M Token、Machine scopeClerk 产品Clerk 的对象模型、凭据、服务间信任关系与 token 生命周期。
clerkClient.m2m.createToken() / verify()Clerk SDKClerk 当前的 token 创建和验证接口。

尤其要留意 scope

  • OAuth scope 通常是 orders.readpayments.write 这样的权限字符串,回答“允许做什么”。
  • Clerk M2M scope 是目标 Machine ID,回答“当前 Machine 可以向哪台 Machine 发起经过 Clerk 认证的调用”。

两者名字相同,语义并不相同。Clerk scope 不能替代订单、文件、租户或管理操作的业务授权。

2. 通用 M2M 机制在解决什么#

设想后台任务 billing-worker 要调用 orders-api。系统至少要回答四个问题:

  1. 调用方是谁?
  2. 它如何证明身份,凭据能否安全轮换?
  3. 这份凭据允许访问哪个服务、执行哪些操作、持续多久?
  4. 接收方如何验证凭据,并在泄漏或离职、下线、事故发生时停止信任?

一次基于 token 的通用流程可以抽象成:

flowchart TD
  A["Machine A 持有客户端凭据"] --> B["向凭据签发方证明身份"]
  B --> C["取得短期 token:主体、目标、权限、期限"]
  C --> D["通过 HTTPS 调用 Machine B,并携带 token"]
  D --> E["Machine B 验证签名或查询 token 状态"]
  E --> F["检查目标、期限、权限与调用方"]
  F --> G["应用执行或拒绝具体业务操作"]

这里包含三个不同阶段:

  • 认证(Authentication):确认凭据对应哪个机器主体。
  • 凭据签发与授权表达:生成一份带有期限、目标和权限的 token。
  • 业务授权(Authorization):接收方决定这个机器能否执行当前操作。

认证成功不等于允许所有操作。HTTP 层通常把“token 无效或无法认证”映射为 401,把“身份有效但权限不足”映射为 403;OAuth Bearer token 对应的标准错误是 invalid_tokeninsufficient_scopeRFC 6750 §3.1

常见方案并不只有 OAuth#

方案主要特点适合场景主要代价
静态 API Key直接把长期随机秘密交给调用方系统少、权限简单、可接受人工治理长期秘密容易扩散;目标、权限、轮换和审计经常要自建。
mTLS双方用证书和私钥在 TLS 层认证Service Mesh、受控基础设施、高价值内部服务证书签发、轮换、服务身份映射和网关兼容性更复杂。
HMAC / 签名请求对请求方法、路径、时间戳和 body 签名Webhook、云 API、需要防篡改或限制重放往往是厂商协议;canonical request 与时钟处理容易出错。
OAuth 2.0 Client Credentials标准 token endpoint、Client Authentication、scope 与 access token多客户端、多 Resource Server、需要标准工具互通要部署或购买 Authorization Server,并设计 scope、audience 与 key lifecycle。
厂商 M2M token 服务厂商封装主体、凭据、token 与管理面已采用该身份平台、边界清晰的内部服务语义与互操作性受厂商协议约束。

所以,说“M2M 是通用标准”只对了一半:问题与术语是通用的,具体协议必须另说

3. 标准化路径:OAuth 2.0 Client Credentials#

RFC 6749 §4.4规定,Client Credentials grant 只用于能安全保存凭据的 confidential client。典型客户端是后端服务、定时任务、CI/CD Runner,而不是浏览器 SPA 或无法保密的移动应用。

它适用于客户端访问自己控制的资源,或访问已经和 Authorization Server 预先约定授权关系的资源。流程中没有浏览器跳转、用户登录或授权确认页面:

flowchart TD
  A["Client:billing-worker"] --> B["Token Endpoint:Client Authentication"]
  B --> C["Authorization Server 校验客户端和预配置权限"]
  C --> D["签发短期 access token"]
  D --> E["Client 调用 Resource Server:orders-api"]
  E --> F["orders-api 校验 token,再执行应用授权"]

3.1 标准请求长什么样#

使用客户端密码的最小请求如下。Authorization: Basic 只是 Client Authentication 方法之一,不是 Client Credentials grant 本身。

POST /token HTTP/1.1
Host: authorization.example.com
Authorization: Basic <base64(client_id:client_secret)>
Content-Type: application/x-www-form-urlencoded

grant_type=client_credentials&scope=orders.read

Authorization Server 验证客户端及其预配置授权后返回:

{
  "access_token": "opaque-or-jwt-value",
  "token_type": "Bearer",
  "expires_in": 300,
  "scope": "orders.read"
}

随后客户端调用 Resource Server:

GET /orders/123 HTTP/1.1
Host: orders.example.com
Authorization: Bearer <access_token>

RFC 6749 要求 grant_type=client_credentials,允许请求 scope,并要求客户端在 token endpoint 完成认证;此流程通常不发 refresh token,过期后重新认证并取新 token即可。RFC 6749 §4.4.2–4.4.3

3.2 Grant Type 不等于 Client Authentication 方法#

这是 M2M 实现里最常见的概念错误。

维度回答的问题常见值
Authorization Grant Type客户端凭什么请求这段授权?client_credentials
Client Authentication MethodAuthorization Server 如何确认客户端身份?client_secret_basic、JWT client assertion、mTLS
Access Token Format发给 Resource Server 的 token 长什么样?Opaque token、JWT
Token Usage调用 API 时如何证明持有 token?Bearer、mTLS-bound、DPoP-bound

client_id 只是公开标识符,不能单独用于认证。RFC 6749 §2.2 如果用 JWT client assertion 认证客户端,JWT 是提交给 token endpoint 的客户端凭据;如果 access token 本身采用 JWT,那个 JWT 才是提交给 Resource Server 的授权凭据。两者不是一件东西。RFC 7523 §2

3.3 scope、resource 与 audience#

  • scope 约束“允许做什么”。它是由 Authorization Server 定义、区分大小写的权限字符串集合;服务端可以下调客户端请求的权限。RFC 6749 §3.3
  • resource 是客户端在授权请求或 token request 中声明的目标服务。RFC 8707 §2
  • aud 是 token 实际面向的 audience。Resource Server 必须确认自己是合法接收方;只验证 JWT 签名却不验证 issaudexp 和 token 类型是不完整的验证。RFC 9068 §4

一句话概括:scope 约束“做什么”,resource / audience 约束“在哪里做”

3.4 JWT 不是 OAuth 的必选项#

OAuth access token 对客户端本来就应当是 opaque value:客户端不该依赖内部结构。Authorization Server 可以签发真正的 Opaque token,由 Resource Server 调用 Introspection endpoint 查询状态;也可以签发 JWT,让 Resource Server 使用公钥在本地验证。RFC 7662 §2

二者是工程取舍:

形态验证路径优势限制
Opaque token查询 Authorization Server 或共享状态即时撤销、集中策略和使用记录更自然增加网络依赖、延迟和验证服务容量。
JWT access token本地验签并校验 claims低延迟、离线验证、易横向扩展已签发 token 很难即时撤销,必须依靠短 TTL 或额外状态。

无论是哪种格式,普通 Bearer token 都是“谁拿到谁能用”。应通过 HTTPS 的 Authorization header 发送,不应放在 URL;URL 很容易进入浏览历史、代理、访问日志与监控系统。RFC 6750 §2.1、§2.3 高风险场景还应评估 mTLS certificate-bound token 或 DPoP,让 token 只能配合指定私钥使用。RFC 9700 §4.10

4. Clerk M2M Tokens 到底是什么#

Clerk 把内部服务间认证建模成一组 Machine 和有方向的信任关系。它复用了 HTTPS Bearer token、JWT 等通用构件,但签发接口、对象模型和 scope 语义由 Clerk 定义。

截至资料核验日,Clerk 的 Machine Authentication 总览明确区分了 OAuth access tokens、M2M Tokens 与 API Keys,并写明 尚未支持 OAuth Client CredentialsClerk Machine Authentication

因此,Clerk M2M Tokens 不能被描述成“Clerk 对 Client Credentials 的封装”。更准确的说法是:

Clerk 提供了一套面向同一 Clerk Instance 内部后台服务的专有 Machine Token 服务,并用 SDK 与 Backend API 封装创建、传输、验证和生命周期管理。

4.1 对象与标准概念的映射#

通用 / OAuth 概念Clerk 对应对象是否等价
机器主体 / OAuth ClientMachine,ID 以 mch_ 开头用途相近,但不是 OAuth Client Registration。
Client CredentialMachine Secret Key用途相近,但不是标准 client_id + Client Authentication metadata。
Token EndpointPOST /m2m_tokensm2m.createToken()都用于取 token,但请求协议不是 OAuth token endpoint。
Access TokenClerk M2M Token,Opaque 值通常以 mt_ 开头,也可为 JWT可作为 API Bearer credential,但不是由 Client Credentials grant 产生的 OAuth access token。
OAuth scopeClerk Machine scope不等价:Clerk 存的是目标 Machine ID,不是动作权限字符串。
Resource / audience被授权访问的目标 Machine作用相近,但应按 Clerk 的 scopes 结果与 SDK 契约处理,不能假定是标准 OAuth aud
Introspection / JWT Validationm2m.verify()Opaque token 远程校验;JWT 本地验签。接口和响应属于 Clerk。

一个通用 OAuth Client 不能把 Clerk /m2m_tokens 当作标准 token endpoint:Clerk 请求不使用 grant_type=client_credentials,也没有 OAuth 的标准 Client Authentication 与 scope 请求模型。反过来,未集成 Clerk 验证逻辑的第三方 Resource Server 也不会自动理解 Clerk M2M Token。

4.2 Clerk 的完整流程#

billing-worker 调用 orders-api 为例:

flowchart TD
  A["管理员在 Clerk 创建 orders-api Machine"] --> B["创建 billing-worker Machine"]
  B --> C["配置单向 scope:billing-worker → orders-api"]
  C --> D["两台 Machine 分别保存自己的 Machine Secret Key"]
  D --> E["billing-worker 用自己的 Secret Key 调用 createToken()"]
  E --> F["Clerk 签发 token:subject=调用方,scopes=目标 Machine ID"]
  F --> G["billing-worker 以 Bearer token 调用 orders-api"]
  G --> H["orders-api 用 SDK 验证 token"]
  H --> I["orders-api 检查调用方和业务权限后执行请求"]

几个关键点:

  • Machine scope 是单向的。A → B 不代表 B → A;双向调用要分别配置。
  • 每台 Machine 有自己的 Machine Secret Key。它只能保存在服务端秘密管理系统中,不能放进浏览器、移动客户端或 NEXT_PUBLIC_* 等公开变量。
  • createToken() 不接收本次调用自选的 scope;Clerk 会把调用方 Machine 当前配置的目标 Machine IDs 写入新 token。
  • Machine 最多配置 150 个目标 scope。Clerk machines.create()
  • 修改 Machine scope 只影响之后新建的 token;旧 token 保留签发时的 scope。删除关系不是对既有 token 的即时 kill switch。Clerk M2M Tokens Guide
  • 验证成功后,subject 表示调用方 Machine ID,scopes 表示可访问的目标 Machine IDs。应用还要检查预期调用方、租户和具体操作权限。

4.3 Opaque 与 JWT#

Clerk 默认创建 Opaque token,也允许创建 JWT:

Clerk 行为Opaque tokenJWT
Clerk 是否保存
验证调用 Clerk Backend API使用 Clerk Instance 公钥 / JWKS 本地验签
即时撤销支持不支持,签发后有效到过期
list()支持不返回
last_used_atClerk 可跟踪Clerk 无法跟踪本地使用
运行时依赖依赖 Clerk 网络与可用性可离线验证,延迟更低
成本创建和远程验证按量计费创建按量计费,本地验证不收费
适合强调即时撤销、集中审计高 QPS、低延迟、可接受短 TTL 的内部调用

Opaque token 可以通过 minRemainingTtlSeconds 复用 Clerk 端已有、未撤销、未过期且 claims/scopes 相同的 token,适合短生命周期 Serverless 或频繁扩缩容的 Worker;JWT 不参与这项去重。Clerk createToken()

生产环境不要依赖默认 TTL。当前 Clerk SDK 参考文字、主指南示例和 2026-05-12 OpenAPI 对省略 TTL 的描述并不完全一致;OpenAPI 又给 Machine 定义了 3600 秒默认 TTL。更稳妥的做法是每次显式设置 secondsUntilExpiration,并验证返回的 expiration

5. Clerk 最小可运行示例#

下面使用 Node.js ESM,不依赖 Web 框架。示例按 Node.js 20.9+ 与 @clerk/backend 3.16.4 编写,使用默认 Opaque token;运行需要自己的 Clerk Development Instance。

5.1 准备 Clerk 资源#

  1. 在 Clerk Dashboard 的 M2M authentication 页面创建接收方 orders-api
  2. 创建调用方 billing-worker,在 Scopes 中选择 orders-api,形成 billing-worker → orders-api
  3. 分别记录两个 mch_... Machine ID,并取得各自的 Machine Secret Key。
  4. 安装依赖:
npm install @clerk/backend@3.16.4

把两个环境文件加入 .gitignore。示例值必须替换为自己的凭据:

# .env.machine-b
CLERK_MACHINE_SECRET_KEY=ak_xxx_receiver
RECEIVER_MACHINE_ID=mch_xxx_orders_api
EXPECTED_CALLER_MACHINE_ID=mch_xxx_billing_worker
# .env.machine-a
CLERK_MACHINE_SECRET_KEY=ak_xxx_caller
TARGET_URL=http://127.0.0.1:3001/internal/orders

5.2 接收方:验证后再授权#

// receiver.mjs
import { createServer } from 'node:http'
import { createClerkClient } from '@clerk/backend'

function requiredEnv(name) {
  const value = process.env[name]
  if (!value) throw new Error(`Missing environment variable: ${name}`)
  return value
}

function bearerToken(header) {
  const match = /^Bearer\s+([^\s]+)$/i.exec(header ?? '')
  return match?.[1] ?? null
}

function json(response, status, body) {
  response.writeHead(status, {
    'content-type': 'application/json; charset=utf-8',
  })
  response.end(JSON.stringify(body))
}

const machineSecretKey = requiredEnv('CLERK_MACHINE_SECRET_KEY')
const receiverMachineId = requiredEnv('RECEIVER_MACHINE_ID')
const expectedCallerMachineId = requiredEnv('EXPECTED_CALLER_MACHINE_ID')
const clerk = createClerkClient({ machineSecretKey })

const server = createServer(async (request, response) => {
  if (request.method !== 'POST' || request.url !== '/internal/orders') {
    return json(response, 404, { error: 'not_found' })
  }

  const token = bearerToken(request.headers.authorization)
  if (!token) return json(response, 401, { error: 'missing_token' })

  try {
    const verified = await clerk.m2m.verify({ token })

    // Opaque verify 已由接收方 Machine Secret Key 约束目标;这里仍显式检查,
    // 既让授权边界可读,也保护未来切换为 JWT 的路径。
    const canCallReceiver = verified.scopes.includes(receiverMachineId)
    const isExpectedCaller = verified.subject === expectedCallerMachineId

    if (!canCallReceiver || !isExpectedCaller) {
      return json(response, 403, { error: 'forbidden' })
    }

    // 此处继续检查租户、动作和资源级业务权限。
    return json(response, 200, {
      ok: true,
      callerMachineId: verified.subject,
    })
  } catch {
    // 不把 token、Machine Secret Key 或 Clerk 原始错误写入响应/日志。
    return json(response, 401, { error: 'invalid_token' })
  }
})

server.listen(3001, '127.0.0.1', () => {
  console.log('receiver listening on http://127.0.0.1:3001')
})

5.3 调用方:创建短期 token 并发送#

// caller.mjs
import { createClerkClient } from '@clerk/backend'

function requiredEnv(name) {
  const value = process.env[name]
  if (!value) throw new Error(`Missing environment variable: ${name}`)
  return value
}

const machineSecretKey = requiredEnv('CLERK_MACHINE_SECRET_KEY')
const targetUrl = requiredEnv('TARGET_URL')
const clerk = createClerkClient({ machineSecretKey })

const issued = await clerk.m2m.createToken({
  tokenFormat: 'opaque',
  secondsUntilExpiration: 300,
  minRemainingTtlSeconds: 60,
})

if (!issued.token) throw new Error('Clerk did not return a token')

const response = await fetch(targetUrl, {
  method: 'POST',
  headers: {
    'content-type': 'application/json',
    authorization: `Bearer ${issued.token}`,
  },
  body: JSON.stringify({ orderId: 'order_demo_123' }),
})

console.log(response.status, await response.text())

依次运行:

node --env-file=.env.machine-b receiver.mjs
node --env-file=.env.machine-a caller.mjs

预期调用方收到 200,响应只包含已验证的 Machine ID,不输出 token。删除 billing-worker → orders-api scope 后,必须重新创建 token 才能观察新配置;已签发 token 仍保留旧 scope。

如果切换到 tokenFormat: 'jwt',接收方要配置 Clerk 公钥 / jwtKey,并保留 verified.scopes.includes(receiverMachineId) 检查。按 @clerk/backend 3.16.4 当前源码,JWT 分支本地验签并映射 scopes,不会使用接收方 Machine Secret Key 发起远程 scope 校验;因此不能只验证签名和过期时间。M2MTokenApi.tsM2MToken.ts

6. Clerk 具体替应用做了哪些工作#

层次Clerk 提供应用仍要负责
身份控制面创建 Machine、分配稳定 ID、生成与轮换 Machine Secret Key一台 Machine 对应哪个部署/环境,秘密写入哪个 Secret Manager。
服务信任关系用单向 Machine scope 配置可访问的目标 Machine设计最小信任图,避免所有服务互相可达。
Token 签发验证 Machine Secret Key,写入 subjectscopes、期限和可选 claims,输出 Opaque/JWT选择显式短 TTL、缓存策略与 token 格式。
Token 验证Opaque 远程校验;JWT 公钥验签;SDK 返回统一 M2MToken核对目标 Machine、预期调用方、业务动作、租户和资源。
生命周期列出和撤销 Opaque token、轮换 Machine Secret Key、统计使用量事故响应、应用审计日志、异常检测和旧部署下线。
开发体验Dashboard、Backend API、多语言 SDK、示例与用量页面把验证接入每个入口,统一 401 / 403 语义并测试失败路径。

Machine Secret Key 可以轮换,旧 key 的过渡窗口可设置为 0 到 28,800 秒(8 小时),便于零停机切换。Clerk rotateSecretKey() Opaque token 可以单独撤销;JWT 不能即时撤销,所以 TTL 就是主要风险窗口。

Custom claims 也不是“Clerk 管理员批准的业务权限”。持有调用方 Machine Secret Key 的代码可在创建 token 时提交 claims;Clerk 负责保存或签名这些值,但接收方仍要判断该调用方是否有权声明并使用它们。

7. Clerk M2M Tokens、Clerk OAuth 与 Clerk API Keys 怎么选#

这是 Clerk 产品内部的三种不同边界:

需求Clerk 当前对应能力主体与授权来源
自己基础设施内的后台服务互调M2M TokensClerk Machine 调用另一个 Clerk Machine。
第三方应用代表用户访问 Clerk APIOAuth access tokens用户授权给 OAuth application。
让应用的用户或 Organization 创建长期 API 凭据API KeysUser / Organization 向调用者委派访问。
标准 OAuth Client Credentials 互操作当前不由 Clerk M2M Tokens 提供选择支持 Client Credentials 的 Authorization Server,或等待 Clerk 正式支持。

如果 API 要开放给大量第三方客户、现成 API Gateway 或标准 OAuth Client,优先要求 OAuth 2.0 Client Credentials、Authorization Server Metadata、明确的 scope/resource/audience 契约。若服务都在同一组织、同一 Clerk Instance 内,并希望快速获得机器注册、方向性信任、token 管理和 SDK,Clerk M2M Tokens 更直接。

8. 生产安全清单#

  • 每个服务、环境和重要部署单元使用独立 Machine,不共享万能 Machine Secret Key。
  • Machine Secret Key 只进入后端 Secret Manager;不提交 Git、不进入公开环境变量、不打印到日志。
  • 所有签发与业务请求使用 HTTPS;Bearer token 只放 Authorization header,不放 URL。
  • 显式配置短 secondsUntilExpiration,不要依赖当前文档中不一致的默认 TTL。
  • 使用方向性最小 scope;记住 scope 变更只影响新 token。
  • Opaque token 需要即时撤销时建立撤销与事故流程;JWT 则把 TTL 压到可接受的风险窗口。
  • 缓存仍然有效的 token,不要为每个下游请求无条件签发新 token;Opaque 可使用 minRemainingTtlSeconds
  • 验证 token 后继续检查目标 Machine ID、预期调用方、租户、动作和资源权限。
  • JWT 验证必须检查签名、允许算法、期限和 Clerk SDK 返回的目标 scopes;不要只做 Base64 解码。
  • 不把 custom claims 自动视为可信的管理员授权。
  • 对高价值或跨信任域系统评估 sender-constrained token、mTLS 或网络层双向身份;普通 Bearer token 泄漏后可以被重放。
  • 测试缺失 token、错误 token、过期、已撤销、scope 缺失、错误调用方、Clerk 暂时不可用和 key 轮换窗口。

9. 当前 Clerk 文档的核验备注#

截至 2026-08-13,官方资料里有几处容易让示例失效或产生错误假设:

  1. M2M 主指南先说明返回字段为 token,但它的 fetch 示例使用了 m2mToken.secret。当前 M2MToken 类型和 SDK 实现使用 m2mToken.token,本文以类型与源码为准。
  2. 主指南的 list() 示例把 mt_123 注释成 Machine ID。当前对象约定是 Machine ID 使用 mch_...,M2M Token 使用 mt_...
  3. 当前 SDK 方法名是 m2m.verify();较早示例中的 verifyToken() 不应直接套用到 3.16.4。
  4. secondsUntilExpiration 的 SDK 文字说明、指南返回示例和 OpenAPI 的 Machine 默认 TTL 不完全一致。本文不推断唯一默认值,统一显式设置。
  5. Opaque token 的接收方 scope 校验有明确 Backend API 契约;当前 JWT SDK 分支是本地验证。使用 JWT 时应显式检查接收方 Machine ID,并针对项目锁定版本做集成测试。

这些都属于 Clerk 当前实现细节,不改变 M2M、OAuth、Bearer 或 JWT 的标准定义。

10. 价格与适用边界#

Clerk M2M Tokens 是按量付费能力。2026-08-13 官方页面列出的价格是:token 创建每次 $0.001,每月前 2,500 次免费;远程验证每次 $0.00001,每月前 100,000 次免费。Hobby 只能使用免费额度,超出需升级 Pro;JWT 本地验证不产生验证费用。Clerk M2M Tokens Pricing

价格、免费额度、套餐限制和计费口径都属于 Clerk 产品事实,而不是 M2M 或 OAuth 标准的一部分,上线前应重新核对。

11. 一手资料#

IETF 标准#

Clerk 官方资料#

本文共 8024 字,上次修改于 Aug 13, 2026,以 CC 署名-非商业性使用-禁止演绎 4.0 国际 协议进行许可。

相关文章

» JWT 介绍和场景示例

» HTTPS 的 SSL/TLS 协议

» 跨域相关问题

» Cookie 机制

» Chrome URLs