本示例提供了一个分步指南,介绍如何使用 DID Connect 实现一个基本的用户登录系统。其目标是使用用户的 DID 钱包对用户进行身份验证,并检索其姓名和电子邮件地址等基本个人资料信息。这是该库最常见的用例之一。
我们将使用 WalletHandlers 与 Express.js 服务器集成,并向用户请求一个 profile 声明。
工作原理
登录过程遵循标准的 DID Connect 工作流程:
初始化
后端使用应用程序的身份设置一个
WalletAuthenticator,并使用一个WalletHandlers实例来管理会话。附加处理程序
将一个特定的处理程序附加到 Express 路由(例如
/api/did/login)上。此处理程序定义了要请求的信息(声明)以及在成功验证后执行的逻辑(onAuth)。用户交互
前端显示一个 DID Connect 按钮或二维码,与后端启动会话。
钱包批准
用户使用其 DID 钱包扫描二维码,审查请求(分享其个人资料),并批准该请求。
后端回调
服务器上的
onAuth回调被触发,接收用户的 DID(userDid)及其个人资料数据。会话创建
应用程序现在可以使用这些信息来创建用户会话、颁发令牌或将用户的个人资料保存到数据库中。
实现
以下是如何构建一个简单的登录端点。
步骤 1:初始化 Authenticator 和 Handlers
首先,你需要使用你的应用程序详细信息来配置 WalletAuthenticator,并配置 WalletHandlers 来管理会话状态。
简单登录设置
const express = require('express');
const { fromRandom } = require('@ocap/wallet');
const { WalletAuthenticator, WalletHandlers } = require('@arcblock/did-connect-js');
const SimpleStorage = require('@arcblock/did-connect-storage-nedb');
// 1. 为应用程序创建一个钱包
const wallet = fromRandom();
// 2. 使用应用程序和链信息配置 authenticator
const authenticator = new WalletAuthenticator({
wallet,
baseUrl: 'http://localhost:3000', // 你的应用程序的基础 URL
appInfo: {
name: 'Simple Login Example',
description: '一个演示 DID Connect 登录的简单示例',
icon: '/images/logo.png', // 你的应用程序图标的 URL
},
chainInfo: {
host: 'https://beta.abtnetwork.io/api',
id: 'beta',
},
});
// 3. 使用 authenticator 和存储适配器初始化 handlers
const handlers = new WalletHandlers({
authenticator,
tokenStorage: new SimpleStorage({ dbPath: '/tmp/did_connect_login_example.db' }),
});
// 4. 创建一个 Express 应用程序
const app = express();
// 如果你的应用程序位于代理之后,这是动态推断 baseUrl 所必需的
app.set('trust proxy', true);WalletAuthenticator:此对象持有你的应用程序的身份(钱包)和元数据(appInfo、chainInfo),这些信息将显示在用户的钱包中。WalletHandlers:此类负责协调 DID Connect 会话。它需要一个authenticator和一个tokenStorage适配器来持久化会话状态。did-connect-storage-nedb是一个简单的基于文件的存储,适合用作示例。
步骤 2:附加登录处理程序
接下来,使用 handlers.attach() 方法创建 API 端点并为你的登录流程定义逻辑。此方法会自动为你创建诸如 /api/did/login/token 和 /api/did/login/status 之类的路由。
附加登录处理程序
handlers.attach(app, {
// DID Connect 端点的基本路径
// 例如,/api/did/login、/api/did/profile
action: 'login',
// 定义要从用户钱包请求的声明
claims: {
profile: () => ({
fields: ['fullName', 'email'],
description: '请提供你的姓名和电子邮件以进行登录。',
}),
},
// 成功验证后执行的回调函数
onAuth: async ({ userDid, claims }) => {
// userDid:已验证用户的 DID。
// claims:用户提交的声明数组。
try {
const profile = claims.find((x) => x.type === 'profile');
console.log('登录成功!', { userDid, profile });
// 在实际应用中,你通常会:
// 1. 使用 userDid 在数据库中查找或创建一个用户。
// 2. 存储个人资料信息。
// 3. 为用户创建一个会话或颁发一个 JWT。
} catch (err) {
console.error('onAuth 回调出错', err);
}
},
});
const PORT = 3000;
app.listen(PORT, () => {
console.log(`服务器正在 http://localhost:${PORT} 上运行`);
console.log(`DID Connect 登录端点已在 /api/did/login 准备就绪`);
});action: 'login':这将生成的端点的基本路径设置为/api/did/login。claims.profile:此对象指定我们正在请求一个profile声明。fields数组列出了我们需要的具体信息片段,而description会在用户的钱包中显示,以解释为什么需要这些信息。onAuth:这是最关键的部分。此函数仅在用户成功验证并批准请求后运行。它接收userDid和claims数据。在这里,我们只是简单地记录信息,但在实际应用中,这里就是你处理用户会话管理的地方。
运行此服务器后,你可以使用 DID Connect UX 库集成前端,将其指向 /api/did/login 端点以启动登录流程。
后续步骤
现在你已经有了一个基本的登录系统,可以探索更多高级功能: