DEV Community

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

Posted on • Edited on

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

The legacy library can’t generate keys itself, but it can import an Ed25519 key.
We’ll generate the key pair once (with tweetnacl, a crypto library) and feed it into paseto.

1. Install dependencies

Run this once:

npm install express paseto tweetnacl dotenv
Enter fullscreen mode Exit fullscreen mode

2. Create a .env file

PORT=3000
Enter fullscreen mode Exit fullscreen mode

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}`));
Enter fullscreen mode Exit fullscreen mode

4. Run it

node server.js
Enter fullscreen mode Exit fullscreen mode

You should now see:

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

5. Test the API

You can test using Insomnia or curl:

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

  • Verify token:
curl -X POST http://localhost:3000/verify \
-H "Content-Type: application/json" \
-d '{"token":"PASTE_YOUR_TOKEN_HERE"}'
Enter fullscreen mode Exit fullscreen mode


Tip: In production, you’d typically store the key pair securely (not generate it every startup). But for demo purposes, this setup is perfect for learning how PASETO works.

Github:

Reference: https://paseto.io/

Top comments (0)