Shopify App 验证凭证完整生命周期:谁颁发、谁持有、谁验证?

文章目录

开发 Shopify App 时,最容易混淆的部分往往不是 API 代码,而是各种凭证。

Client ID、Client Secret、Access Token、Session Token、Webhook HMAC 和 Scope 都与“认证”有关,但它们负责的事情并不一样:

  • 有的证明应用身份
  • 有的允许应用访问商店数据
  • 有的证明当前请求来自哪个商店
  • 有的验证 Webhook 是否来自 Shopify
  • 有的规定应用可以访问哪些数据

理解它们的生命周期,可以帮助我们避免 Token 泄露、权限错误、Webhook 伪造和跨商店访问等问题。


一、先看懂 Shopify App 的信任链

一个典型的嵌入式 Shopify App,大致会经过这样的流程:

开发者创建应用
        ↓
Shopify 生成应用凭据
        ↓
商家安装应用并同意权限
        ↓
应用获得商店访问授权
        ↓
前端请求应用后端
        ↓
后端验证当前商店身份
        ↓
后端调用 Shopify Admin API
        ↓
Shopify 检查 Token 和权限
        ↓
Shopify 发送 Webhook
        ↓
后端验证 Webhook 签名

整个流程中,主要会用到以下身份和授权材料:

名称主要作用
Client ID识别应用
Client Secret证明应用身份
Access Token访问某个商店的 Admin API
Session Token验证嵌入式页面请求
Webhook HMAC验证 Shopify 发来的通知
Scope规定应用可以访问什么

二、Client ID 和 Client Secret

Client ID 是什么?

Client ID 是应用的身份编号。

可以把它理解成:

应用的身份证号码

当开发者在 Shopify Dev Dashboard 中创建应用时,Shopify 会生成 Client ID。

Client ID 通常不是秘密,可以出现在应用配置、授权地址或部分前端配置中。

但它只能说明:

这是哪个应用

它不能单独证明应用拥有访问某个商店数据的权限。

Client Secret 是什么?

Client Secret 是应用的秘密密钥,可以理解为:

应用的秘密印章

它用于证明请求确实来自应用后端,而不是其他人伪造的请求。

Client Secret 只能保存于:

  • 服务器环境变量
  • Gadget 的私密配置
  • 密钥管理服务
  • 后端数据库的加密区域

不要将它放在:

  • React 前端
  • 浏览器 Local Storage
  • URL 参数
  • GitHub 公开仓库
  • 日志文件
  • 公开教程或截图

Client Secret 什么时候使用?

它主要会出现在两个场景。

1. 应用授权流程

在需要使用应用密钥的 OAuth 流程中,应用后端会使用 Client ID、Client Secret 和授权信息完成授权交换。

Shopify 会确认这些信息是否属于当前应用。

2. Webhook 签名验证

Shopify 发送 Webhook 时,会使用应用的 Client Secret 对请求体生成 HMAC-SHA256 签名。

应用后端收到请求后,也使用相同的 Client Secret 重新计算签名,然后进行比较。

Client Secret 不应该被理解为“永远不会改变的密码”。它应该按照长期敏感密钥来管理,需要时可以轮换或撤销。


三、Access Token:访问商店数据的钥匙

Access Token 是应用后端访问 Shopify Admin API 的授权凭证。

可以这样理解:

Client ID:我是哪一个应用?
Client Secret:我能证明我是这个应用吗?
Access Token:我被允许访问哪一家商店?

Access Token 如何产生?

典型安装流程如下:

商家点击安装应用
        ↓
Shopify 展示应用申请的权限
        ↓
商家同意授权
        ↓
应用完成授权交换
        ↓
应用获得商店访问 Token

具体的 Token 类型和获取方式取决于应用类型、分发方式以及当前 Shopify 授权流程。

有些应用使用长期有效的访问授权,有些应用使用会过期的 Token,并配合 Refresh Token 自动刷新。因此,应用不应该默认 Access Token 永远有效。

Access Token 应该保存在哪里?

Access Token 只应该由服务端保存,例如:

