New:Introducing Socket Scanning for VS Code Marketplace Extensions.Learn more →
Get Started

@opendatalabs/service-auth

Package Overview
Dependencies
Maintainers
4
Versions
135
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@opendatalabs/service-auth

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

latest
Source
npmnpm
Version
1.33.0
Version published
Weekly downloads
379
24.26%
Maintainers
4
Weekly downloads
 
Created
Source

@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.

Keywords

oauth

FAQs

Package last updated on 14 Oct 2026

Related posts