🛠️
Technical Documentation
  • Introduction
    • About Empeiria
  • Empe Blockchain
    • Overview
    • Chain Architecture
      • Auth
      • Authz
      • Bank
      • Distribution
      • Governance
      • Staking
      • IBC
      • DidDoc
      • Vesting
      • Minter
      • Stablefee
      • LinkedResources
  • EVDI
    • EVDI Architecture
    • Self-Sovereign Identity
      • Technical Foundations
      • Roles in the SSI framework
      • Protocols and Standards
  • User Guide
    • Empe DID Wallet
      • Intro
      • Download and first launch
      • Create or import did
      • Main screen overview
      • How to claim credential from issuer
      • How to use credential with verifier
      • Settings and other options
    • Keplr Wallet and Blockchain Operations
      • How to Connect Keplr Wallet
    • Ping Pub operation
    • Staking Tokens Guide
    • Voting on Governance Proposals Guide
    • Sending Tokens Guide
  • Developer Guide
    • Tutorial: Credential Issuance & Verification
      • Overview
      • Understanding Key Concepts
      • Project Setup
      • Deploying the Issuer
      • Uploading the Credential Schema
      • Issuing Credentials
      • Frontend for Credential Issuance
      • Testing Credential Issuance
      • Deploying the Verifier
      • Setting Up the Verification Flow
      • Creating a Verification Endpoint
      • Creating a Protected Dashboard
      • Testing the Verification Flow
      • Summary & Next Steps
    • One-click deployment
      • Introduction
      • Registration
      • Login
      • Creating an Issuer
      • Issuer Data Description
      • Creating a Verifier
      • Verifier Data Description
    • Issuer
      • Terminology and Concepts
      • DID Document Management
      • Schema Management
      • Issuing Credentials and Interacting With Wallets
      • Revocations
      • Security Considerations
      • Error Handling and Troubleshooting
      • Future Enhancements
      • References and Standards
      • FAQ
    • Verifier
      • Terminology and Concepts
      • Architecture Overview
      • Core Responsibilities
      • Query Language
      • Client Configuration
      • Frontend Integration
      • Revocations
      • Server-Side VP Queries
      • Security Considerations
      • Error Handling and Troubleshooting
      • Future Enhancements
      • References and Standards
      • FAQ
    • Wallet SDK (Coming soon)
    • Introduction to cosmwasm
  • Validator Guide
    • Important links
    • Validators Guide
      • New validator
      • Hardware requirements
      • Required software installation
      • Go installation
      • Install prebuild binary
      • Install binary from source code (option B)
      • Configure a node
      • Cosmovisor setup
      • Install wasmvm
      • Sync with state-sync
      • Full state sync from archive snapshot
      • Latest snapshot
      • Run a Validator
      • Migration to v0.2.2
      • Migration to v0.3.0
      • Migration to v0.4.0
    • FAQ
  • Airdrop
    • On-Chain Testnet Airdrop
    • Faucet Guide: How to Claim Testnet Tokens?
  • Appendix
    • Glossary
Powered by GitBook
On this page
  1. Developer Guide
  2. Tutorial: Credential Issuance & Verification

Issuing Credentials

What We Are Doing:

  • Setting up a minimal Express application in src/index.js that:

    • Loads environment variables (via dotenv).

    • Serves static files from a public/ directory.

    • Mounts our router (where the /kyc-credential route will live).

Why: Before we can implement any credential-related endpoints, we need a working Express server that can:

  • Host our frontend assets (HTML/CSS/JS) under public/.

  • Accept POST requests (JSON/form data) from the frontend.

  • Delegate route handling to src/issuer-routes.js.

  • Spin up on a known port so the frontend and wallet callbacks work correctly.

Steps: Create src/index.js with the following contents:

import express from "express";
import path from "path";
import {fileURLToPath} from "url";
import dotenv from "dotenv";
import issuerRouter from "./issuer-routes.js";
import jwt from "jsonwebtoken";

dotenv.config();

// Convert module URL to a __dirname-like value
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

// PORT and BASE_URL come from .env (fallback to 3000 if not set)
const PORT = process.env.PORT || 3000;
const BASE_URL = process.env.BASE_URL || `http://localhost:${PORT}`;

// Initialize Express app
const app = express();

// Serve any static assets (e.g., index.html, scripts, styles) from public/
app.use(express.static(path.join(__dirname, "../public")));

// Parse URL-encoded bodies (HTML form submissions)
app.use(express.urlencoded({extended: true}));

// Attach our router (defined in src/issuer-routes.js)
app.use("/issuer", express.json(), issuerRouter);

// Start the server
app.listen(PORT, () => {
  console.log(`Server is running on ${BASE_URL}`);
});

To .env file, add the following variables:

PORT=3000

BASE_URL=http://192.168.1.1:3000 # or your desired base URL it should match the URL of your server + the port. 
# It cannot be localhost because the Empe DID Wallet needs to access it from a mobile device

JWT_SECRET=`your-jwt-secret` # a secret key for signing JWTs, used later for authorization

Issuing Credentials

What We Are Doing:

  • Implementing a route (/kyc-credential) in our Express app that:

    • Takes user input (age, firstName, lastName).

    • Contacts the Issuer to create a credential issuance offering.

    • Returns the offering data, including a qr_code_url.

Why: This route enables users to input their info and receive a QR code. Scanning the QR code with the Empe DID Wallet allows them to claim the credential.

Steps: Update src/issuer-routes.js:

import {Router} from "express";
import fetch from "node-fetch";
import dotenv from "dotenv";

dotenv.config();

const router = Router();
const ISSUER_URL = process.env.ISSUER_URL;
const ISSUER_SECRET = process.env.ISSUER_SECRET;

router.post("/kyc-credential", async (req, res) => {
  try {
    const {age, firstName, lastName} = req.body;
    // Fetch issuer metadata to get offering_endpoint
    const metadataRes = await fetch(`${ISSUER_URL}/.well-known/openid-credential-issuer`);
    const metadata = await metadataRes.json();
    const offering_endpoint = metadata.offering_endpoint;
    // Request an issuance offering from the Issuer
    const offeringRes = await fetch(offering_endpoint, {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        "x-client-secret": ISSUER_SECRET,
      },
      body: JSON.stringify({
        credential_type: "KYC Verifiable Credential",
        credential_subject: {age: Number(age), firstName, lastName},
      }),
    });

    const offeringData = await offeringRes.json();
    res.status(200).json(offeringData);
  } catch (error) {
    console.error(error);
    res.status(500).json({error: "Internal server error"});
  }
});

export default router;

Run the server:

  node src/index.js

Next, we will create a simple frontend form to submit user data and display the QR code.

PreviousUploading the Credential SchemaNextFrontend for Credential Issuance

Last updated 5 days ago

Also make sure you have ISSUER_URL and ISSUER_SECRET set in your .env file as described in the .

Deploying the Issuer