Gadget 数据库
服务器加密存储
密钥管理服务
安全的环境变量

不应该放在:

  • React 代码
  • HTML 页面
  • 浏览器 Cookie
  • Local Storage
  • URL 查询参数
  • 前端日志

推荐的数据流是:

React 页面
        ↓
Gadget 或应用后端
        ↓
读取服务端保存的 Access Token
        ↓
调用 Shopify Admin API

而不是:

React 页面
        ↓
直接携带 Access Token
        ↓
请求 Shopify Admin API

Shopify 如何验证 Access Token?

应用后端调用 Admin API 时,会将 Access Token 放到请求中。

Shopify 会检查:

  • Token 是否存在
  • Token 是否有效
  • Token 是否已经过期或撤销
  • Token 是否属于当前商店
  • 当前授权是否包含所需 Scope

只要其中一项不符合,API 请求就可能失败。


四、Session Token:嵌入式页面的临时通行证

Session Token 主要用于嵌入式 Shopify App。

它和 Access Token 不一样:

Token用途
Session Token验证当前页面请求来自哪个 Shopify Admin 环境
Access Token让服务端访问 Shopify Admin API

Session Token 可以理解为:

商家今天打开应用时拿到的一张临时通行证

Session Token 的工作流程

商家打开 Shopify Admin 中的应用
        ↓
嵌入式页面加载
        ↓
App Bridge 初始化
        ↓
前端请求当前 Session Token
        ↓
前端将 Token 发给应用后端
        ↓
后端验证 Token
        ↓
后端确认当前商店身份

Session Token 通常是短期有效的 JWT,包含用于认证的声明,例如:

  • 当前应用身份
  • 当前商店目标
  • 签发时间
  • 过期时间
  • 会话相关信息

它的有效期较短,因此不能把它当成长期登录凭证。

后端需要检查什么?

应用后端应该检查:

  • 签名是否正确
  • Token 是否属于当前应用
  • Token 是否已经过期
  • 当前请求属于哪一家商店
  • 请求是否来自正确的嵌入式应用环境

验证成功后,后端才能建立当前请求的商店上下文,并根据商店身份读取对应的数据和 Access Token。


五、Webhook HMAC:Shopify 通知上的防伪签名

Webhook 是 Shopify 主动发送给应用的通知。

例如:

商品创建
商品更新
订单创建
商家卸载应用
隐私数据删除请求

但服务器不能因为“收到了一条 HTTP 请求”就直接执行操作。

它需要先确认:

这条通知是不是 Shopify 发来的?
内容有没有被修改?

这就是 Webhook HMAC 的作用。

Shopify 如何生成 HMAC?

Shopify 每次发送 Webhook 时,会使用应用的 Client Secret 对原始请求体计算 HMAC-SHA256。

签名通常放在请求头:

X-Shopify-Hmac-Sha256

后端收到请求后,需要:

  1. 读取原始请求体
  2. 使用 Client Secret 重新计算 HMAC
  3. 与请求头中的签名进行比较
  4. 验证失败时拒绝处理
  5. 验证成功后再执行业务逻辑

验证时应该使用原始请求体。如果请求体已经被 JSON 解析、格式化或重新序列化,重新计算出来的签名可能不一致。

HMAC 验证后还要做什么?

签名正确只说明:

消息来自拥有 Client Secret 的一方,并且内容没有被随意修改

它不能保证消息没有重复,也不能保证事件一定按顺序到达。

因此,后端还应该处理:

  • Webhook 重试
  • 重复事件
  • 事件乱序
  • 处理失败
  • 网络延迟

可以使用:

X-Shopify-Webhook-Id

作为事件去重依据。

推荐流程:

收到 Webhook
        ↓
验证 HMAC
        ↓
读取 Webhook ID
        ↓
检查是否已经处理过
        ↓
记录事件状态
        ↓
执行幂等业务逻辑

六、Scope:应用的权限清单

Scope 不是 Token,也不是密码。

它是一份权限清单,例如:

read_products
write_products
read_orders
read_customers
read_inventory

