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
Also make sure you have ISSUER_URL
and ISSUER_SECRET
set in your .env
file as described in the Deploying the Issuer.
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.
Last updated