Implement Delegated Connect
Delegated Connect allows one DID (an agent) to perform actions on behalf of another DID (a delegator). This is useful in scenarios where an application needs to act for a user or an organization, such as a SaaS platform operating for a tenant business. This guide shows how to establish a verifiable chain of trust from the delegator to the agent.
How It Works#
The core of the delegated flow is a delegation token. This is a JSON Web Token (JWT) signed by the Delegator (the one granting permission) that authorizes the Agent (the application's wallet) to act on its behalf. When the Agent makes a request, it presents this delegation token to the user's wallet, which can then verify the entire chain of authority.
Here is the sequence of events in a typical delegated connect flow:
Configuration#
To enable this flow, provide delegator and delegation information when creating your WalletAuthenticator instance. Both can be provided as functions to be resolved dynamically for each request.
Parameter | Type | Description |
|---|---|---|
|
| The wallet object for the delegating party. The |
|
| A JWT signed by the |
Example Implementation#
Here is how to configure the WalletAuthenticator and attach the handlers for a delegated connection.
const { fromRandom } = require('@ocap/wallet');
const { toDid } = require('@ocap/util');
const Jwt = require('@arcblock/jwt');
const { WalletAuthenticator, WalletHandlers } = require('@arcblock/did-connect');
// 1. Define the delegator (e.g., a business) and the agent (your app)
const delegator = fromRandom();
const agent = fromRandom({ role: 'application' }); // The application's wallet
// 2. Create the delegation JWT
// The delegator signs a token granting the agent specific permissions.
const delegationToken = Jwt.signV2(delegator.address, delegator.secretKey, {
agentDid: toDid(agent.address),
permissions: [
{
role: 'DIDConnectAgent',
claims: [
'authPrincipal',
'profile',
'signature',
'prepareTx',
'agreement',
'verifiableCredential',
'asset',
'keyPair',
'encryptionKey',
],
},
],
exp: Math.floor(new Date().getTime() / 1000) + 60 * 60, // Expires in 1 hour
});
// 3. Configure the WalletAuthenticator
const authenticator = new WalletAuthenticator({
wallet: agent, // The application wallet is the agent
appInfo: () => ({
name: 'DID Wallet Demo',
description: 'Demo application for delegated connect',
icon: 'https://arcblock.oss-cn-beijing.aliyuncs.com/images/wallet-round.png',
}),
delegator: () => delegator.toJSON(),
delegation: () => delegationToken,
});
// 4. Attach the handlers to your Express app
const handlers = new WalletHandlers({ authenticator });
handlers.attach({
app: server, // Your express app instance
action: 'delegated',
claims: {
profile: () => ({
fields: ['fullName', 'email'],
description: 'Requesting profile on behalf of the delegator',
}),
},
onAuth: ({ claims }) => {
console.log('Delegated auth successful!', claims);
// Handle successful authentication
},
});In this setup, when a user scans the QR code for the delegated action:
- The request sent to the wallet will be issued by the
delegator's DID. - It will be signed by the
agent's wallet. - The wallet will show that the
agentis acting on behalf of thedelegator. - The
appPkin the final signed response will be thedelegator's public key, while anagentPkfield will contain theagent's public key.
The Wallet Verification Process#
When a DID wallet receives a delegated request, it performs a multi-step verification to ensure the request is legitimate and transparent to the user.
This process ensures that the user can trust that the delegation is valid before approving any claims.
Now that you understand how to implement delegated connections, you can build more complex, multi-party applications. To learn more about the authenticator's configuration, see the WalletAuthenticator API Reference.