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

@0-auth/zero-auth-idp

v0.2.0

Published

Minimal self-hosted OAuth/OIDC authorization server with a backend-hosted UI

Readme

@0-auth/zero-auth-idp

[!NOTE] This is an OAuth 2.0 authorization server with an optional OpenID Connect extension. OAuth remains the default. Configure the optional oidc extension when clients need standardized sign-in and identity claims.

A small, self-hosted OAuth authorization server for Express applications. It provides a backend-hosted login and consent UI, Authorization Code + PKCE, and opaque access tokens without requiring a second server.

Install

npm install @0-auth/zero-auth-idp express

Quick start

The application owns users and verifies credentials. The package owns the OAuth flow and receives a small user object after successful authentication.

import express from "express";
import { createIdentityProvider } from "@0-auth/zero-auth-idp";

const idp = createIdentityProvider({
  issuer: "http://localhost:3000/auth",
  logoutRedirectUri: "http://localhost:4000/signed-out",
  clients: [
    {
      clientId: "demo-app",
      name: "Demo app",
      clientType: "public",
      redirectUris: ["http://localhost:4000/callback"],
      allowedScopes: ["profile", "projects:read"],
    },
  ],
  authenticateUser: async ({ email, password }) => {
    // Replace this with your application's user lookup and password check.
    if (email !== "[email protected]" || password !== "change-me") return null;
    return { id: "user-123", email };
  },
});

const app = express();
app.use("/auth", idp.router());

app.get("/api/projects", idp.authenticateBearer(["projects:read"]), (req, res) => {
  res.json({ userId: req.idpUser?.id, projects: [] });
});

app.listen(3000);

The hosted flow is:

/authorize -> /login -> /consent -> client callback
                         |
                         +-> /token (code + PKCE verifier)

The client must use response_type=code, code_challenge_method=S256, and a registered redirect URI. The authorization code is short-lived and single-use.

For a runnable MongoDB application with Docker Compose, hashed users, and a complete PKCE callback, see examples/express-idp.

Endpoints

When mounted at /auth:

| Endpoint | Purpose | | -------------------------------------------------- | ------------------------------------------ | | GET /auth/.well-known/oauth-authorization-server | OAuth metadata | | GET /auth/authorize | Start Authorization Code + PKCE | | GET/POST /auth/login | Hosted login UI | | GET/POST /auth/consent | Hosted consent UI | | POST /auth/token | Exchange a code for an access token | | POST /auth/introspect | Inspect a token with a confidential client | | POST /auth/revoke | Revoke an access token | | POST /auth/logout | End the browser session | | GET /auth/.well-known/openid-configuration | OIDC metadata when enabled | | GET /auth/.well-known/jwks.json | OIDC signing keys when enabled | | GET /auth/userinfo | OIDC user claims when enabled |

OIDC (opt-in)

Pass oidc to enable OpenID Connect discovery, signed ID tokens, JWKS, and /userinfo. Add openid to a client's allowed scopes; authorization requests using that scope must include a nonce.

const idp = createIdentityProvider({
  // ...OAuth configuration
  oidc: { signingKey: privateKey, keyId: "idp-key-2026-01" },
});

Production deployments must provide a stable RSA signingKey; development instances generate a temporary key. The ID token contains iss, sub, aud, iat, exp, auth_time, nonce, and available email or name claims.

Access tokens are opaque, short-lived Bearer tokens. Use the returned token with Authorization: Bearer <token> and protect resource routes with idp.authenticateBearer(). Routes that require missing scopes return 403 with a WWW-Authenticate challenge that identifies the required scope.

Pass onEvent to receive redacted login, denial, token, and logout events for audit logs or metrics. Event handlers are best effort; handler failures do not fail an authentication request, and raw passwords, codes, and tokens are never included.

When logoutRedirectUri is configured, a successful logout returns 303 to that fixed HTTP(S) URL. Without it, logout returns 204. The fixed server-side value prevents callers from turning logout into an open redirect.

Hosted UI

Pass ui.renderLogin, ui.renderConsent, or ui.renderError to replace a hosted page. Login renderers receive the client name and the previously entered email after a failed attempt; passwords are never returned. Import escapeHtml for every context value inserted into HTML. Same-origin stylesheets are allowed by the package's Content Security Policy.

import { createIdentityProvider, escapeHtml } from "@0-auth/zero-auth-idp";

const ui = {
  renderLogin: ({ action, transactionId, csrfToken, clientName, email = "", error }) => `
    <link rel="stylesheet" href="/auth.css">
    <h1>Continue to ${escapeHtml(clientName)}</h1>
    ${error ? `<p role="alert">${escapeHtml(error)}</p>` : ""}
    <form method="post" action="${escapeHtml(action)}">
      <input type="hidden" name="transaction" value="${escapeHtml(transactionId)}">
      <input type="hidden" name="csrf_token" value="${escapeHtml(csrfToken)}">
      <input type="email" name="email" value="${escapeHtml(email)}" required>
      <input type="password" name="password" required>
      <button>Continue</button>
    </form>`,
};

Storage

The default in-memory storage is useful for local development and tests. It is not durable and must not be used for a multi-instance deployment.

Implement OAuthStorage for a database or shared cache, then pass it as storage. The adapter must store hashes for session, authorization-code, and access-token values, and consumeAuthorizationCode must be atomic.

Security defaults

  • PKCE with S256 is mandatory.
  • Redirect URIs must match exactly and cannot contain fragments.
  • Issuers must be HTTP(S) URLs without credentials, queries, or fragments; redirect URIs reject credential-bearing and active-content schemes.
  • Authorization codes are short-lived and single-use.
  • Sessions and transactions are rejected by the provider when expired, even if a storage adapter returns stale records.
  • Sessions use HTTP-only cookies; HTTPS issuers and production environments use secure cookies by default.
  • Browser forms use CSRF tokens.
  • Logout requires a same-origin Origin, Referer, or browser fetch metadata.
  • Authorization responses include the server issuer (iss) and metadata advertises that support for mix-up protection.
  • OIDC is disabled unless explicitly configured; ID tokens are signed with RS256.
  • Hosted pages may load stylesheets from the issuer origin; scripts remain blocked.
  • HTML, token, and error responses use no-store and basic security headers.
  • Raw passwords, codes, sessions, and access tokens are never stored by the built-in storage.

Rate-limit authenticateUser, use HTTPS in production, and replace the memory storage before deploying more than one process.

Deliberate V1 limits

This package does not currently implement refresh tokens, registration, password reset, email verification, dynamic client registration, or a client-management UI. Add those only after the OAuth and OIDC flows are stable.

License

MIT