Step-by-step Guide: Creating a PASETO (Platform-Agnostic Security Token) in Express.js

Published: (December 27, 2025 at 01:05 PM EST)
2 min read
Source: Dev.to

Source: Dev.to

Cover image for Step‑by‑step Guide: Creating a PASETO (Platform‑Agnostic Security Token) in Express.js

1. Install dependencies

Run this once:

npm install express paseto tweetnacl dotenv

2. Create a .env file

PORT=3000

3. Create an Express server with PASETO

Create a file named server.js:

import express from "express";
import { V2 } from "paseto";
import nacl from "tweetnacl";
import dotenv from "dotenv";

dotenv.config();

/**
 * Generate an Ed25519 key pair with tweetnacl
 */
console.log("🟡 Generating Ed25519 key pair (v2.public) ...");
const keyPair = nacl.sign.keyPair(); // Uint8Arrays
const privateKey = Buffer.from(keyPair.secretKey);
const publicKey = Buffer.from(keyPair.publicKey);
console.log("✅ Keys ready, starting Express...");

const app = express();
app.use(express.json());

// issue token
app.post("/token", async (req, res) => {
  try {
    const payload = {
      userId: req.body.userId,
      role: req.body.role,
      issuedAt: new Date().toISOString(),
    };

    const token = await V2.sign(payload, privateKey, {
      issuer: "my-app",
      audience: "users",
      expiresIn: "1h",
    });

    res.json({ token });
  } catch (err) {
    console.error("❌ Token generation failed:", err);
    res.status(500).json({ error: err.message });
  }
});

// verify token
app.post("/verify", async (req, res) => {
  try {
    const { token } = req.body;
    const payload = await V2.verify(token, publicKey, {
      issuer: "my-app",
      audience: "users",
    });
    res.json({ valid: true, payload });
  } catch (err) {
    console.error("❌ Verification failed:", err);
    res.status(401).json({ error: "Invalid or expired token" });
  }
});

const PORT = process.env.PORT || 3000;
app.listen(PORT, () => console.log(`🚀 Server running on http://localhost:${PORT}`));

4. Run the server

node server.js

You should see output similar to:

🟡 Generating Ed25519 key pair (v2.public) ...
✅ Keys ready, starting Express...
🚀 Server running on http://localhost:3000

5. Test the API

Generate a token

curl -X POST http://localhost:3000/token \
  -H "Content-Type: application/json" \
  -d '{"userId":123,"role":"admin"}'

Token generation response

Verify the token

Replace PASTE_YOUR_TOKEN_HERE with the token you received above.

curl -X POST http://localhost:3000/verify \
  -H "Content-Type: application/json" \
  -d '{"token":"PASTE_YOUR_TOKEN_HERE"}'

Token verification response

Tip: In production you should store the key pair securely instead of generating it on every startup. This demo setup is intended for learning how PASETO works.

Back to Blog

Related posts

Read more »