{"id":17224,"library":"fastify-basic-auth-middleware","title":"Fastify Basic Auth Middleware","description":"This package provides a plug-and-play HTTP Basic Authentication solution designed for use with the Fastify web framework. It supports checking credentials against static user lists or through custom synchronous or asynchronous authorizer functions. As of version 0.0.2, it emphasizes secure credential comparison with a `safeCompare` utility to prevent timing attacks. While its README initially showed Express.js examples, the package is explicitly built for Fastify. It ships with TypeScript types, ensuring type safety for Fastify applications. This plugin is distinct from the `@fastify/basic-auth` core plugin, offering a different API for integrating basic authentication.","status":"active","version":"0.0.2","language":"javascript","source_language":"en","source_url":"https://github.com/xtrinch/fastify-basic-auth-middleware","tags":["javascript","express","middleware","basic","auth","authentication","http","typescript"],"install":[{"cmd":"npm install fastify-basic-auth-middleware","lang":"bash","label":"npm"},{"cmd":"yarn add fastify-basic-auth-middleware","lang":"bash","label":"yarn"},{"cmd":"pnpm add fastify-basic-auth-middleware","lang":"bash","label":"pnpm"}],"dependencies":[],"imports":[{"note":"While CommonJS `require` works, ESM `import` is preferred for modern Fastify projects, especially since the library provides TypeScript types. The README's `require` example is valid CJS.","wrong":"const basicAuth = require('fastify-basic-auth-middleware')","symbol":"basicAuth","correct":"import basicAuth from 'fastify-basic-auth-middleware'"},{"note":"`safeCompare` is exported as a property of the default export function, not as a named export. It's crucial for securely comparing user input to prevent timing attacks in custom authorizers.","wrong":"import { safeCompare } from 'fastify-basic-auth-middleware'","symbol":"safeCompare","correct":"import basicAuth from 'fastify-basic-auth-middleware'; const safeCompare = basicAuth.safeCompare;"},{"note":"When writing custom authorizers in TypeScript, you'll likely need types from Fastify itself for `request` and `reply` objects.","symbol":"FastifyRequest","correct":"import type { FastifyRequest } from 'fastify'"}],"quickstart":{"code":"import Fastify from 'fastify';\nimport basicAuthPlugin from 'fastify-basic-auth-middleware';\n\nconst fastify = Fastify({ logger: true });\n\n// Register the basic auth plugin with static users\nfastify.register(basicAuthPlugin, {\n  users: { 'admin': 'supersecret', 'user': 'password123' },\n});\n\n// Add a preHandler hook to protect routes with basic authentication\nfastify.addHook('preHandler', async (request, reply) => {\n  try {\n    // The plugin adds 'auth' to the request if credentials are provided\n    // and checks them against the configured users/authorizer.\n    // If unauthorized, it will automatically send a 401 response.\n    if (!request.auth || !request.auth.user) {\n      reply.code(401).send('Unauthorized'); // This part is handled by the plugin, but explicitly showing the check\n    }\n    request.log.info(`Authenticated user: ${request.auth.user}`);\n  } catch (err) {\n    request.log.error('Authentication error:', err);\n    reply.code(500).send('Internal Server Error');\n  }\n});\n\n// Define a protected route\nfastify.get('/protected', async (request, reply) => {\n  return { message: `Hello, ${request.auth.user}! You accessed a protected route.` };\n});\n\n// Define an unprotected route\nfastify.get('/public', async (request, reply) => {\n  return { message: 'This is a public route.' };\n});\n\nconst start = async () => {\n  try {\n    await fastify.listen({ port: 3000 });\n    fastify.log.info(`Server listening on ${fastify.server.address().port}`);\n    console.log('Try accessing: http://localhost:3000/protected with admin:supersecret');\n    console.log('Try accessing: http://localhost:3000/public');\n  } catch (err) {\n    fastify.log.error(err);\n    process.exit(1);\n  }\n};\n\nstart();","lang":"typescript","description":"This example sets up a Fastify server with basic authentication using static user credentials. It protects the `/protected` route, demonstrating how the `fastify-basic-auth-middleware` integrates with Fastify's plugin system and hooks."},"warnings":[{"fix":"Ensure you are using `fastify.register(basicAuthPlugin, options)` to integrate this plugin with your Fastify instance. For `app.use()` style middleware, Fastify v3+ requires `@fastify/express` or `middie` plugins, but this specific package is a native Fastify plugin.","message":"The README examples explicitly use `require('express')()` and `app.use()`, which are incorrect for Fastify applications. Fastify uses its own plugin system (`fastify.register`) and hooks (`fastify.addHook` or `onRequest`) for middleware integration. Following the README's Express examples will lead to errors.","severity":"breaking","affected_versions":"0.0.x"},{"fix":"Always use the provided `basicAuth.safeCompare(userInput, secret)` function for comparing user-provided credentials with secrets within your custom authorizer. Also, use bitwise logical operators (`|`, `&`) instead of standard (`||`, `&&`) to avoid short-circuiting that could reveal timing information.","message":"When implementing a custom `authorizer` function, direct string comparison (`==` or `===`) for credentials is vulnerable to timing attacks. This can expose sensitive information about credentials based on response times.","severity":"gotcha","affected_versions":">=0.0.1"},{"fix":"For asynchronous `authorizer` functions, pass `authorizeAsync: true` in the options object and ensure your `authorizer` function calls a callback (`cb(error, isApproved)`) or returns a Promise as per Fastify's async hook patterns.","message":"Asynchronous custom `authorizer` functions require setting `authorizeAsync: true` in the plugin options. If this flag is not set, the plugin will treat your asynchronous function as synchronous, leading to incorrect authorization behavior or errors.","severity":"gotcha","affected_versions":">=0.0.1"},{"fix":"Consult the documentation for the specific package you intend to use. If you want the core plugin, install `@fastify/basic-auth`. If you explicitly chose `fastify-basic-auth-middleware`, follow its specific API for plugin registration and usage.","message":"This `fastify-basic-auth-middleware` package is distinct from the official Fastify core plugin `@fastify/basic-auth`. They have different APIs and usage patterns. Be careful not to confuse the two when integrating basic authentication into your Fastify application.","severity":"gotcha","affected_versions":">=0.0.1"}],"env_vars":null,"last_verified":"2026-04-22T00:00:00.000Z","next_check":"2026-07-21T00:00:00.000Z","problems":[{"fix":"Replace `app.use(basicAuth(...))` with `fastify.register(basicAuthPlugin, { ...options... })` to correctly register the plugin with Fastify. Hooks like `fastify.addHook('preHandler', ...)` can then utilize the plugin's functionality.","cause":"Attempting to use `app.use()` with a Fastify instance, as shown in the README's Express example, instead of Fastify's `fastify.register()` or `fastify.addHook()`. Fastify does not have a native `.use()` method for middleware unless `@fastify/express` or `middie` are registered.","error":"TypeError: app.use is not a function"},{"fix":"Ensure that `authorizeAsync: true` is set in the options object when registering the plugin. Additionally, verify that your asynchronous authorizer correctly calls the provided `cb(null, true)` for success or `cb(null, false)` for failure (or resolves/rejects a Promise if using `async/await`).","cause":"Your custom `authorizer` function is asynchronous but you forgot to set `authorizeAsync: true` in the plugin options, or the async function is not correctly handling the callback/Promise resolution.","error":"Error: Unauthorized (HTTP 401 response) when using custom async authorizer"},{"fix":"Augment the `FastifyRequest` interface to include the `auth` property. Create a declaration file (e.g., `src/types/fastify.d.ts`) with:\n```typescript\ndeclare module 'fastify' {\n  interface FastifyRequest {\n    auth: {\n      user: string;\n      password?: string;\n    };\n  }\n}\n```","cause":"When using TypeScript, the `request.auth` property, which is decorated by the plugin, is not automatically recognized by Fastify's default `FastifyRequest` type.","error":"Property 'auth' does not exist on type 'FastifyRequest'"}],"ecosystem":"npm","meta_description":null}