npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@painda/auth

v0.1.8

Published

PaindaProtocol authentication middleware and JWT validators

Readme

🐼 @painda/auth

Secure, token-based authentication middleware for PaindaProtocol.

@painda/auth provides a robust, customizable authentication layer for your real-time applications. It supports JWT, API keys, and custom validation logic with built-in protection against slow-loris auth attacks and unauthorized connections.

⚡ Highlights

  • Pluggable Validators: Use any async function to verify tokens (JWT, DB lookup, etc.).
  • Automatic Enforcement: Protects your server by enforcing auth before any message handling.
  • Timeout Protection: Automatically disconnects clients that fail to authenticate within a window.
  • Guest Support: Configurable "allow-guest" mode for public rooms.

Installation

npm install @painda/auth @painda/core

Authentication Flows

PaindaProtocol supports two authentication flows. Choose the one that fits your security requirements.

Flow 1: Query-Parameter Auth (Recommended for most use cases)

The client sends the token automatically as a ?token= query parameter on every (re)connection. This is handled by PPClient's getToken callback — no extra code needed on the client.

Client:

import { PPClient } from "@painda/client";

const client = new PPClient({
  url: "ws://localhost:3000",
  getToken: async () => {
    // Called on EVERY connect & reconnect — always a fresh token
    return await refreshJwtToken();
  },
});
// Token is automatically appended as ?token=<value> on the WS URL

Server (using server.use() middleware):

import { PPServer } from "@painda/core";

const server = new PPServer({ port: 3000 });

server.use(async (socket, next) => {
  // Token arrives as ?token= query parameter
  const url = new URL(`ws://x${socket.request.url}`);
  const token = url.searchParams.get("token");

  if (!token) return next(new Error("No token provided"));

  try {
    const user = await verifyJwt(token);
    socket.data.user = user; // Attach user to socket
    next();
  } catch {
    next(new Error("Invalid token"));
  }
});

server.on("connection", (client) => {
  console.log("Authenticated user:", client.data.user);
});

Note: With PaindaProtocol's core client (@painda/core/common/client), tokens are sent as the first binary frame after connect instead of URL query params. This avoids token leakage in proxy/server logs. The @painda/client browser package uses URL query params for compatibility.


Flow 2: Post-Connect Authentication (via @painda/auth)

For scenarios where the token should not appear in the URL (e.g., strict security policies, proxy logging concerns). The client sends an authenticate message after connecting.

Server:

import { PPServer } from "@painda/core";
import { PPAuthMiddleware } from "@painda/auth";

const server = new PPServer({ port: 3000 });

const auth = new PPAuthMiddleware(server, {
  validator: async (token) => {
    const user = await verifyJwt(token);
    if (!user) throw new Error("Invalid token");
    return user; // Attached to socket as `userContext`
  },
  authTimeout: 5000, // Client has 5s to authenticate
  allowGuest: false,
});

server.on("connection", (client) => {
  if (auth.isAuthenticated(client)) {
    const user = (client as any).userContext;
    console.log("Authenticated:", user.name);
  }
});

Client:

import { PPClient } from "@painda/client";

const client = new PPClient({ url: "ws://localhost:3000" });

// After connecting, send the authenticate message manually:
client.on("open", async () => {
  const token = await getStoredToken();
  client.emit("authenticate", { token });
});

// Listen for auth result:
client.on("auth-success", () => console.log("✅ Authenticated!"));
client.on("auth-error", (err) => console.error("❌ Auth failed:", err));

When to use which flow?

| Criterion | Flow 1: Query-Parameter | Flow 2: Post-Connect (@painda/auth) | |-----------|------------------------|--------------------------------------| | Simplicity | ✅ Automatic via getToken | 🔶 Manual authenticate message | | JWT Refresh | ✅ Auto-refreshed on every reconnect | 🔶 Must re-send manually | | Token Visibility | ⚠️ In URL (potential log/proxy exposure) | ✅ In message body only | | Recommended for | Standard apps, games, SPAs | High-security, banking, enterprise |


Options

| Option | Default | Description | |--------|---------|-------------| | validator | required | (token) => user \| boolean — validate token and return user object | | authTimeout | 5000 | Milliseconds before auto-disconnect for unauthenticated clients | | allowGuest | false | Allow connections without a token (sets userContext.guest = true) |

Post-Connect Auth Flow

  1. Client connects → auth timer starts (authTimeout ms)
  2. Client sends { type: "authenticate", payload: { token } }
  3. Validator runs → success: auth-success response / fail: disconnect with code 4002
  4. Timeout reached without auth → disconnect with code 4001

License

MIT License — free for private projects, open-source, and community use.

  • Enterprise (Paid): Commercial projects above a certain company size or revenue threshold require a commercial license. Inquiries via pp.painda.tools/enterprise.
  • Pro Plugins: Premium modules (Dashboard, Redis Adapter, Enterprise Support) available at pp.painda.tools/plugins.