mcpField
B
b2c-slas-auth-patterns

b2c-slas-auth-patterns

github.com/salesforcecommercecloud安全57112 次安装今天更新
代码仓库

关于 b2c-slas-auth-patterns

面向 Salesforce B2C Commerce 开发者的 SLAS 认证技能,涵盖基础登录之外的认证模式。内容包括无密码登录、店铺会话衔接、系统间访问与令牌安全,并提供 PWA Kit、Storefront Next 和 SFRA 示例。

主要功能

  1. 01电子邮件和短信 OTP 流程
  2. 02FIDO2/WebAuthn 密钥
  3. 03PWA Kit 与 SFRA 会话桥接
  4. 04混合认证指南
  5. 05TSOB 与令牌管理
  6. 06使用 JWKS 验证 JWT

适用场景

  1. 01为店铺添加无密码登录
  2. 02衔接 PWA Kit 与 SFRA 会话
  3. 03让后端服务代表购物者操作
  4. 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.json
references/
PASSKEYS.md
SESSION-BRIDGE.md
TOKEN-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 格式、参数和速率限制。

通过电子邮件发送一次性密码,以实现无密码登录。

流程概览
  1. 使用回调 URI 调用 /oauth2/passwordless/login
  2. SLAS 向你的回调 POST pwdless_login_token
  3. 你的应用通过电子邮件向购物者发送 OTP
  4. 购物者输入 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 配置短信:

  1. 设置 Marketing Cloud 连接器
  2. 配置包含 OTP 模板的短信旅程
  3. 通过 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:

  1. 升级到 B2C Commerce 25.3+
  2. 在 Business Manager 中启用 Hybrid Auth
  3. 移除 Plugin SLAS cartridge
  4. 更新店面以使用平台身份验证

令牌刷新

用于说明流程;请使用 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;
        }
    }
}
必需的配置
  1. SLAS 客户端必须启用 TSOB(sfcc.ts_ext_on_behalf_of 作用域)
  2. 在 SLAS Admin API 或 Business Manager 中进行配置
  3. 妥善保护客户端密钥(仅限服务器端使用)
  4. 将 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已授予的作用域
tsobTSOB 令牌类型(用于可信系统令牌)

最佳实践

安全
  • 切勿在前端代码中暴露客户端密钥
  • 所有令牌交换都使用 HTTPS
  • 对敏感操作在服务端验证令牌
  • 实施适当的 CORS 策略
  • 安全存储令牌(优先使用 httpOnly Cookie)
令牌管理
  • 在令牌过期前主动刷新
  • 为公共客户端处理刷新令牌轮换
  • 用户退出登录时,从所有存储位置清除令牌
  • 尽可能使用短期访问令牌
  • 刷新请求中始终包含 channel_id
用户体验
  • 提供备用身份验证方式
  • 身份验证失败时显示清晰的错误消息
  • 记住用户首选的身份验证方式
  • 妥善处理会话过期

详细参考资料

评论

支持 Markdown