DID Connect 允许你将多个不同的身份验证会话链接在一起,通过一次初始交互为用户创建一个无缝的多步骤流程。这对于复杂的场景非常理想,例如用户注册后进行 KYC,或者登录后进行交易确认。
本指南解释了链接工作流背后的机制以及如何在它们之间传递数据。
核心机制
链接工作流的关键在于 onAuth 生命周期回调。当 DID Connect 会话中的一个步骤成功完成后,onAuth 处理程序不是简单地结束会话,而是可以启动一个新的会话,并指示用户的钱包自动进入该会话。
这是通过从 onAuth 函数返回两个特定属性来实现的:
nextWorkflow:下一个 DID Connect 会话的完整深层链接 URL。nextToken:下一个工作流的会话令牌。
当钱包收到包含 nextWorkflow 的响应时,它会立即打开此 URL,开始流程的下一个阶段,而无需用户扫描新的二维码。原始会话保持待定状态,直到整个工作流链完成或被拒绝。
会话完成的工作原理
当你将会话 A 链接到会话 B 时:
- 会话 A 的
onAuth返回会话 B 的nextWorkflow和nextToken。 - 会话 A 不会被标记为
succeed。相反,它会记录它已被会话 B 接替。 - 当会话 B(链中的最终会话)成功完成时,它会将自己标记为
succeed。 - 然后它会查找
prevToken(会话 A 的令牌)并将该会话也标记为succeed,从而确保整个链被正确关闭。

在工作流之间传递数据
通常,你需要将上下文从一个步骤传递到下一个步骤。例如,将用户的 DID 从登录步骤传递到后续的购买步骤。这可以通过使用 nextWorkflowData 和 previousWorkflowData 来实现。
发送数据
在第一个会话的
onAuth处理程序中,返回一个名为nextWorkflowData的对象。该对象将被自动进行 Base64 编码,并作为previousWorkflowData查询参数附加到nextWorkflowURL 中。接收数据
下一个会话将自动解析此参数。解码后的数据将在该会话的所有生命周期钩子(
onStart、onConnect、onAuth)内的extraParams.previousWorkflowData对象中可用。
如果你链接了两个以上的工作流(A → B → C),数据会被合并。当会话 B 返回自己的 nextWorkflowData 时,它会与从 A 收到的 previousWorkflowData 合并,然后将合并后的对象传递给 C。
实现示例
让我们考虑一个场景:用户登录后,立即被提示签署一条欢迎消息。
步骤 1:定义登录工作流
在你的登录会话的 onAuth 处理程序中,你将为签署消息生成一个新会话,并将其作为 nextWorkflow 返回。
login-handler.js
// 这是一个简化的示例。在实际应用中,你将有一个单独的端点来生成令牌。
const { WalletHandlers, WalletAuthenticator } = require('@arcblock/did-connect');
const get = require('lodash/get');
// 假设 authenticator 和 tokenStorage 已初始化
const authenticator = new WalletAuthenticator(/* ... */);
const tokenStorage = new MemoryAuthStorage();
const handlers = new WalletHandlers({ authenticator, tokenStorage });
// 第一步的处理程序:登录
handlers.attach({
app: server,
action: 'login',
claims: { profile: { description: '请提供你的个人资料' } },
onAuth: async ({ userDid, claims }) => {
const profile = claims.find(x => x.type === 'profile');
console.log(`名为 ${profile.fullName} 的 ${userDid} 已登录。`);
// 现在,为签署消息创建下一个工作流
// 在实际应用中,你会调用自己的令牌生成端点
const { data: nextSession } = await axios.get('https://yourapp.com/api/did/sign/token');
return {
// 下一个会话的 URL 和令牌
nextWorkflow: nextSession.url,
nextToken: nextSession.token,
// 将用户名传递给下一步
nextWorkflowData: {
fullName: profile.fullName,
},
};
},
});步骤 2:定义签名工作流
此工作流将从登录步骤接收用户名,并用它来自定义签名请求。
sign-handler.js
// 第二步的处理程序:签署消息
handlers.attach({
app: server,
action: 'sign',
claims: {
signature: ({ extraParams }) => {
// 从上一个工作流访问数据
const fullName = get(extraParams, 'previousWorkflowData.fullName', 'user');
return {
type: 'mime:text/plain',
description: `你好 ${fullName},请签署这条欢迎消息!`,
data: `欢迎加入,${fullName}!`,
};
},
},
onAuth: async ({ userDid }) => {
console.log(`${userDid} 签署了欢迎消息。`);
// 这是最后一步,所以我们不返回 nextWorkflow
return { successMessage: '入门流程完成!' };
},
});通过此设置,用户扫描一个二维码进行登录,批准后,其钱包中会立即显示个性化的签名请求。签名后,整个多步骤过程即告完成。
链接工作流是设计复杂且用户友好的交互的强大功能。你可以创建复杂的入门流程、多方协议或任何需要顺序、经过身份验证的步骤的流程。
接下来,了解另一个用于更复杂应用程序结构的高级功能。请参阅 Delegated Connect 指南。