Setting Up the Verification Flow

What We Are Doing:

  • Configuring the Verifier in our Express app.

  • Defining a verification flow named "kyc" that checks:

    • The credential type is "KYC Verifiable Credential".

    • The subject`s age is at least 18.

Why: We want only users who hold a valid KYC credential proving they are over 18 to access a protected resource.

Steps: In src/index.js, after app.use("/issuer", express.json(), issuerRouter); and before app.listen(PORT... add the following code to set up the Verifier client and define the verification flow:

Verification flow configuration is done using the VerifierClient from the @empe/verifier-client package. This allows us to define how the verification should be performed and what conditions must be met for a credential to be considered valid.

import verifierRouter from "./verifier-routes.js";
import authorizationRouter from "./authorization-routes.js";
import {VerifiablePresentation} from '@empe/identity';
import {VerifierClient} from "@empe/verifier-client";
import jwt from 'jsonwebtoken';

const VERIFIER_SERVICE_URL = process.env.VERIFIER_SERVICE_URL;    // URL of the Verifier service
const VERIFIER_CLIENT_SECRET = process.env.VERIFIER_CLIENT_SECRET; // Secret to authenticate with Verifier
const JWT_SECRET = process.env.JWT_SECRET; // Secret key used to sign our own JWTs

app.use("/verifier", express.json(), verifierRouter);
app.use("/authorization", express.json(), authorizationRouter); // Authorization routes for handling access tokens and protected resources we will create this later.

const verifierConfiguration = {
  baseUrl: BASE_URL,                     // Our app’s public URL, used for callback links
  verifierServiceUrl: VERIFIER_SERVICE_URL,
  clientSecret: VERIFIER_CLIENT_SECRET,
  verificationFlows: [
    {
      name: "kyc",                       // Identifier for this verification flow
      vpQuery: [                         // Requirements for the incoming Verifiable Presentation (VP)
        {
          fields: [
            {
              path: ["$.type"],          // Inspect the top-level "type" array in the VP
              filter: {
                type: "array",
                contains: {const: "KYC Verifiable Credential"} // Must include this credential type
              }
            },
            {
              path: ["$.credentialSubject.age"], // Inspect the age field in credentialSubject
              filter: {
                type: "number",
                minimum: 18                 // Age must be at least 18
              }
            }
          ]
        }
      ],
      handleVerificationResult: async (data) => {
        // Called after the Verifier service finishes checking the VP
        if (data.verification_status === 'verified') {
          const {vp} = data;
          // Reconstruct the VerifiablePresentation object to read its contents
          const vpJSON = VerifiablePresentation.fromJSON(vp);
          // Extract the holder's DID (the wallet that presented the VP)
          const holder = vpJSON.holder().toString();

          // Create a JWT containing the holder DID and the VP payload
          // This token can be used by our frontend to grant access to protected routes
          const accessToken = jwt.sign({sub: holder, vp: data.vp}, JWT_SECRET);
          return {
            access_token: accessToken,
            verification_status: data.verification_status,
            redirect_url: "/authorization/dashboard"   // After successful verification, redirect here
          };
        }
        // If not verified, return the raw result (e.g., pending or failed)
        return data;
      }
    }
  ]
};

// Instantiate the VerifierClient with our Express app and configuration
const verifierClient = new VerifierClient(app, verifierConfiguration);
// Initialize the client, which registers all necessary verification endpoints under the hood
verifierClient.initialize();

Now our app can request a verification QR code and handle verification results.

Last updated