在您如 請求聲明 指南中所示定義了 DID Connect 會話的聲明後,下一個關鍵步驟是處理來自使用者 DID 錢包的回應。@arcblock/did-connect-js 函式庫提供了一套全面的生命週期回呼,以管理會話的每種可能結果,無論是使用者批准、拒絕,還是會話逾時。
這些回呼作為函數傳遞給 handlers.attach() 方法,並為您提供特定的掛鉤,以便在驗證過程中執行您的業務邏輯。
DID Connect 生命週期
一個典型的 DID Connect 會話遵循一個清晰的事件序列。下圖說明了此流程,並指出了每個主要生命週期回呼的觸發時機。

生命週期回呼
以下是可用於處理整個 DID Connect 會話生命週期的回呼的詳細說明。
| 回呼 | 觸發時機... | 常見使用案例 |
|---|---|---|
onStart | 新會話啟動且 QR code 準備就緒時。 | 記錄會話啟動、準備會話特定資源。 |
onConnect | 使用者的錢包掃描 QR code 並建立連線時,但在聲明被批准之前。 | 基於 userDid 進行權限檢查、生成動態聲明。 |
onDecline | 使用者在其錢包中明確拒絕請求時。 | 顯示取消訊息、記錄拒絕操作。 |
onAuth | (必要) 使用者批准請求並提交所請求的聲明時。 | 核心業務邏輯: 驗證聲明、建立使用者會話、更新資料庫。 |
onComplete | 整個 DID Connect 會話結束時,無論成功或失敗。 | 最後的清理工作、移除臨時會話資料。 |
onExpire | 在使用者完成操作前會話逾時。 | 通知使用者 QR code 已過期、清理過時的會話。 |
onError | 會話期間發生意外錯誤時。 | 錯誤記錄與報告。 |
onConnect:預先批准邏輯與動態聲明
onConnect 回呼特別強大,因為它允許您在知道使用者 DID 但在他們看到完整的聲明列表之前執行邏輯。這是根據使用者身份執行權限檢查或動態生成聲明的理想位置。
參數: { req, challenge, userDid, userPk, extraParams, updateSession }
範例:使用 onConnect 生成動態聲明
handlers.attach({
action: 'dynamic-claims',
// 此函數可以是異步的
onConnect: ({ userDid }) => {
// 您可以根據允許列表檢查使用者的 DID
if (!isUserAllowed(userDid)) {
throw new Error('您無權存取此服務。');
}
// 或根據使用者屬性返回一組動態聲明
return {
profile: () => ({
fields: ['fullName', 'email'],
description: '請提供您的姓名和電子郵件以繼續',
}),
};
},
onAuth: async ({ claims, userDid }) => {
// `claims` 現在包含動態生成的個人資料聲明的結果
console.log('動態聲明已由以下使用者批准:', userDid, claims);
},
});onAuth:處理成功驗證
onAuth 回呼是您 DID Connect 整合的核心。它是唯一必要的回呼,當使用者在錢包中成功批准請求時執行。它接收使用者提交的聲明資料,您可以使用這些資料來完成應用程式的邏輯,例如登入使用者或驗證資產所有權。
參數: { req, challenge, claims, userDid, userPk, extraParams, updateSession }
範例:在 onAuth 中處理提交的聲明
handlers.attach({
action: 'profile-login',
claims: {
profile: () => ({
fields: ['fullName', 'email'],
description: '請提供您的姓名和電子郵件以登入。',
}),
},
onAuth: async ({ userDid, claims }) => {
try {
const profileClaim = claims.find((c) => c.type === 'profile');
if (profileClaim) {
console.log(`為 ${userDid} 登入成功`);
console.log('使用者個人資料:', profileClaim.value);
// 在這裡,您通常會建立使用者會話、儲存到資料庫等。
const user = await findOrCreateUser(userDid, profileClaim.value);
}
} catch (err) {
console.error('登入過程中發生錯誤:', err);
}
},
});onDecline:處理使用者取消操作
如果使用者決定在其錢包中取消請求,則會觸發 onDecline 回呼。這使您能夠優雅地處理取消操作,例如,在前端通知使用者登入嘗試已取消。
參數: { req, challenge, userDid, userPk, extraParams, updateSession }
範例:處理被拒絕的請求
handlers.attach({
action: 'profile-login',
claims: { /* ... */ },
onAuth: async ({ userDid, claims }) => { /* ... */ },
onDecline: ({ userDid }) => {
console.log(`使用者 ${userDid} 拒絕了連線請求。`);
// 您可以更新會話以通知前端
},
});使用 updateSession 持久化資料
包括 onAuth、onConnect 和 onStart 在內的多個回呼,都會收到一個 updateSession 函數作為參數。這個工具對於將資訊從您的後端邏輯傳遞回會話狀態至關重要,然後您的前端應用程式可以輪詢並檢索這些狀態。
例如,在 onAuth 中成功登入後,您可以生成一個應用程式特定的 JWT 並將其儲存到會話中。您的前端隨後可以檢索此權杖以驗證後續的 API 請求。
- 要持久化普通的、非敏感的資訊:
await updateSession({ key: 'value' }); - 要持久化敏感資訊(將被加密):
await updateSession({ key: 'sensitive-value' }, true);
範例:使用 updateSession 將權杖傳遞給前端
handlers.attach({
action: 'profile-login',
claims: { /* ... */ },
onAuth: async ({ userDid, claims, updateSession }) => {
const user = await findOrCreateUser(userDid, claims);
const appToken = generateAppToken(user);
// 持久化一個非敏感的會話 ID
await updateSession({ sessionId: 'some-session-id' });
// 持久化一個敏感的 JWT,它將在會話儲存中被加密
await updateSession({ token: appToken }, true);
console.log(`已為使用者 ${userDid} 更新會話`);
},
});透過有效使用這些生命週期回呼,您可以建構穩健且使用者友善的驗證流程。現在您已了解如何處理單一會話的回應,您可以開始探索更複雜的使用者旅程。
接下來,請在 鏈接工作流程 指南中學習如何透過將多個 DID Connect 會話連結在一起來建立多步驟互動。