关于 b2c-slas-auth-patterns
面向 Salesforce B2C Commerce 开发者的 SLAS 认证技能,涵盖基础登录之外的认证模式。内容包括无密码登录、店铺会话衔接、系统间访问与令牌安全,并提供 PWA Kit、Storefront Next 和 SFRA 示例。
主要功能
- 01电子邮件和短信 OTP 流程
- 02FIDO2/WebAuthn 密钥
- 03PWA Kit 与 SFRA 会话桥接
- 04混合认证指南
- 05TSOB 与令牌管理
- 06使用 JWKS 验证 JWT
适用场景
- 01为店铺添加无密码登录
- 02衔接 PWA Kit 与 SFRA 会话
- 03让后端服务代表购物者操作
- 04在服务端验证 SLAS 令牌
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ salesforcecommercecloud/ b2c-developer-tooling --skill b2c-slas-auth-patterns安装后在 Claude Code 中输入/b2c-slas-auth-patterns确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
evals/trigger-evals.jsonreferences/PASSKEYS.mdSESSION-BRIDGE.mdTOKEN-LIFECYCLE.md详细介绍
B2C SLAS 认证模式
超越基本登录的 SLAS(Shopper Login and API Access Service,购物者登录和 API 访问服务)高级认证模式。这些模式支持无密码认证、混合店面和系统间集成。
范围与依据
此技能涵盖 SLAS 认证模式,包括无密码登录(电子邮件 OTP、短信、通行密钥)、会话桥接、混合认证(B2C 25.3+)、令牌管理、TSOB,以及 PWA Kit、Storefront Next 和 SFRA 的框架专用示例。代码示例仅用于说明典型流程。回答特定于版本的问题、框架专用实现,或提供用户将在生产环境中运行的代码之前,请通过 b2c docs search 和 b2c docs read 对照官方文档确认当前 API 契约、参数、速率限制和版本要求。规范文档是 B2C 平台具体信息、API 格式和配置要求的权威来源。
规范文档
commerce-api/slas- SLAS 概览commerce-api/slas-best-practices- 安全和实施最佳实践commerce-api/slas-passwordless-login-overview- 无密码认证概览commerce-api/slas-passwordless-login-email- 电子邮件 OTP 实现commerce-api/slas-passwordless-login-passkey- 通行密钥/WebAuthn 实现commerce-api/slas-passwordless-sms- 短信 OTP 实现commerce-api/slas-session-bridge-overview- 会话桥接概览commerce-api/slas-session-bridge-auth- 会话桥接实现commerce-api/hybrid-authentication- 混合认证(B2C 25.3+)commerce-api/hybrid-auth-pwa-kit-v2- PWA Kit v2 混合认证pwa-kit-managed-runtime/hybrid-auth- PWA Kit 托管运行时混合认证pwa-kit-managed-runtime/plugin-slas-setup- Plugin SLAS 设置commerce-api/slas-trusted-system- 可信系统代为操作(TSOB)commerce-api/slas-public-client- 公共客户端配置commerce-api/slas-private-client- 私有客户端配置commerce-api/slas-validate-jwt-with-jwks- JWT 验证
认证方法概览
| 方法 | 使用场景 | 用户体验 |
|---|---|---|
| 密码 | 传统登录 | 用户名 + 密码表单 |
| 电子邮件 OTP | 无密码电子邮件认证 | 将验证码发送到电子邮箱 |
| 短信 OTP | 无密码短信认证 | 将验证码发送到手机 |
| 通行密钥 | FIDO2/WebAuthn | 生物识别或设备 PIN |
| 会话桥接 | 混合店面 | PWA ↔ SFRA 无缝切换 |
| 混合认证 | B2C 25.3+ | 内置平台认证同步 |
| TSOB | 系统集成 | 后端服务调用 |
无密码电子邮件 OTP
此处仅为流程示例;请通过
b2c docs read commerce-api/slas-passwordless-login-email和b2c docs read commerce-api/slas-passwordless-login-overview确认当前 API 格式、参数和速率限制。
通过电子邮件发送一次性密码,以实现无密码登录。
流程概览
- 使用回调 URI 调用
/oauth2/passwordless/login - SLAS 向你的回调 POST
pwdless_login_token - 你的应用通过电子邮件向购物者发送 OTP
- 购物者输入 OTP,应用用其换取令牌
第 1 步:发起无密码登录
// POST /shopper/auth/v1/organizations/{org}/oauth2/passwordless/login
async function initiatePasswordlessLogin(email, siteId) {
const response = await fetch(
`https://${shortCode}.api.commercecloud.salesforce.com/shopper/auth/v1/organizations/${orgId}/oauth2/passwordless/login`,
{
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: new URLSearchParams({
user_id: email,
mode: 'callback',
channel_id: siteId,
callback_uri: 'https://yoursite.com/api/passwordless/callback'
})
}
);
// SLAS will POST to your callback_uri with pwdless_login_token
return response.json();
}
第 2 步:处理回调并发送 OTP
你的回调端点会收到 pwdless_login_token。生成 OTP 并发送给用户:
// Your callback endpoint (receives POST from SLAS)
app.post('/api/passwordless/callback', async (req, res) => {
const { pwdless_login_token, user_id } = req.body;
// Generate 6-digit OTP
const otp = Math.floor(100000 + Math.random() * 900000).toString();
// Store token + OTP mapping (e.g., Redis with 10 min TTL)
await redis.setex(`pwdless:${otp}`, 600, JSON.stringify({
token: pwdless_login_token,
email: user_id
}));
// Send OTP via email (configure in SLAS Admin UI)
await sendOTPEmail(user_id, otp);
res.status(200).send('OK');
});
第 3 步:用 OTP 换取令牌
// POST /shopper/auth/v1/organizations/{org}/oauth2/passwordless/token
async function exchangeOTPForToken(otp, clientId, clientSecret, siteId) {
// Retrieve stored token
const stored = JSON.parse(await redis.get(`pwdless:${otp}`));
if (!stored) throw new Error('Invalid or expired OTP');
const response = await fetch(
`https://${shortCode}.api.commercecloud.salesforce.com/shopper/auth/v1/organizations/${orgId}/oauth2/passwordless/token`,
{
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Authorization': `Basic ${btoa(clientId + ':' + clientSecret)}`
},
body: new URLSearchParams({
grant_type: 'client_credentials',
hint: 'pwdless_login',
pwdless_login_token: stored.token,
channel_id: siteId
})
}
);
// Returns: { access_token, refresh_token, ... }
return response.json();
}
速率限制
- 每位用户每 10 分钟 6 次请求
- 非生产租户的每个端点每月 1,000 次请求
无密码短信 OTP
通过 Marketing Cloud 或自定义集成使用短信发送 OTP。
使用 Marketing Cloud
通过 Salesforce Marketing Cloud 配置短信:
- 设置 Marketing Cloud 连接器
- 配置包含 OTP 模板的短信旅程
- 通过 SLAS 回调触发(流程与电子邮件 OTP 相同)
自定义短信提供商
使用与电子邮件相同的回调流程,但通过短信提供商发送:
// In your callback handler
const twilio = require('twilio')(accountSid, authToken);
async function sendOTPSMS(phoneNumber, otp) {
await twilio.messages.create({
body: `Your login code is: ${otp}`,
from: '+1234567890',
to: phoneNumber
});
}
Passkeys(FIDO2/WebAuthn)
用于说明流程;请使用
b2c docs read commerce-api/slas-passwordless-login-passkey确认当前 API 形式和参数。
使用 FIDO2/WebAuthn 通行密钥启用生物识别身份验证。注册前需通过 OTP 验证身份。此流程包括先通过 SLAS 启动注册,再使用浏览器 WebAuthn API 创建凭据,最后完成注册。身份验证遵循类似的启动/验证/完成模式。
完整的注册和身份验证代码示例,请参阅 references/PASSKEYS.md。
Session Bridge
用于说明流程;请使用
b2c docs read commerce-api/slas-session-bridge-overview和b2c docs read commerce-api/slas-session-bridge-auth确认当前 API 形式和与平台无关的模式。PWA Kit 示例仅适用于特定框架。
使用已签名的桥接令牌(访客使用 dwsgst,已注册用户使用 dwsrst),在 PWA Kit 和 SFRA 店面之间保持会话连续性。支持 PWA 到 SFRA 和 SFRA 到 PWA 两种方向。请注意,DWSID 已弃用,不再适用于已注册的购物者。
有关完整实现详情,包括令牌生成、重定向模式、回调处理程序和错误处理,请参阅 references/SESSION-BRIDGE.md。
混合身份验证(B2C 25.3+)
用于说明概念;请使用
b2c docs read commerce-api/hybrid-authentication确认版本要求和迁移指南。
Hybrid Auth 将取代混合 PWA/SFRA 店面的 Plugin SLAS。 它直接内置于 B2C 平台中,并提供自动会话同步。
优势
- 无需手动实现会话桥接
- 自动同步 PWA 和 SFRA
- 简化令牌管理
- 内置平台支持
从 Plugin SLAS 迁移
如果正在使用 Plugin SLAS,请迁移到 Hybrid Auth:
- 升级到 B2C Commerce 25.3+
- 在 Business Manager 中启用 Hybrid Auth
- 移除 Plugin SLAS cartridge
- 更新店面以使用平台身份验证
令牌刷新
用于说明流程;请使用
b2c docs read commerce-api/slas-public-client和b2c docs read commerce-api/slas-private-client确认参数要求和令牌轮换行为。
重要: 访客令牌刷新时必须提供 channel_id 参数。
公共客户端(一次性刷新令牌)
公共客户端(无密钥)会收到一次性刷新令牌:
async function refreshTokenPublic(refreshToken, clientId, siteId) {
const response = await fetch(
`https://${shortCode}.api.commercecloud.salesforce.com/shopper/auth/v1/organizations/${orgId}/oauth2/token`,
{
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: new URLSearchParams({
grant_type: 'refresh_token',
refresh_token: refreshToken,
client_id: clientId,
channel_id: siteId // REQUIRED
})
}
);
// Returns NEW refresh_token (old one is invalidated)
return response.json();
}
私有客户端(可重复使用的刷新令牌)
私有客户端可以重复使用刷新令牌:
async function refreshTokenPrivate(refreshToken, clientId, clientSecret, siteId) {
const response = await fetch(
`https://${shortCode}.api.commercecloud.salesforce.com/shopper/auth/v1/organizations/${orgId}/oauth2/token`,
{
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Authorization': `Basic ${btoa(clientId + ':' + clientSecret)}`
},
body: new URLSearchParams({
grant_type: 'refresh_token',
refresh_token: refreshToken,
channel_id: siteId // REQUIRED
})
}
);
// Same refresh_token can be used again
return response.json();
}
可信系统代行(TSOB)
用于说明流程;请使用
b2c docs read commerce-api/slas-trusted-system确认当前 API 形式和配置要求。
通过服务器到服务器的身份验证,代购物者执行操作。
使用场景
- 后端服务访问购物者数据
- 订单管理系统
- 客户服务应用程序
获取代购物者操作的令牌
async function getTSOBToken(shopperLoginId) {
const response = await fetch(
`https://${shortCode}.api.commercecloud.salesforce.com/shopper/auth/v1/organizations/${orgId}/oauth2/trusted-system/token`,
{
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Authorization': `Basic ${btoa(clientId + ':' + clientSecret)}`
},
body: new URLSearchParams({
grant_type: 'client_credentials',
login_id: shopperLoginId,
channel_id: siteId,
usid: shopperUsid // Optional: reuse existing session
})
}
);
// Returns tokens that act as the specified shopper
return response.json();
}
重要限制
3 秒保护窗口: 同一购物者在 3 秒内发起的多次 TSOB 调用会返回 HTTP 409:
"Tenant id <id> has already performed a login operation for user id <user_id> in the last 3 seconds."
在代码中处理此情况:
async function getTSOBTokenWithRetry(shopperLoginId, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
return await getTSOBToken(shopperLoginId);
} catch (error) {
if (error.status === 409 && i < maxRetries - 1) {
await new Promise(r => setTimeout(r, 3000));
continue;
}
throw error;
}
}
}
必需的配置
- SLAS 客户端必须启用 TSOB(
sfcc.ts_ext_on_behalf_of作用域) - 在 SLAS Admin API 或 Business Manager 中进行配置
- 妥善保护客户端密钥(仅限服务器端使用)
- 将
login_id长度限制在 60 个字符以内
JWT 验证
用于说明流程;请使用
b2c docs read commerce-api/slas-validate-jwt-with-jwks确认当前 API 形式和验证模式。
使用 JWKS(JSON Web Key Set)验证 SLAS 令牌。
获取 JWKS
async function getJWKS() {
const response = await fetch(
`https://${shortCode}.api.commercecloud.salesforce.com/shopper/auth/v1/organizations/${orgId}/oauth2/jwks`
);
return response.json();
}
验证令牌
const jose = require('jose');
async function validateToken(accessToken) {
// Get JWKS
const jwksUrl = `https://${shortCode}.api.commercecloud.salesforce.com/shopper/auth/v1/organizations/${orgId}/oauth2/jwks`;
const JWKS = jose.createRemoteJWKSet(new URL(jwksUrl));
// Verify token
const { payload } = await jose.jwtVerify(accessToken, JWKS, {
issuer: `https://${shortCode}.api.commercecloud.salesforce.com/shopper/auth/v1/organizations/${orgId}`,
audience: clientId
});
return payload;
}
令牌声明
| 声明 | 说明 |
|---|---|
sub | 主体(客户 ID 或访客 ID) |
isb | 身份主体绑定 |
iss | 颁发者 |
aud | 受众(客户端 ID) |
exp | 过期时间 |
iat | 颁发时间 |
scope | 已授予的作用域 |
tsob | TSOB 令牌类型(用于可信系统令牌) |
最佳实践
安全
- 切勿在前端代码中暴露客户端密钥
- 所有令牌交换都使用 HTTPS
- 对敏感操作在服务端验证令牌
- 实施适当的 CORS 策略
- 安全存储令牌(优先使用 httpOnly Cookie)
令牌管理
- 在令牌过期前主动刷新
- 为公共客户端处理刷新令牌轮换
- 用户退出登录时,从所有存储位置清除令牌
- 尽可能使用短期访问令牌
- 刷新请求中始终包含
channel_id
用户体验
- 提供备用身份验证方式
- 身份验证失败时显示清晰的错误消息
- 记住用户首选的身份验证方式
- 妥善处理会话过期
详细参考资料
- 通行密钥(FIDO2/WebAuthn) - 注册和身份验证代码示例
- 会话桥接流程 - 会话桥接实现详解
- 令牌生命周期 - 令牌过期和刷新模式