WalletHandlers
The WalletHandlers class is the core component for integrating DID authentication into an Express.js application. It provides a set of handlers that manage the entire authentication lifecycle, from generating a session and presenting a QR code to processing claims from the user's wallet.
This class extends BaseHandler and works in tandem with an instance of WalletAuthenticator to create and verify the cryptographic messages that underpin the protocol. For details on how to configure the signing and verification component, see the WalletAuthenticator API Reference.
Authentication Flow#
The WalletHandlers.attach() method sets up several endpoints on your server. The following diagram illustrates how a web application, your server (backend), and a DID Wallet interact during a typical authentication flow.
Class: WalletHandlers#
Extends EventEmitter to provide hooks into the authentication lifecycle.
new WalletHandlers(config)#
Creates an instance of the DID Auth handlers. This instance orchestrates the authentication process by managing session state and handling communication with the wallet.
Parameters
Name | Type | Description |
|---|---|---|
|
| The configuration object. |
|
| A storage instance for managing session tokens. Must conform to the expected storage interface. |
|
| An instance of |
|
| (Optional) A function to transform the callback URL pathname. Defaults to an identity function. |
|
| (Optional) A global callback invoked when the wallet connects. It can be used for permission checks before proceeding. Throwing an error will halt the process. |
|
| (Optional) Custom options to configure the handlers. |
|
| (Optional) URL prefix for the endpoints. Defaults to |
|
| (Optional) How long (in milliseconds) to wait before cleaning up a completed session. Defaults to |
|
| (Optional) The query parameter key for the session token. Defaults to |
|
| (Optional) The query parameter key for the wallet's public encryption key. Defaults to |
|
| (Optional) The query parameter key for the wallet protocol version. Defaults to |
Example
const { WalletHandlers } = require('@arcblock/did-auth');
const Authenticator = require('./path/to/authenticator-instance'); // Your configured WalletAuthenticator
const TokenStorage = require('./path/to/token-storage-instance'); // Your token storage
const handlers = new WalletHandlers({
authenticator: Authenticator,
tokenStorage: TokenStorage,
});attach(config)#
Attaches the DID authentication routes to an Express app instance for a specific action (e.g., 'login', 'claim'). This is the main method for making the authentication flow operational.
It registers the following routes under /{prefix}/{action}:
GET /token: Creates a new session token and auth URL.GET /status: Checks the current status of a session token.GET /timeout: Manually expires a session token.GET /auth: Called by the wallet to fetch the authentication request (claims).POST /auth: Called by the wallet to submit the signed authentication response.
Parameters
Name | Type | Default | Description |
|---|---|---|---|
|
| The Express app instance. | |
|
| A unique name for this group of routes (e.g., 'login'). | |
|
|
| (Optional) An array of claims to request from the user. |
|
|
| (Optional) Callback executed when a new session starts (token is generated). |
|
|
| (Optional) Action-specific callback when a wallet connects. Can return dynamic claims. |
|
| Required | Callback executed on each successful authentication step from the wallet. |
|
|
| (Optional) Callback executed when the user declines the request in their wallet. |
|
|
| (Optional) Callback executed when the entire authentication flow is successfully completed. |
|
|
| (Optional) Callback executed when a session token expires. |
|
|
| (Optional) Callback for handling errors during the process. |
|
|
| (Optional) Specifies if an |
|
|
| (Optional) If |
Example: Attaching a Login Handler
const express = require('express');
// Assuming 'handlers' is an initialized WalletHandlers instance
const app = express();
const onAuthSuccess = async ({ userDid, userPk, claims }) => {
console.log('User authenticated:', { userDid, userPk });
// Find or create user in your database
// The final result object can be returned to the wallet.
return { successMessage: 'Login successful!' };
};
handlers.attach({
app,
action: 'login',
claims: [
{ type: 'profile', fields: ['fullName', 'email'], description: 'Please provide your profile for registration' },
{ type: 'signature', description: 'Please sign this message to confirm your identity' }
],
onAuth: onAuthSuccess,
onComplete: ({ userDid }) => {
console.log(`Session for ${userDid} is complete and will be cleaned up.`);
}
});
app.listen(3000, () => {
console.log('DID Auth server running on http://localhost:3000');
});Events#
WalletHandlers inherits from EventEmitter and emits events based on the underlying token storage operations. You can listen to these events to monitor session activity.
created: Emitted when a new session token is created.- Payload:
{ token, ... }- The initial data of the created session.
- Payload:
updated: Emitted whenever a session's data is updated (e.g., status change fromcreatedtoscanned).- Payload: An object containing the updated fields of the session, excluding internal protected keys.
deleted: Emitted when a session token is destroyed (e.g., after completion or timeout).- Payload:
{ token }- The token of the deleted session.
- Payload:
Example: Listening to Events
// Assuming 'handlers' is an initialized WalletHandlers instance
handlers.on('updated', (sessionData) => {
if (sessionData.status === 'scanned') {
console.log(`Token ${sessionData.token} was scanned by wallet.`);
}
if (sessionData.status === 'succeed') {
console.log(`Authentication for token ${sessionData.token} succeeded.`);
}
});
handlers.on('deleted', ({ token }) => {
console.log(`Session for token ${token} was deleted.`);
});Now that you understand how to configure WalletHandlers, see a practical example in the Set up with Express.js guide or dive into the data structures in the Schemas reference.