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

@digibuffer/auth-core

v1.0.2

Published

Auth library for JWT tokens and API keys — DB-agnostic, Edge-compatible, works anywhere.

Readme

@digibuffer/auth-core

Auth library for JWT tokens and API keys. DB-agnostic, Edge-compatible, works in Node.js and Edge runtime (Next.js middleware, Cloudflare Workers).

Features

  • JWT — sign, verify, decode using jose (Edge-compatible)
  • API Keys — generate, hash (SHA-256), constant-time compare
  • Request helpers — extract Bearer token or X-API-Key from any Request
  • Next.js adapterwithAuth, withToken, createNextMiddleware
  • DB-agnostic — you provide getUser and getUserByApiKey callbacks
  • TypeScript — fully typed

Installation

npm install @digibuffer/auth-core

Setup

// lib/auth.ts
import { createAuth } from '@digibuffer/auth-core';

export const auth = createAuth({
  jwt: {
    secret: process.env.JWT_SECRET!,
    expiresIn: '7d',
    issuer: 'storagecone.com',    // optional — embed in token, verified on decode
    audience: 'app.storagecone.com', // optional
  },

  // Called when a valid JWT is found — load the user from your DB
  getUser: async (userId) => {
    return db.users.findUnique({ where: { id: userId } });
  },

  // Called when X-API-Key header is present — look up by hashed key
  getUserByApiKey: async (hashedKey) => {
    return db.apiKeys.findFirst({ where: { keyHash: hashedKey, active: true } });
  },
});

Both callbacks are optional. Omit getUser if you only need token payloads (no DB lookup). Omit getUserByApiKey if you don't use API keys.


JWT

Sign a token

const token = await auth.signToken({ sub: user.id, role: 'admin' });

Verify a token

const payload = await auth.verifyToken(token);
// → { sub: 'user-123', role: 'admin', iat: ..., exp: ... } or null

Decode without verifying

const payload = auth.decodeToken(token);
// No signature check — use only when you already trust the source

API Keys

Generate a key pair

const { key, hashedKey } = await auth.generateApiKey('sk');
// key      → 'sk_aBcDeFgH...'  show to user once, never store
// hashedKey → 'a3f5...'        store this in your DB
// Save to DB
await db.apiKeys.create({
  data: { keyHash: hashedKey, userId: user.id, name: 'My API Key' },
});

Hash a key manually

const hashedKey = await auth.hashApiKey(rawKey);

Custom prefixes

await auth.generateApiKey('sk');  // sk_...  (secret key)
await auth.generateApiKey('pk');  // pk_...  (public key)
await auth.generateApiKey('tok'); // tok_... (token)

Protecting Routes (Next.js App Router)

import { withAuth, withToken } from '@digibuffer/auth-core/adapters/next';
import { auth } from '@/lib/auth';

// Require a valid user (JWT + DB lookup via getUser)
export const GET = withAuth(auth, async (req, user) => {
  return Response.json({ files: await db.files.findMany({ where: { userId: user.id } }) });
});

// Require a valid token only (no DB lookup — faster)
export const GET = withToken(auth, async (req, payload) => {
  return Response.json({ userId: payload.sub, role: payload.role });
});

Both wrappers return 401 with { error, code } JSON automatically on failure.


Middleware (Next.js)

// middleware.ts
import { createNextMiddleware } from '@digibuffer/auth-core/adapters/next';
import { auth } from '@/lib/auth';

export const middleware = createNextMiddleware(auth, {
  publicPaths: ['/login', '/signup', '/api/webhooks', '/api/public'],
  redirectTo: '/login', // web pages redirect here; API routes get 401 JSON
});

export const config = {
  matcher: ['/((?!_next/static|_next/image|favicon.ico).*)'],
};

Unauthenticated requests to /api/* get { "error": "Unauthorized" } with status 401. All other routes redirect to /login?callbackUrl=<original-path>.


Manual auth context

For more control, use getAuthContext directly:

export async function GET(req: Request) {
  const ctx = await auth.getAuthContext(req);

  if (!ctx.user) {
    return Response.json({ error: 'Unauthorized' }, { status: 401 });
  }

  // ctx.user       → full user object (from getUser callback)
  // ctx.userId     → user ID (from JWT sub or API key lookup)
  // ctx.tokenPayload → full JWT payload (only when auth via JWT)

  return Response.json({ user: ctx.user });
}

Auth resolution order:

  1. Authorization: Bearer <token> header → verifies JWT → calls getUser
  2. X-API-Key: <key> header → hashes key → calls getUserByApiKey
  3. Returns {} if neither is valid (never throws)

For a hard require, use auth.requireUser(req) or auth.requireToken(req) — these throw AuthError on failure.


Cross-product SSO

Issue a token from one product and verify it in another using a shared secret and issuer/audience:

// storagecone.com — issue token on login
const token = await auth.signToken({
  sub: user.id,
  role: user.role,
  // JWT carries issuer: 'storagecone.com', audience: 'marketplace.storagecone.com'
});

// marketplace.storagecone.com — verify the same token
const marketplaceAuth = createAuth({
  jwt: {
    secret: process.env.SHARED_JWT_SECRET!,
    issuer: 'storagecone.com',
    audience: 'marketplace.storagecone.com',
  },
  getUser: async (id) => marketplaceDb.users.findUnique({ where: { id } }),
});

API Reference

createAuth(config)Auth

| Config field | Type | Description | |---|---|---| | jwt.secret | string | Signing secret — keep this in env vars | | jwt.expiresIn | string \| number | e.g. '7d', '1h', 3600. Default: '7d' | | jwt.issuer | string | Optional issuer claim | | jwt.audience | string \| string[] | Optional audience claim | | getUser | (id) => AuthUser \| null | DB callback for JWT auth | | getUserByApiKey | (hash) => AuthUser \| null | DB callback for API key auth |

Auth instance

| Method | Returns | Description | |---|---|---| | signToken(payload) | Promise<string> | Sign a JWT | | verifyToken(token) | Promise<TokenPayload \| null> | Verify a JWT | | decodeToken(token) | TokenPayload \| null | Decode without verifying | | generateApiKey(prefix?) | Promise<ApiKeyPair> | Generate { key, hashedKey } | | hashApiKey(key) | Promise<string> | SHA-256 hash a raw key | | getAuthContext(req) | Promise<AuthContext> | Resolve auth, never throws | | requireUser(req) | Promise<AuthUser> | Throws AuthError if no valid user | | requireToken(req) | Promise<TokenPayload> | Throws AuthError if no valid token | | extractBearerToken(req) | string \| null | Read Bearer token from headers/cookie | | extractApiKey(req) | string \| null | Read X-API-Key header |

AuthError

throw new AuthError('Forbidden', 'FORBIDDEN', 403);
// .message    → 'Forbidden'
// .code       → 'UNAUTHORIZED' | 'FORBIDDEN' | 'INVALID_TOKEN' | 'EXPIRED_TOKEN'
// .statusCode → 403

License

Proprietary — All rights reserved.