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

unauth

v0.0.5

Published

Low-level OIDC utilities

Readme

unauth

npm version npm downloads bundle size

A collection of low-level, and high-level server-agnostic, OAuth 2.1 and OpenID Connect utilities based on JWT (unjwt). Adapters for popular frameworks are available.

[!WARNING] This package is in active development. It is not recommended for production use yet unless you are willing to help with testing and feedback. Expect breaking changes, as I prioritize usability and correctness over stability at this stage.

Usage

Install the package:

# ✨ Auto-detect (supports npm, yarn, pnpm, deno and bun)
npx nypm install unauth

Import:

ESM (Node.js, Bun, Deno)

// Main functions
import { OAuthProvider } from "unauth/oauth";
import { OIDCProvider } from "unauth/oidc";

CDN (Deno, Bun and Browsers)

// Main functions
import { OAuthProvider } from "https://esm.sh/unauth/oauth";
import { OIDCProvider } from "https://esm.sh/unauth/oidc";

Quick start (OIDC)

import { OIDCProvider } from "unauth/oidc";
import { generateJWK } from "unauth/utils";

// Configure the provider once during startup.
const [atJwk, idJwk] = await Promise.all([
  generateJWK("RS256", { kid: "at-rsa-1" }),
  generateJWK("RS256", { kid: "id-rsa-1" }),
]);
const oidc = useOIDCProvider({
  issuer: "https://auth.example.com",
  authorizationCodeOptions: {
    privateKey: "ac-secret",
  },
  refreshTokenOptions: {
    privateKey: "rt-secret",
  },
  accessTokenOptions: atJwk,
  idTokenOptions: idJwk,
});

// In your authorize endpoint
const authorize = oidc.validateAuthorizeRequest(req.query);
if (!authorize.success) {
  return redirectWithError(authorize.error);
}

const code = await oidc.issueAuthorizationCode({
  ...authorize.value,
  subject: "user-123",
  redirect_uri: authorize.value.redirect_uri ?? DEFAULT_REDIRECT_URI,
});

// In your token endpoint
const normalized = oidc.validateTokenRequest(req.body);
if (!normalized.success) {
  return sendError(normalized.error);
}

const grant = await oauth.issueTokenGrant(validation.value);
if (!grant.success) {
  return sendError(grant.error);
}

const idToken = await oidc.introspectIdToken(grant.value.id_token);

Quick start (OAuth only)

import { OAuthProvider } from "unauth/oauth";
import { generateJWK } from "unauth/utils";

// Configure the provider once during startup.
const atJwk = await generateJWK("RS256", { kid: "at-rsa-1" });
const oauth = useOAuthProvider({
  issuer: "https://auth.example.com",
  authorizationCodeOptions: {
    privateKey: "ac-secret",
  },
  refreshTokenOptions: {
    privateKey: "rt-secret",
  },
  accessTokenOptions: atJwk,
});

const validation = oauth.validateTokenRequest(req.body);
if (!validation.success) {
  return sendError(validation.error);
}

const grant = await oauth.issueTokenGrant(validation.value);
if (!grant.success) {
  return sendError(grant.error);
}

// Later, verify tokens issued by the provider
const accessClaims = await oauth.introspectAccessToken(
  grant.value.access_token,
);

[!NOTE] For advanced use-cases you can import the lower-level helpers directly, e.g. import { issueAuthorizationCode } from "unauth/oauth" or import { buildUserInfo } from "unauth/oidc", to compose custom flows while keeping the same core primitives.

Adapters

  • H3 v1: For use with H3 v1

Minimal H3 v1 Example

In the following example instead of using useOIDCProvider or useOAuthProvider, we use createOIDCRouter (or createOAuthRouter) which creates an H3 router with all the necessary endpoints that can be mounted as a sub-app. We also provide an authorize hook to validate the client and redirect URI.

import {
  createApp,
  createRouter,
  defineEventHandler,
  getQuery,
  useBase,
} from "h3";
import { createOIDCRouter, validateRedirectUri } from "unauth/h3/oidc";
import { generateJWK } from "unauth";

const [atJwk, idJwk] = await Promise.all([
  generateJWK("RS256", { kid: "at-rsa-1" }),
  generateJWK("RS256", { kid: "id-rsa-1" }),
]);

// If the first argument is a string, it will return a handler with a base
const oidcRouter = createOIDCRouter({
  issuer: "http://localhost:3000",
  discovery: {
    // the base path where the OIDC endpoints will be served
    // (e.g. /oidc/v1/.well-known/openid-configuration)
    base: "/oidc/v1",
    // you can also override individual endpoints here, e.g.:
    // authorization_endpoint: "/oidc/v1/authorize",
  },

  authorizationCodeOptions: {
    privateKey: "ac-secret",
  },
  refreshTokenOptions: {
    privateKey: "rt-secret",
  },
  accessTokenOptions: atJwk, // we can directly pass keys and use default options
  idTokenOptions: idJwk, // same as accessTokenOptions

  // Hook that is called when the /authorize endpoint is hit
  authorize: async (input) => {
    // in a real app, you'd look up the client_id and allowed redirect URIs in your database
    if (input.client_id !== "test-client") {
      return {
        error: "invalid_client",
        error_description: "Unknown client",
      };
    }
    const validRedirectUri = validateRedirectUri(input.redirect_uri, [
      "http://localhost:3000/callback", // this is the one requested
      "http://localhost:3000/alt-callback",
    ]);
    if (!validRedirectUri.success) {
      return validRedirectUri.error;
    }

    // in a real app, you'd determine this from the user's login session
    const subject = "user-123";

    return {
      subject,
      redirect_uri: validRedirectUri.value,
    };
  },
});

// Create an H3 app instance
export const app = createApp();
const router = createRouter();

// Simple callback endpoint for manual testing; used by the scripted test (which intercepts the Location header)
router.get(
  "/callback",
  defineEventHandler((event) => {
    const q = getQuery<{ code?: string; state?: string }>(event);
    return `Callback received. code=${q.code ?? "<none>"} state=${q.state ?? "<none>"}`;
  }),
);

// Use the same base as used in `createOIDCRouter`
router.use("/oidc/v1/**", useBase("/oidc/v1", oidcRouter.handler));

app.use(router);

Development

  • Clone this repository
  • Install latest LTS version of Node.js
  • Enable Corepack using corepack enable
  • Install dependencies using pnpm install
  • Run interactive tests using pnpm dev

Credits

License

Published under the MIT license. Made by community 💛


🤖 auto updated with automd