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

@autolabz/service-auth-fastify

v1.0.1

Published

Fastify authentication middleware for AutoLab services

Readme

@autolabz/service-auth-fastify

Fastify authentication middleware for AutoLab services: centralized authentication with fallback to OAuth userinfo.

Version 1.0.0 - This is a major version upgrade from @autolabz/service-auth-middleware v0.2.x with breaking changes. See Migration from v0.2.x below.

Features

  • Unified authentication chain: Prioritize SIMPLE JWT verification, fallback to OAuth userinfo
  • OAuth validation:
    • X-Client-Id matches azp (or userinfo.client_id)
    • Support for required scopes subset validation
  • Flexible: iss/aud validation only when JWT claims exist; skip during userinfo fallback
  • Framework-agnostic core: Built on @autolabz/service-auth-core for maximum reusability

Installation

npm install @autolabz/service-auth-fastify

Quick Start

Use the all-in-one plugin for the simplest integration:

import Fastify from 'fastify';
import { authPlugin } from '@autolabz/service-auth-fastify';

const app = Fastify({ logger: true });

const authCfg = {
  jwtAlg: 'HS256',
  jwtAccessSecret: process.env.JWT_ACCESS_SECRET,
  authBaseUrl: process.env.AUTH_BASE_URL!,
  oauthUserinfoPath: '/oauth/userinfo',
  oauthUserinfoTimeoutMs: 2000,
};

app.register(authPlugin, {
  authConfig: authCfg,
  clientId: {},
  enforce: { requiredScopes: ['data'] }, // Optional: require 'data' scope
});

app.get('/api/hello', async (req, reply) => {
  const userId = req.auth?.userId;
  const clientId = req.clientId;
  return { message: `Hello, user ${userId} from client ${clientId}` };
});

app.listen({ port: 3000, host: '0.0.0.0' });

Usage with Downstream Services

Use makeAuthBridgeFromRequest to create an AuthBridge that transparently forwards authentication to downstream services:

import { makeAuthBridgeFromRequest } from '@autolabz/service-auth-fastify';
import { createPointsClient } from '@autolabz/points-sdk';
import { createDataClient } from '@autolabz/data-sdk';
import { createLLMClient } from '@autolabz/llmapi-sdk';

app.get('/api/user/balance', async (req, reply) => {
  // Create AuthBridge from incoming request
  const auth = makeAuthBridgeFromRequest(req, {
    onUnauthorized: () => {
      req.log.warn('Downstream service returned 401');
    },
  });

  // Pass to SDK
  const pointsClient = createPointsClient({
    baseURL: process.env.POINTS_BASE_URL!,
    auth,
  });

  const balance = await pointsClient.getMyBalance();
  return reply.send(balance);
});

Configuration Reference

AuthConfig

| Key | Description | Required | Default | | --- | --- | --- | --- | | jwtAlg | SIMPLE mode algorithm: 'HS256' or 'RS256' | Yes | - | | jwtAccessSecret | HS256 local verification secret | Yes (when jwtAlg=HS256) | - | | jwksUrl | RS256 JWK Set URL | Yes (when jwtAlg=RS256) | - | | authIssuer | Expected issuer (validates only when JWT claim exists) | No | - | | authBaseUrl | OAuth base URL | Yes | - | | oauthUserinfoPath | Userinfo endpoint path | No | 'oauth/userinfo' | | oauthUserinfoTimeoutMs | Userinfo request timeout (ms) | No | 2000 | | oauthExpectedAudience | Expected audience value | No | - |

EnforceOptions

| Key | Description | Default | | --- | --- | --- | | requiredScopes | Array of required scopes (subset check) | [] (no check) | | enforceForSimple | Enforce scope check for SIMPLE mode | false |

Environment Variables

Typical environment variable setup:

# SIMPLE mode (local JWT verification)
JWT_ALG=HS256
JWT_ACCESS_SECRET=your-secret

# OAuth userinfo fallback
AUTH_BASE_URL=http://auth-service:4001/api
OAUTH_USERINFO_PATH=/oauth/userinfo
OAUTH_USERINFO_TIMEOUT_MS=2000

# Optional
AUTH_ISSUER=https://auth.example.com
OAUTH_EXPECTED_AUDIENCE=autolab-api

Advanced Usage

Custom Scope Requirements per Route

import { oauthEnforceClientScope } from '@autolabz/service-auth-fastify';

app.get('/api/admin/users', {
  preHandler: oauthEnforceClientScope(authCfg, { requiredScopes: ['admin'] }),
}, async (req, reply) => {
  // This route requires 'admin' scope
  return { users: [] };
});

Manual Middleware Chain

If you prefer manual control over the middleware chain:

import { 
  oauthOrSimpleAuth, 
  clientIdMiddleware, 
  oauthEnforceClientScope 
} from '@autolabz/service-auth-fastify';

app.addHook('onRequest', oauthOrSimpleAuth(authCfg));
app.addHook('onRequest', clientIdMiddleware({}));
app.addHook('onRequest', oauthEnforceClientScope(authCfg, { requiredScopes: ['data'] }));

Request Properties

After authentication, the following properties are added to the request:

  • req.auth: AuthPayload object

    • userId: User ID (UUID)
    • sub?: Subject
    • email?: User email
    • iss?: Issuer
    • aud?: Audience
    • azp?: Authorized party (client ID)
    • scope?: Token scopes (space-separated)
    • tokenType?: Token type
  • req.clientId: Client ID from X-Client-Id header or client_id query parameter

Migration from v0.2.x

Breaking Changes

  1. Package name changed: @autolabz/service-auth-middleware@autolabz/service-auth-fastify
  2. Core logic extracted: JWT/userinfo logic moved to @autolabz/service-auth-core
  3. Plugin name updated: Internal plugin name changed from @autolabz/service-auth-middleware:authPlugin to @autolabz/service-auth-fastify:authPlugin

Migration Steps

  1. Update package.json:
{
  "dependencies": {
-   "@autolabz/service-auth-middleware": "^0.2.2"
+   "@autolabz/service-auth-fastify": "^1.0.0"
  }
}
  1. Update imports:
- import { authPlugin } from '@autolabz/service-auth-middleware';
+ import { authPlugin } from '@autolabz/service-auth-fastify';
  1. No code changes required - the API remains the same!

Troubleshooting

401 Unauthorized

  • Check AUTH_BASE_URL and OAUTH_USERINFO_PATH are correct
  • Verify Authorization header uses Bearer <token> format
  • Confirm token has required scopes

X-Client-Id Mismatch

  • Ensure gateway doesn't forward external X-Client-Id headers
  • Let backend set this header consistently

Request Timeout

  • Increase OAUTH_USERINFO_TIMEOUT_MS
  • Check auth service performance and network connectivity

JWT Verification Failed

  • HS256: Verify JWT_ACCESS_SECRET matches auth service
  • RS256: Ensure JWKS_URL is accessible and kid matches

License

MIT