PASETO in Node.js — paseto Quickstart
Quickstart for using the paseto npm package to issue and verify PASETO v4.public tokens in Node.js, including key handling and async API.
Detailed Explanation
Node.js has solid PASETO support via the paseto npm package by Filip Skokan (the same author as the popular jose JWT library). It supports v3 and v4, local and public.
Install:
npm install paseto
Generating a v4.public key pair:
import { V4 } from 'paseto'
const { publicKey, privateKey } = await V4.generateKey('public')
The keys are standard Node.js KeyObject instances — you can serialize them with .export({ format: 'pem', type: 'pkcs8' }) for storage.
Issuing a token:
import { V4 } from 'paseto'
const token = await V4.sign(
{
sub: 'user-12345',
aud: 'https://api.example.com'
},
privateKey,
{
issuer: 'https://auth.example.com',
expiresIn: '15 minutes'
}
)
// "v4.public.eyJzdWIiOi..."
The library handles ISO 8601 conversion, iat insertion, and exp calculation from a human-readable duration.
Verifying a token:
import { V4 } from 'paseto'
try {
const payload = await V4.verify(token, publicKey, {
issuer: 'https://auth.example.com',
audience: 'https://api.example.com'
})
console.log(payload.sub) // 'user-12345'
} catch (err) {
// Signature failure, expired token, wrong issuer, etc.
}
If verification fails for any reason — invalid signature, expired exp, iss mismatch, aud mismatch — the promise rejects. There's no API to "decode without verifying" by accident.
Footers:
Pass { footer: { kid: 'key-1' } } as an option to sign(), and the footer is included on the wire and bound into the signature. verify() returns the footer alongside the payload when you pass the complete: true option.
v4.local symmetric tokens:
Same API surface: V4.encrypt() / V4.decrypt() with a symmetric key from V4.generateKey('local'). The encrypted payload is opaque on the wire — only the holder of the symmetric key can read it.
Async-only:
The Node paseto package is async throughout. This is intentional — it lets the library use Node's native crypto primitives, which are non-blocking in modern Node versions.
Use Case
A Node.js auth service issues v4.public tokens with the paseto npm package, sets exp via expiresIn, and verifies tokens with audience and issuer pinning at every API endpoint.