Used to check for browser translation.
用于检测浏览器翻译。
ブラウザの翻訳を検出する
How-to Guides

Handle Multiple Workflows


For processes that require more than one step, such as logging in and then signing a contract, you can chain multiple authentication workflows together. The did-auth library facilitates this by allowing one completed workflow to trigger the next, seamlessly passing data between them.

This is managed by returning nextWorkflow, nextToken, and optionally nextWorkflowData from the onAuth callback upon the successful completion of a step.

Authentication Flow#

The following diagram illustrates the sequence of a two-step authentication process where Workflow A is followed by Workflow B.

WalletApp BackendApp FrontendWalletApp BackendApp FrontendGenerate tokenB and urlB for Workflow B.Frontend redirects or Wallet opens nextWorkflowRequest Auth URL (Workflow A)Return { tokenA, urlA }Open urlAScan QR, get Auth Claim (A)Return signed claimSubmit approved Claim (A)onAuth(A) logic runsReturn { nextWorkflow: urlB, nextToken: tokenB, ... }Poll status for tokenAReturn { status: "scanned", nextWorkflow: urlB }Scan QR, get Auth Claim (B)Access previousWorkflowData from AReturn signed claimSubmit approved Claim (B)onAuth(B) logic runsMark both tokenA and tokenB as "succeed"Return { status: "succeed" }Poll status for tokenBReturn { status: "succeed" }

How It Works#

The process relies on a few key properties that you return from your onAuth handler.

Property

Description

nextWorkflow

The full DID Connect URL for the next authentication step. The wallet will automatically proceed to this URL.

nextToken

The session token for the nextWorkflow. This is required to link the two sessions.

nextWorkflowData

An object containing any data you want to pass from the current workflow to the next one.

previousWorkflowData

This data is available in the extraParams of the subsequent workflow's callbacks (onConnect, onAuth, etc.) and contains the nextWorkflowData from the previous step.

When nextWorkflow is returned, the library links the current session to the next one. Upon completion of the final workflow in the chain, all preceding linked sessions are automatically marked as succeed.

Implementation Example#

To implement a multi-step workflow, you'll primarily use the onAuth callback to control the flow.

In this example, the first step authenticates the user (an authPrincipal claim), and the second step asks for their profile information.

// did-auth handler setup
handlers.attach({
app: server,
action: 'multi-step-demo',
claims: [
{ // This is the claim for the *second* step
profile: () => ({
fields: ['fullName', 'email'],
description: 'Step 2: Provide your profile',
}),
},
],
onAuth: async ({ claims, extraParams }) => {
// Check if we are in the first step (authPrincipal claim)
// The `previousWorkflowData` will be absent in the first step.
const isFirstStep = claims.length === 0;

if (isFirstStep) {
console.log('Step 1 (Login) complete. Starting Step 2 (Profile).');

// Generate a new token and URL for the next workflow step
// Note: This assumes you have an endpoint to generate a new session.
const { data: nextStepInfo } = await axios.get(`${server.url}/api/did/multi-step-demo/token`);

return {
nextWorkflow: nextStepInfo.url, // URL for the wallet to continue
nextToken: nextStepInfo.token, // Session token for the next step
nextWorkflowData: { step: 1, message: 'Login successful!' }, // Data to pass
};
}

// This is the second step, because previousWorkflowData exists
console.log('Step 2 (Profile) complete.');
console.log('Data from Step 1:', extraParams.previousWorkflowData);
// Expected output: { step: 1, message: 'Login successful!' }

const profile = claims.find((x) => x.type === 'profile');
console.log('User profile:', profile);

return { successMessage: 'Multi-step process finished!' };
},
});

Data Flow Between Steps#

  1. After the user completes the first authentication step, your onAuth handler returns the nextWorkflow details. The library serializes nextWorkflowData into the nextWorkflow URL that is sent to the wallet.
    Response to Wallet (after step 1):{
    "status": "ok",
    "response": {
    "nextToken": "f2c4e1a3",
    "nextWorkflowData": {
    "step": 1,
    "message": "Login successful!"
    }
    },
    "nextWorkflow": "https://abtwallet.io/i/?url=https%3A%2F%2Fexample.com%2Fapi%2Fdid%2Fmulti-step-demo%2Fauth%3F_t_%3Df2c4e1a3%26previousWorkflowData%3DeyJzdGVwIjoxLCJtZXNzYWdlIjoiTG9naW4gc3VjY2Vzc2Z1bCEifQ"
    }

  2. The wallet proceeds to the nextWorkflow URL. When the user approves the second claim, your onAuth handler is called again. This time, the extraParams object contains the previousWorkflowData from the first step.
    extraParams in onAuth (during step 2):{
    // ... other params
    previousWorkflowData: {
    step: 1,
    message: 'Login successful!'
    }
    }

Chaining More Than Two Workflows#

The library automatically merges workflow data. If you chain three workflows (A → B → C):

  • Workflow A passes nextWorkflowData to B.
  • When B completes, it can return its own nextWorkflowData. The library merges this new data with the data received from A.
  • The combined data object is passed to workflow C as previousWorkflowData.


By returning nextWorkflow from your onAuth handler, you can create sophisticated, multi-step user experiences. This is ideal for scenarios like progressive onboarding or multi-part transactions.

To see how this can be applied, continue to the Request a Signature guide to learn how to ask for a signature after a user has logged in.