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

@opendatalabs/service-auth

v1.26.0

Published

OAuth private_key_jwt service-to-service auth helper (RFC 7521/7523/9068) for Vana.

Readme

@opendatalabs/service-auth

OAuth 2.0 service-to-service authentication helper built around the private_key_jwt client authentication method. A caller signs a JWT assertion (RFC 7521 / 7523), exchanges it at the OAuth token endpoint (Hydra in Vana's deployment) for an RFC 9068 JWT access token, and forwards that token as Authorization: Bearer <jwt> to the resource server. The resource server verifies the JWT locally against the issuer's JWKS, with no back-channel introspect on the hot path.

The package wraps jose and ships three subpaths consumers care about (./client, ./jwks, ./resource-server) plus a ./testkit for verifying integrations.

Install

npm install @opendatalabs/service-auth jose

Caller (./client)

import { createServiceAuthClient } from "@opendatalabs/service-auth/client";

const auth = createServiceAuthClient({
  clientId: process.env.SERVICE_CLIENT_ID!,
  privateKeyJwk: JSON.parse(process.env.SERVICE_PRIVATE_JWK!),
  tokenEndpoint: process.env.OAUTH_TOKEN_ENDPOINT!,
});

const { token } = await auth.getServiceToken({
  audience: "vana-account-introspect",
});

await fetch("https://account.vana.org/api/oauth/introspect", {
  method: "POST",
  headers: {
    authorization: `Bearer ${token}`,
    "content-type": "application/json",
  },
  body: JSON.stringify({ token: someUserToken }),
});

Tokens are cached in-process by (audience, scope) until 30s before expiry. No on-disk cache, no shared cache, no refresh-token flow. A cold start re-fetches.

Publishing JWKS (./jwks)

// app/.well-known/jwks.json/route.ts
import { createJwksHandler } from "@opendatalabs/service-auth/jwks";

const handler = createJwksHandler({
  keys: [
    JSON.parse(process.env.SERVICE_PUBLIC_JWK_CURRENT!),
    // During rotation, include the previous public key too:
    JSON.parse(process.env.SERVICE_PUBLIC_JWK_PREVIOUS ?? "null"),
  ].filter(Boolean),
});

export function GET(request: Request) {
  return handler(request);
}

The helper strips all private fields. If you accidentally pass a private JWK, the response still only exposes the public half.

Resource server (./resource-server)

import { createServiceAuthValidator } from "@opendatalabs/service-auth/resource-server";

const validator = createServiceAuthValidator({
  jwksUri: `${process.env.OAUTH_PUBLIC_URL}/.well-known/jwks.json`,
  issuer: process.env.OAUTH_ISSUER!,
  audience: "vana-account-introspect",
});

export async function POST(request: Request) {
  const auth = await validator.requireJwt()(request);
  if (!auth.ok) return auth.response;
  // auth.result.clientId is the verified caller.
  // ...do your work.
}

Rejection shapes:

  • 401 with WWW-Authenticate: Bearer error="invalid_token" for expired / wrong-iss / wrong-aud / bad-signature / not-a-bearer.
  • 403 with WWW-Authenticate: Bearer error="insufficient_scope" when requiredScopes is not satisfied.

Testing (./testkit)

import { createFixtures } from "@opendatalabs/service-auth/testkit";
import { createServiceAuthValidator } from "@opendatalabs/service-auth/resource-server";

const f = await createFixtures({ audience: "my-resource" });
const validator = createServiceAuthValidator({
  issuer: f.issuer.issuer,
  audience: "my-resource",
  jwks: f.issuer.jwks,
});

About this package

This package implements RFC 7521 (assertion framework), RFC 7523 (JWT bearer assertions for private_key_jwt), and RFC 9068 (JWT access tokens).

It is the public companion to Vana's internal service-auth setup. The ./registration subpath (manifest schema + Hydra admin reconciliation) is Vana-operator-only and not part of the public surface; it is exported so the Vana account app can consume it as a workspace package.

Versioning

Released via semantic-release from the vana-com/unity-surfaces repository. Pushes to main publish the stable channel (dist-tag latest). Pushes to dev publish the prerelease channel (dist-tag next, e.g. 1.0.0-next.1). Use conventional commits for commit messages.

npm install @opendatalabs/service-auth          # latest
npm install @opendatalabs/service-auth@next     # prerelease

License

MIT.