跳到主要内容

委托连接

委托连接是一项高级功能,通过允许应用程序使用临时的或较低权限的“Agent” DID 执行 DID Connect 操作,同时仍向最终用户展示其主要的、官方的 DID,从而增强了安全性。这意味着应用程序的主私钥永远不会暴露在处理日常交互的热钱包中。

本指南解释了委托连接的概念,并展示了如何使用 WalletAuthenticator 实现它。

工作原理

委托连接涉及三个关键参与者:

  • 委托人(Delegator):拥有应用程序身份的主 DID。这是用户将看到并信任的 DID。委托人的钱包持有主私钥,应将其保存在安全的冷存储中。
  • Agent:一个次要的、临时的 DID,被授权代表委托人执行特定的 DID Connect 操作。应用程序后端使用 Agent 的钱包来签署认证请求。
  • 委托证书(Delegation Certificate):由委托人签署的、格式为 JWT 的可验证凭证。该证书以密码学方式证明 Agent 有权代表委托人行事。它通常包括过期时间和允许的声明列表。

这个过程确保即使 Agent 的密钥被泄露,损害也会受到委托证书中定义的权限和过期日期的限制。委托人的主密钥仍然安全。

流程

下图展示了委托认证的流程:

Delegated Connect

  1. 委托

    委托人签署一个 JWT,授予 Agent 执行 DID Connect 操作的权限。

  2. 请求

    应用程序的 WalletAuthenticator 创建一个认证请求。它由 Agent 签署,但 iss(签发者)字段设置为委托人的 DID。该请求还包括委托证书。

  3. 验证

    用户的钱包接收到请求。它首先使用 Agent 的公钥验证消息签名。然后,它使用委托人的公钥验证包含的委托证书。这个两步过程确认了 Agent 的权限。

  4. 响应

    用户批准请求,该请求清楚地显示了委托人的身份,然后钱包将响应发送回应用程序。

实现

要实现委托连接,你需要为 WalletAuthenticator 配置委托人、Agent 钱包和委托证书。

步骤 1:定义委托人和 Agent

首先,你需要两个不同的钱包。一个将作为委托人(主身份),另一个作为 Agent(活跃的签名者)。

钱包设置

javascript
const { fromRandom } = require('@ocap/wallet');

// 你的应用程序的主要、可信身份
const delegator = fromRandom();

// 将处理日常操作的 Agent 钱包
const agent = fromRandom();

步骤 2:创建委托证书

该证书是一个由 delegator 签署的 JWT,授予 agent 权限。

创建委托 JWT

javascript
const Jwt = require('@arcblock/jwt');
const { toDid } = require('@ocap/util');

const createDelegation = () => {
  const now = Math.floor(Date.now() / 1000);
  const claims = [
    'authPrincipal',
    'profile',
    'signature',
    'prepareTx',
    'agreement',
    'verifiableCredential',
    'asset',
    'keyPair',
    'encryptionKey',
  ];

  const payload = {
    agentDid: toDid(agent.address),
    permissions: [{
      role: 'DIDConnectAgent',
      claims: claims,
    }],
    exp: now + 3600, // 1 小时后过期
    iat: now,
    nbf: now,
  };

  return Jwt.signV2(delegator.address, delegator.secretKey, payload);
};

const delegationCert = createDelegation();

步骤 3:配置 WalletAuthenticator

通过提供 delegator、delegation 证书和 wallet(即 Agent)来实例化 WalletAuthenticator。

认证器配置

javascript
const { WalletAuthenticator, WalletHandlers } = require('@arcblock/did-connect');
const MemoryAuthStorage = require('@arcblock/did-connect-storage-memory');

const authenticator = new WalletAuthenticator({
  // 'wallet' 属性是我们的 AGENT
  wallet: () => agent.toJSON(),

  // delegator 是主应用身份
  delegator: () => delegator.toJSON(),

  // 证明委托的 JWT
  delegation: () => delegationCert,

  appInfo: () => ({
    name: '委托连接演示',
    description: '委托认证演示',
    icon: 'https://arcblock.oss-cn-beijing.aliyuncs.com/images/wallet-round.png',
  }),
});

const handlers = new WalletHandlers({
  tokenStorage: new MemoryAuthStorage(),
  authenticator
});

// 附加到你的 Express 应用
handlers.attach({
  app: server, // 你的 express 应用实例
  action: 'delegatedLogin',
  claims: {
    profile: () => ({ fields: ['fullName'], description: '使用委托登录' }),
  },
  onAuth: (claims) => {
    console.log('用户已认证:', claims);
  },
});

当 DID Connect 会话开始时,WalletAuthenticator 将自动处理委托流程。二维码将包含用户钱包验证从委托人到 Agent 的信任链所需的信息。用户将看到来自你的应用程序主身份(委托人)的请求,从而提供无缝且安全的体验。

有关构造函数选项的更多详细信息,请参阅 WalletAuthenticator API 参考。