它规定应用可以访问和修改哪些数据。

Scope 的授权过程

开发者声明应用需要哪些权限
        ↓
Shopify 在安装页面展示这些权限
        ↓
商家查看并同意
        ↓
Shopify 记录该商店的授权范围
        ↓
API 请求时执行权限检查

因此,Scope 的关系可以简单理解为:

开发者提出申请
商家同意授权
Shopify 保存并执行

如果应用一开始只有:

read_products

后来新增:

write_products

已经安装的商店通常需要重新授权,才能使用新的写入权限。

应用不应该一次申请所有权限,而应该遵守最小权限原则:

只申请当前功能真正需要的 Scope。

这样可以:

  • 减少商家的疑虑
  • 降低数据风险
  • 简化安装体验
  • 降低审核复杂度
  • 让应用更容易维护

七、完整的凭证生命周期

阶段一:开发者创建应用

开发者创建 Shopify App
        ↓
Shopify 生成 Client ID 和 Client Secret
        ↓
开发者将 Client Secret 保存到服务端
        ↓
应用声明所需 Scope

阶段二:商家安装应用

商家点击安装
        ↓
Shopify 展示权限列表
        ↓
商家同意授权
        ↓
应用完成 OAuth 或对应授权流程
        ↓
应用获得 Access Token
        ↓
Access Token 安全保存到服务端

阶段三:商家使用应用

商家打开 Embedded App
        ↓
App Bridge 获取 Session Token
        ↓
前端携带 Session Token 请求后端
        ↓
后端验证 Session Token
        ↓
确认当前商店身份
        ↓
后端读取该商店的 Access Token
        ↓
调用 Shopify Admin API
        ↓
Shopify 检查 Access Token 和 Scope
        ↓
返回数据或执行操作

阶段四:Shopify 发送 Webhook

商品或订单发生变化
        ↓
Shopify 使用 Client Secret 生成 HMAC
        ↓
发送 Webhook
        ↓
后端验证 HMAC
        ↓
检查 Webhook ID 是否重复
        ↓
执行幂等业务逻辑

八、用五句话记住这些凭证

Client ID:
应用的身份证号码。

Client Secret:
应用的秘密印章。

Access Token:
访问某个商店 Admin API 的钥匙。

Session Token:
嵌入式页面请求使用的临时通行证。

Webhook HMAC:
Shopify 通知上的防伪签名。

Scope:
商家同意的权限清单。

九、开发时最容易犯的错误

把 Access Token 放进前端

Access Token 只能由服务端使用。

正确流程:

React → 应用后端 → Shopify Admin API

把 Session Token 当成 Access Token

Session Token 用于验证当前页面请求,Access Token 用于访问 Shopify 数据。

两者用途不同、保存位置不同、有效期也不同。

认为 Scope 一旦配置就永久生效

新增权限后,已经安装的商店通常需要重新授权。

只验证 HMAC,不做事件去重

Webhook 可能重试,同一个事件可能多次到达。

使用处理后的 JSON 验证 HMAC

验证时应尽量保留原始请求体。

假设 Access Token 永远不会过期

应用应该能够处理:

  • Token 失效
  • Token 过期
  • Token 刷新
  • 商家撤销授权
  • 应用重新授权

十、最终理解

Shopify App 的认证不是一把钥匙,而是一整条信任链:

Client ID / Client Secret
        ↓
证明应用身份

Access Token
        ↓
允许应用访问某个商店

Scope
        ↓
规定应用可以做哪些操作

Session Token
        ↓
验证当前嵌入式页面请求

Webhook HMAC
        ↓
验证 Shopify 发来的通知

整个系统可以总结为:

应用身份
+
商店授权
+
当前请求身份
+
API 权限
+
Webhook 签名

当你明确知道每一种凭证是谁生成、谁保存、什么时候验证,以及验证失败后应该怎么处理,Shopify App 的认证体系就不再是一堆容易混淆的名词,而会变成一条清晰的安全流程。

citation:Installing and setting up apps

citation:Creating webhooks

citation:Shopify Editions | Winter ’26