### Minimal Fastify Basic Auth Setup Source: https://github.com/fastify/fastify-basic-auth/blob/main/_autodocs/README.md This example demonstrates the minimal setup for the @fastify/basic-auth plugin. It requires registering the plugin with a validation function and then adding the 'fastify.basicAuth' hook to the request lifecycle. ```javascript const fastify = require('fastify')() await fastify.register(require('@fastify/basic-auth'), { validate: async (username, password) => { if (username === 'admin' && password === 'secret') { return } throw new Error('Invalid credentials') } }) fastify.after(() => { fastify.addHook('onRequest', fastify.basicAuth) fastify.get('/', (req, reply) => { reply.send({ hello: 'world' }) }) }) await fastify.listen({ port: 3000 }) ``` -------------------------------- ### Install @fastify/basic-auth Source: https://github.com/fastify/fastify-basic-auth/blob/main/README.md Install the plugin using npm. Ensure compatibility with your Fastify version. ```bash npm i @fastify/basic-auth ``` -------------------------------- ### Plugin Registration with Options Source: https://github.com/fastify/fastify-basic-auth/blob/main/_autodocs/types.md Example of registering the @fastify/basic-auth plugin with various configuration options. ```typescript await fastify.register(require('@fastify/basic-auth'), { validate: (username, password) => Promise.resolve(), authenticate: { realm: 'Protected' }, header: 'Authorization', strictCredentials: true, utf8: true, proxyMode: false }) ``` -------------------------------- ### Example: Custom Header and Realm Source: https://github.com/fastify/fastify-basic-auth/blob/main/_autodocs/api-reference/internal-utilities.md Demonstrates using a custom header name and a static realm string to configure the authentication challenge. ```javascript // Returns a function that uses custom header getAuthenticateHeaders( { header: 'X-Auth-Challenge', realm: 'Secure' }, false, false )() ``` -------------------------------- ### Example: Proxy-Authenticate Header Source: https://github.com/fastify/fastify-basic-auth/blob/main/_autodocs/api-reference/internal-utilities.md Shows how to generate a `Proxy-Authenticate` header instead of `WWW-Authenticate` by setting the `proxyMode` option to `true`. ```javascript // Returns a function that uses Proxy-Authenticate in proxy mode getAuthenticateHeaders(true, true, true)() ``` -------------------------------- ### Example: Realm from Request Source: https://github.com/fastify/fastify-basic-auth/blob/main/_autodocs/api-reference/internal-utilities.md Illustrates generating a 'Basic' `WWW-Authenticate` header where the `realm` is dynamically determined from the incoming request object. ```javascript // Returns a function that computes realm from request getAuthenticateHeaders( { realm: (req) => 'API' }, true, false )(request) ``` -------------------------------- ### Example: No Authentication Header Source: https://github.com/fastify/fastify-basic-auth/blob/main/_autodocs/api-reference/internal-utilities.md Demonstrates calling `getAuthenticateHeaders` with `false` for the `authenticate` option, resulting in a function that always returns `false`. ```javascript // Returns a function that always returns false getAuthenticateHeaders(false, true, false)() ``` -------------------------------- ### Example: Basic Header with UTF-8 Source: https://github.com/fastify/fastify-basic-auth/blob/main/_autodocs/api-reference/internal-utilities.md Shows how to generate a 'Basic' `WWW-Authenticate` header including the UTF-8 charset parameter when `authenticate` is `true` and `useUtf8` is `true`. ```javascript // Returns a function that returns the Basic header with UTF-8 getAuthenticateHeaders(true, true, false)() ``` -------------------------------- ### Proxy Authentication Setup Source: https://github.com/fastify/fastify-basic-auth/blob/main/_autodocs/configuration.md This configuration enables proxy mode for basic authentication, suitable when an upstream proxy handles initial authentication. It specifies a realm for the proxy server. ```javascript const fastify = require('fastify')() await fastify.register(require('@fastify/basic-auth'), { validate: async (username, password) => { return await verifyProxyCredentials(username, password) }, proxyMode: true, authenticate: { realm: 'Proxy Server' } }) ``` -------------------------------- ### Registering Fastify Basic Auth with Options Source: https://github.com/fastify/fastify-basic-auth/blob/main/_autodocs/configuration.md Register the @fastify/basic-auth plugin with various configuration options. This example shows how to set up the validate function, authentication realm, header, and other parameters. ```javascript await fastify.register(require('@fastify/basic-auth'), { validate: (username, password, req, reply) => { /* ... */ }, authenticate: { realm: 'API' }, header: 'Authorization', strictCredentials: true, utf8: true, proxyMode: false }) ``` -------------------------------- ### HTTP Headers Source: https://github.com/fastify/fastify-basic-auth/blob/main/_autodocs/quick-reference.md Examples of Authorization and Proxy-Authorization headers for requests, and standard response headers. ```APIDOC ### Request (Standard Mode) ``` Authorization: Basic dXNlcjpwYXNz ``` ### Request (Proxy Mode) ``` Proxy-Authorization: Basic dXNlcjpwYXNz ``` ### Response (Success) ``` HTTP/1.1 200 OK ``` ### Response (Failure, Standard Mode) ``` HTTP/1.1 401 Unauthorized WWW-Authenticate: Basic realm="Protected Area", charset="UTF-8" ``` ### Response (Failure, Proxy Mode) ``` HTTP/1.1 407 Proxy Authentication Required Proxy-Authenticate: Basic realm="Proxy Server", charset="UTF-8" ``` ``` -------------------------------- ### Build Valid Authorization Header Source: https://github.com/fastify/fastify-basic-auth/blob/main/_autodocs/api-reference/usage-examples.md This example demonstrates how to construct a Basic Authorization header using username and password. It is useful for client-side code or testing purposes. The output can be directly used with tools like `curl`. ```javascript // In test code or client code const username = 'user' const password = 'password' // Build the Authorization header const credentials = `${username}:${password}` const base64 = Buffer.from(credentials).toString('base64') const authHeader = `Basic ${base64}` console.log(authHeader) // Output: Basic dXNlcjpwYXNzd29yZA== // Use with curl // curl -H "Authorization: Basic dXNlcjpwYXNzd29yZA==" http://localhost:3000/ ``` -------------------------------- ### Base64 Encoding and Decoding Examples Source: https://github.com/fastify/fastify-basic-auth/blob/main/_autodocs/api-reference/internal-utilities.md Demonstrates UTF-8 and ASCII base64 encoding and decoding in Node.js. Shows handling of non-ASCII characters and potential data loss with ASCII. ```javascript // UTF-8 decoding (default) const b64 = Buffer.from('user:password', 'utf8').toString('base64') // → "dXNlcjpwYXNzd29yZA==" const decoded = Buffer.from('dXNlcjpwYXNzd29yZA==', 'base64').toString('utf8') // → "user:password" // With non-ASCII characters const b64utf8 = Buffer.from('user:pässwörd', 'utf8').toString('base64') // → "dXNlcjpww6Rzc3fDtnJk" const decodedUtf8 = Buffer.from('dXNlcjpww6Rzc3fDtnJk', 'base64').toString('utf8') // → "user:pässwörd" // ASCII decoding (loses non-ASCII data) const decodedAscii = Buffer.from('dXNlcjpww6Rzc3fDtnJk', 'base64').toString('ascii') // → "user:p?ss??rd" (mojibake) ``` -------------------------------- ### Minimal Basic Auth Configuration Source: https://github.com/fastify/fastify-basic-auth/blob/main/_autodocs/configuration.md This snippet shows the most basic setup for the @fastify/basic-auth plugin. It requires a validate function to check username and password. ```javascript const fastify = require('fastify')() await fastify.register(require('@fastify/basic-auth'), { validate: async (username, password) => { if (username === 'admin' && password === 'secret') { return } throw new Error('Invalid credentials') } }) ``` -------------------------------- ### Registering the Plugin with Basic Authentication Source: https://github.com/fastify/fastify-basic-auth/blob/main/README.md This example shows how to register the basic-auth plugin with Fastify, enabling basic authentication. The `validate` function is required to verify user credentials. ```APIDOC ## Registering Basic Auth ### Description Registers the `@fastify/basic-auth` plugin to enforce basic authentication for requests. ### Method `fastify.register()` ### Parameters - **`require('@fastify/basic-auth')`**: The plugin to register. - **`options`** (Object): - **`validate`** (Function): Required. A function that validates the username and password. It receives `username`, `password`, `req`, and `reply`. It can return a promise or use `async/await` to signal success or failure. - **`authenticate`** (Boolean|Object): Optional. If `true`, adds the `WWW-Authenticate` header. If an object, it can specify a `realm` or a custom `header`. - **`proxyMode`** (Boolean): Optional. If `true`, enables proxy authentication. - **`header`** (String): Optional. Specifies the header to retrieve credentials from. ### Request Example ```javascript const fastify = require('fastify')() async function validate (username, password) { if (username === 'user' && password === 'secret') { return true } return false } fastify.register(require('@fastify/basic-auth'), { validate: validate, authenticate: true // Adds WWW-Authenticate: Basic header }) fastify.get('/', (req, reply) => { reply.send({ hello: 'world' }) }) fastify.listen(3000) ``` ### Response #### Success Response (200) Returns the requested resource if authentication is successful. #### Error Response (401) Returns a `401 Unauthorized` status code if authentication fails. ``` -------------------------------- ### Integrating Fastify Basic Auth with @fastify/auth Source: https://github.com/fastify/fastify-basic-auth/blob/main/_autodocs/quick-reference.md Combine Fastify Basic Auth with the @fastify/auth plugin for more advanced authentication strategies. This example uses `preHandler` hook for authentication. ```javascript await fastify.register(require('@fastify/auth')) await fastify.register(require('@fastify/basic-auth'), { validate }) fastify.after(() => { fastify.addHook('preHandler', fastify.auth([fastify.basicAuth])) }) ``` -------------------------------- ### Register Basic Auth with Realm Source: https://github.com/fastify/fastify-basic-auth/blob/main/README.md Customize the `WWW-Authenticate` header by providing a `realm` string within the `authenticate` object. This appends `realm="example"` to the header. ```javascript fastify.register(require('@fastify/basic-auth'), { validate, authenticate: {realm: 'example'} // WWW-Authenticate: Basic realm="example" }) ``` -------------------------------- ### Basic Authentication Header Format Source: https://github.com/fastify/fastify-basic-auth/blob/main/_autodocs/configuration.md Illustrates the standard Authorization header format for Basic authentication, including examples of base64-encoded credentials and their decoded values. ```text Authorization: Basic ``` ```text Authorization: Basic dXNlcjpwYXNz // Decodes to: user:pass ``` ```text Authorization: Basic YWRtaW46c2VjcmV0 // Decodes to: admin:secret ``` -------------------------------- ### Basic Setup for Fastify Basic Auth Source: https://github.com/fastify/fastify-basic-auth/blob/main/_autodocs/quick-reference.md Register the basic-auth plugin and add the onRequest hook for authentication. This is the most common way to set up basic authentication for your Fastify application. ```javascript await fastify.register(require('@fastify/basic-auth'), { validate: async (username, password) => { if (username === 'user' && password === 'pass') return throw new Error('Invalid') } }) fastify.after(() => { fastify.addHook('onRequest', fastify.basicAuth) }) ``` -------------------------------- ### Usage with Async/Await Validation Source: https://github.com/fastify/fastify-basic-auth/blob/main/README.md This example demonstrates using Promises and async/await for the `validate` function. The plugin supports asynchronous validation logic. ```javascript const fastify = require('fastify')() const authenticate = {realm: 'Westeros'} fastify.register(require('@fastify/basic-auth'), { validate, authenticate }) async function validate (username, password, req, reply) { if (username !== 'Tyrion' || password !== 'wine') { return new Error('Winter is coming') } } ``` -------------------------------- ### Basic Auth Validation with Database Source: https://github.com/fastify/fastify-basic-auth/blob/main/_autodocs/quick-reference.md Implement the validate function to check credentials against a database. This example assumes a `db.findUser` method and a `user.verifyPassword` method. ```javascript validate: async (username, password) => { const user = await db.findUser(username) if (user && await user.verifyPassword(password)) return throw new Error('Invalid credentials') } ``` -------------------------------- ### Production Basic Auth with Realm and Strictness Source: https://github.com/fastify/fastify-basic-auth/blob/main/_autodocs/configuration.md This example configures basic auth for production, including a database lookup for authentication, a custom realm, and strict credential parsing. The authenticated user is attached to the request object. ```javascript const fastify = require('fastify')() await fastify.register(require('@fastify/basic-auth'), { validate: async (username, password, req, reply) => { const user = await database.authenticate(username, password) if (!user) { const error = new Error('Authentication failed') error.statusCode = 401 throw error } // Attach user to request for handler access req.user = user }, authenticate: { realm: 'My Company API' }, utf8: true, strictCredentials: true }) ``` -------------------------------- ### Override Credentials for Development Source: https://github.com/fastify/fastify-basic-auth/blob/main/_autodocs/api-reference/usage-examples.md This example shows how to override normal validation logic for development environments using environment variables. Ensure that `DEV_OVERRIDE_USER` and `DEV_OVERRIDE_PASS` are set to enable this override. ```javascript const fastify = require('fastify')() const OVERRIDE_USER = process.env.DEV_OVERRIDE_USER const OVERRIDE_PASS = process.env.DEV_OVERRIDE_PASS await fastify.register(require('@fastify/basic-auth'), { validate: async (username, password) => { // Allow override in development if (OVERRIDE_USER && OVERRIDE_PASS) { if (username === OVERRIDE_USER && password === OVERRIDE_PASS) { return } } // Normal validation const user = await db.findUser(username) if (!user || !(await user.verifyPassword(password))) { throw new Error('Invalid credentials') } } }) ``` -------------------------------- ### UTF-8 Credentials Support Source: https://github.com/fastify/fastify-basic-auth/blob/main/_autodocs/api-reference/usage-examples.md This example shows how to handle non-ASCII characters in usernames and passwords. Set `utf8: true` in the plugin options and ensure the client encodes credentials using UTF-8. The server will then correctly decode them. ```javascript // Client encoding const username = 'üser' const password = 'pässword' const credentials = `${username}:${password}` const base64 = Buffer.from(credentials, 'utf8').toString('base64') const authHeader = `Basic ${base64}` // Server validation (with utf8: true) const fastify = require('fastify')() await fastify.register(require('@fastify/basic-auth'), { validate: async (username, password) => { // username will be 'üser' // password will be 'pässword' if (username === 'üser' && password === 'pässword') { return } throw new Error('Invalid credentials') }, utf8: true // Required for non-ASCII support }) ``` -------------------------------- ### Using basicAuth with onRequest Hook Source: https://github.com/fastify/fastify-basic-auth/blob/main/_autodocs/api-reference/fastify-basic-auth.md Example of integrating the basicAuth handler using the onRequest hook for a specific route. This ensures authentication before the route handler is executed. ```javascript // Using with onRequest hook fastify.route({ method: 'GET', url: '/protected', onRequest: fastify.basicAuth, handler: async (req, reply) => { return { data: 'secret' } } }) ``` -------------------------------- ### Example Usage of Control Character Detection Source: https://github.com/fastify/fastify-basic-auth/blob/main/_autodocs/api-reference/internal-utilities.md Demonstrates how to use the `controlRE` to test if a decoded string contains any prohibited control characters. ```javascript const decoded = "user:pass" if (controlRE.test(decoded)) { // Reject: contains control character } ``` -------------------------------- ### Authenticate Option: With Custom Header Name Source: https://github.com/fastify/fastify-basic-auth/blob/main/_autodocs/configuration.md Configure the 'authenticate' option with a custom 'header' string to specify a non-standard HTTP header name for the challenge. This example uses 'X-Challenge' instead of 'WWW-Authenticate'. ```javascript authenticate: { header: 'X-Challenge', realm: 'My API' } ``` -------------------------------- ### Async Style Validation with Database Lookup Source: https://github.com/fastify/fastify-basic-auth/blob/main/_autodocs/configuration.md Implement the validation function using async/await for asynchronous operations like database lookups. This example compares a provided password against a stored hash using bcrypt. ```javascript async function validate(username, password, req, reply) { const user = await db.users.findOne({ username }) if (!user) { throw new Error('User not found') } const isValid = await bcrypt.compare(password, user.passwordHash) if (!isValid) { throw new Error('Invalid password') } } ``` -------------------------------- ### Log Authentication Events Source: https://github.com/fastify/fastify-basic-auth/blob/main/_autodocs/api-reference/usage-examples.md Integrate basic-auth with custom validation logic that logs authentication success or failure events. This example demonstrates logging user, IP, duration, and reason for authentication attempts. ```javascript const fastify = require('fastify')() await fastify.register(require('@fastify/basic-auth'), { validate: async (username, password, req) => { const startTime = Date.now() try { const user = await db.findUser(username) if (!user) { fastify.log.warn({ event: 'auth_failed', reason: 'user_not_found', username, ip: req.ip }) throw new Error('User not found') } const valid = await user.verifyPassword(password) const duration = Date.now() - startTime if (!valid) { fastify.log.warn({ event: 'auth_failed', reason: 'invalid_password', username, ip: req.ip, duration }) throw new Error('Invalid password') } fastify.log.info({ event: 'auth_success', username, ip: req.ip, duration }) } catch (err) { throw err } } }) ``` -------------------------------- ### Register Basic Auth with Custom Header Name Source: https://github.com/fastify/fastify-basic-auth/blob/main/README.md Specify a custom header name for authentication using the `header` key within the `authenticate` object. This example sets the header to `Proxy-Authenticate`. ```javascript fastify.register(require('@fastify/basic-auth'), { validate, authenticate: { header: 'Proxy-Authenticate' // Proxy-Authenticate: Basic } }) ``` -------------------------------- ### Conditional Authentication Based on Path Source: https://github.com/fastify/fastify-basic-auth/blob/main/_autodocs/api-reference/usage-examples.md Register the basic-auth plugin and add an onRequest hook to conditionally apply authentication only to non-public paths. This example shows how to define public paths and then use fastify.basicAuth within the hook. ```javascript const fastify = require('fastify')() const publicPaths = ['/health', '/info', '/docs'] await fastify.register(require('@fastify/basic-auth'), { validate: async (username, password) => { if (username === 'admin' && password === 'secret') { return } throw new Error('Invalid credentials') } }) fastify.after(() => { // Only authenticate if path is not public fastify.addHook('onRequest', (req, reply, done) => { if (publicPaths.includes(req.url)) { return done() } fastify.basicAuth(req, reply, done) }) fastify.get('/health', (req, reply) => { return { status: 'ok' } }) fastify.get('/admin', (req, reply) => { return { admin: true } }) }) ``` -------------------------------- ### Import @fastify/basic-auth Module Source: https://github.com/fastify/fastify-basic-auth/blob/main/_autodocs/quick-reference.md Import the basic-auth plugin using either CommonJS or TypeScript/ESM syntax. Ensure you have the correct version installed for your Fastify setup. ```javascript // CommonJS const basicAuth = require('@fastify/basic-auth') const { fastifyBasicAuth } = require('@fastify/basic-auth') // TypeScript/ESM import basicAuth from '@fastify/basic-auth' import { fastifyBasicAuth } from '@fastify/basic-auth' ``` -------------------------------- ### Using basicAuth with @fastify/auth Source: https://github.com/fastify/fastify-basic-auth/blob/main/_autodocs/api-reference/fastify-basic-auth.md Shows how to use the basicAuth handler in conjunction with the @fastify/auth plugin, applying it as a 'preHandler' hook. ```javascript // Using with @fastify/auth fastify.addHook('preHandler', fastify.auth([fastify.basicAuth])) ``` -------------------------------- ### Handling Missing or Bad Authorization Header Error Source: https://github.com/fastify/fastify-basic-auth/blob/main/_autodocs/types.md Example of how to catch and handle the FST_BASIC_AUTH_MISSING_OR_BAD_AUTHORIZATION_HEADER error using Fastify's error handler. ```javascript fastify.setErrorHandler(function (err, req, reply) { if (err.code === 'FST_BASIC_AUTH_MISSING_OR_BAD_AUTHORIZATION_HEADER') { // handle auth error } }) ``` -------------------------------- ### Configuring `authenticate` Option Source: https://github.com/fastify/fastify-basic-auth/blob/main/README.md Demonstrates how to configure the `authenticate` option to customize the `WWW-Authenticate` header, including setting a realm or using a custom header name. ```APIDOC ## Authenticate Option Configuration ### Description Configures the `WWW-Authenticate` header behavior, including setting a realm or customizing the header name. ### Parameters - **`authenticate`** (Boolean|Object): - **`true`**: Adds `WWW-Authenticate: Basic` header. - **`false`**: No `WWW-Authenticate` header is added. - **Object**: Allows for more advanced configuration: - **`realm`** (String|Function): Specifies the realm for the `WWW-Authenticate` header. Can be a static string or a function that returns the realm string based on the request. - **`header`** (String): Specifies a custom header name to use instead of `WWW-Authenticate`. ### Request Example (with realm) ```javascript fastify.register(require('@fastify/basic-auth'), { validate, authenticate: { realm: 'my-realm' } // WWW-Authenticate: Basic realm="my-realm" }) ``` ### Request Example (with custom header) ```javascript fastify.register(require('@fastify/basic-auth'), { validate, authenticate: { header: 'Proxy-Authenticate' // Uses Proxy-Authenticate header } }) ``` ### Response Handles authentication responses based on the `authenticate` configuration. ``` -------------------------------- ### Configuration Options Source: https://github.com/fastify/fastify-basic-auth/blob/main/_autodocs/quick-reference.md Details on the available configuration options for the @fastify/basic-auth plugin. ```APIDOC | Option | Type | Default | Values | |--------|------|---------|--------| | validate | function | required | `(username, password, req, reply, done?) => void | Promise` | | authenticate | - | false | `false | true | { realm?: string | function, header?: string }` | | header | string | "Authorization" or "Proxy-Authorization" | Any HTTP header name | | strictCredentials | boolean | true | `true` (RFC strict) or `false` (lenient) | | utf8 | boolean | true | `true` (UTF-8) or `false` (ASCII) | | proxyMode | boolean | false | `true` (proxy mode) or `false` (standard) | ``` -------------------------------- ### Using basicAuth with addHook Source: https://github.com/fastify/fastify-basic-auth/blob/main/_autodocs/api-reference/fastify-basic-auth.md Demonstrates how to apply the basicAuth handler globally to all routes using the addHook method with the 'onRequest' hook. ```javascript // Using with addHook fastify.addHook('onRequest', fastify.basicAuth) ``` -------------------------------- ### Authenticate Option: Basic Challenge Source: https://github.com/fastify/fastify-basic-auth/blob/main/_autodocs/configuration.md Configure the 'authenticate' option to 'true' to send a standard 'Basic' challenge header when authentication fails. If 'utf8' is also true, 'charset="UTF-8"' will be appended. ```javascript authenticate: true ``` -------------------------------- ### Integrate Basic Auth with @fastify/auth Source: https://github.com/fastify/fastify-basic-auth/blob/main/_autodocs/api-reference/usage-examples.md This snippet shows how to register both @fastify/auth and @fastify/basic-auth, and then protect all routes using the basic authentication strategy. ```javascript const fastify = require('fastify')() await fastify.register(require('@fastify/auth')) await fastify.register(require('@fastify/basic-auth'), { validate: async (username, password) => { const user = await db.findUser(username) if (!user || !(await user.verifyPassword(password))) { throw new Error('Invalid credentials') } } }) fastify.after(() => { // Protect all routes with auth fastify.addHook('preHandler', fastify.auth([ fastify.basicAuth // Can add more strategies here ])) fastify.get('/', (req, reply) => { return { authenticated: true } }) }) ``` -------------------------------- ### Callback Style Validation with Timing-Safe Comparison Source: https://github.com/fastify/fastify-basic-auth/blob/main/_autodocs/configuration.md Implement the validation function using a callback style for synchronous operations. This example uses crypto.timingSafeEqual for secure password comparison. ```javascript const crypto = require('crypto') function validate(username, password, req, reply, done) { const validUser = Buffer.from('admin') const validPass = Buffer.from('secret') try { const user = Buffer.from(username) const pass = Buffer.from(password) const userMatch = user.length === validUser.length && crypto.timingSafeEqual(user, validUser) const passMatch = pass.length === validPass.length && crypto.timingSafeEqual(pass, validPass) if (userMatch && passMatch) { done() } else { done(new Error('Invalid credentials')) } } catch (err) { done(err) } } ``` -------------------------------- ### Multiple Authentication Strategies with @fastify/auth Source: https://github.com/fastify/fastify-basic-auth/blob/main/_autodocs/api-reference/integration-patterns.md Register @fastify/auth and @fastify/basic-auth, then use fastify.auth to protect all routes with basic authentication. Ensure @fastify/auth is registered before other auth plugins. ```javascript const fastify = require('fastify')() // Register @fastify/auth first await fastify.register(require('@fastify/auth')) // Register basic auth await fastify.register(require('@fastify/basic-auth'), { validate: async (username, password) => { if (username === 'user' && password === 'pass') { return } throw new Error('Invalid credentials') } }) fastify.after(() => { // Protect all routes with auth plugin fastify.addHook('preHandler', fastify.auth([ fastify.basicAuth, // Could add more strategies: fastify.bearerAuth, fastify.customAuth ])) fastify.get('/protected', async (req, reply) => { return { data: 'protected' } }) }) ``` -------------------------------- ### Validate Function - Callback Mode Source: https://github.com/fastify/fastify-basic-auth/blob/main/_autodocs/types.md Example of the validate function using callback mode. Call `done()` with no arguments for success, or `done(new Error(...))` for failure. ```javascript function validate(username, password, req, reply, done) { if (isValid(username, password)) { done() // no arguments = success } else { done(new Error('Auth failed')) // error = failure } } ``` -------------------------------- ### Using basicAuth with Global Hooks Source: https://github.com/fastify/fastify-basic-auth/blob/main/_autodocs/api-reference/integration-patterns.md This pattern demonstrates how to apply `basicAuth` globally to all routes or a group of routes by using `fastify.addHook`. This is useful for protecting entire sections of an API. ```APIDOC ## Using basicAuth with Global Hooks ### Description Applies authentication to all routes or a group of routes using `fastify.addHook` with `onRequest`, `preValidation`, or `preHandler`. ### Method `fastify.addHook('onRequest', fastify.basicAuth)` ### Endpoint Applies to all routes defined after the hook is added. ### Parameters #### Request Body N/A ### Request Example ```javascript fastify.addHook('onRequest', fastify.basicAuth) fastify.get('/data', async (req, reply) => { return { data: 'sensitive' } }) ``` ### Response #### Success Response (200) Returns the result of the route handler for authenticated requests. #### Response Example ```json { "data": "sensitive" } ``` ``` -------------------------------- ### Fastify Basic Auth with TypeScript Source: https://github.com/fastify/fastify-basic-auth/blob/main/_autodocs/README.md Demonstrates how to register the basic-auth plugin and utilize its TypeScript support for type safety. The `validate` function is where custom authentication logic resides. ```typescript import fastify from 'fastify' import basicAuth from '@fastify/basic-auth' const app = fastify() await app.register(basicAuth, { validate: async (username: string, password: string) => { // ... } }) // app.basicAuth is now typed correctly ``` -------------------------------- ### Register Basic Auth with Proxy Authentication Header Source: https://github.com/fastify/fastify-basic-auth/blob/main/README.md Configure the plugin for proxy authentication by setting `proxyMode: true` and `authenticate: true`. This will use the `Proxy-Authenticate: Basic` header. ```javascript fastify.register(require('@fastify/basic-auth'), { validate, proxyMode: true, authenticate: true // Proxy-Authenticate: Basic }) ``` -------------------------------- ### Using Basic Auth Hooks Source: https://github.com/fastify/fastify-basic-auth/blob/main/_autodocs/INDEX.md Apply basic authentication to requests using Fastify hooks or route options. This can be done globally via `onRequest` or on a per-route basis. ```javascript fastify.addHook('onRequest', fastify.basicAuth) fastify.route({onRequest: fastify.basicAuth, handler: ... }) fastify.auth([fastify.basicAuth]) ``` -------------------------------- ### Validate Function - Promise Mode Source: https://github.com/fastify/fastify-basic-auth/blob/main/_autodocs/types.md Example of the validate function using promise mode. Return `undefined` or `Promise` for success, or throw an `Error` or return a rejected `Promise` for failure. ```javascript async function validate(username, password, req, reply) { if (isValid(username, password)) { return // success } else { throw new Error('Auth failed') // or return Error } } ``` -------------------------------- ### Enabling Proxy Authentication Source: https://github.com/fastify/fastify-basic-auth/blob/main/README.md Shows how to configure the plugin for proxy authentication using the `proxyMode` option, which affects header names and status codes. ```APIDOC ## Proxy Authentication Mode ### Description Enables proxy authentication mode, which changes the plugin's behavior to handle proxy credentials instead of resource credentials. ### Method `fastify.register()` ### Parameters - **`proxyMode`** (Boolean): If `true`, the plugin will: - Read credentials from the `Proxy-Authorization` header. - Use a `407` status code for missing or invalid credentials. - Use the `Proxy-Authenticate` header if `authenticate` is set. ### Request Example ```javascript fastify.register(require('@fastify/basic-auth'), { validate, proxyMode: true, authenticate: true // Uses Proxy-Authenticate header }) ``` ### Response #### Error Response (407) Returns a `407 Proxy Authentication Required` status code when `proxyMode` is enabled and authentication fails. ``` -------------------------------- ### Fastify Basic Auth Configuration Options Source: https://github.com/fastify/fastify-basic-auth/blob/main/_autodocs/00-START-HERE.txt Details the available configuration options for the Fastify Basic Auth plugin, allowing users to customize authentication behavior, header names, and compliance modes. ```APIDOC ## Configuration Options The `fastifyBasicAuth` plugin accepts an options object to customize its behavior. Key options include: ### `validate` (required function) A function that must be provided to validate user credentials. It typically receives the username and password and should return a boolean or throw an error. ### `authenticate` (header configuration) Specifies how the `Authorization` header should be processed. This option is used for custom header configurations. ### `header` (custom header name) Allows specifying a custom name for the `Authorization` header if a non-standard name is used. ### `strictCredentials` (RFC mode) When set to `true`, enforces strict adherence to RFC 7617 for credential handling. Defaults to `false`. ### `utf8` (encoding) Determines whether to use UTF-8 encoding for credentials. Defaults to `true`. ### `proxyMode` (proxy authentication) Enables proxy authentication mode, which is relevant when Fastify is running behind a proxy that handles authentication. ``` -------------------------------- ### Authenticate Option: With Static Realm Source: https://github.com/fastify/fastify-basic-auth/blob/main/_autodocs/configuration.md Configure the 'authenticate' option with a static 'realm' string to specify the scope of protection for the challenge header. The 'Basic' challenge will include this realm. ```javascript authenticate: { realm: 'Secure Area' } ``` -------------------------------- ### Configure Basic Auth with Environment Variables Source: https://github.com/fastify/fastify-basic-auth/blob/main/_autodocs/configuration.md Use environment variables to dynamically set username, password, and realm for basic authentication. This snippet shows how to define a validation function that reads credentials from process.env. ```javascript const validate = async (username, password) => { const expectedUser = process.env.BASIC_AUTH_USER const expectedPass = process.env.BASIC_AUTH_PASSWORD if (username === expectedUser && password === expectedPass) { return } throw new Error('Invalid credentials') } await fastify.register(require('@fastify/basic-auth'), { validate, authenticate: { realm: process.env.API_REALM || 'Protected' } }) ``` -------------------------------- ### Custom Error Messages for User Not Found or Invalid Password Source: https://github.com/fastify/fastify-basic-auth/blob/main/_autodocs/errors.md This example shows how to throw custom errors with specific properties ('userNotFound', 'invalidPassword') from a validation function and handle them in the Fastify error handler to provide tailored responses. ```javascript async function validate(username, password, req, reply) { const user = await db.findUser(username) if (!user) { const error = new Error('User not found') error.userNotFound = true throw error } const isValid = await bcrypt.compare(password, user.passwordHash) if (!isValid) { const error = new Error('Invalid password') error.invalidPassword = true throw error } } fastify.setErrorHandler(function (err, req, reply) { if (err.invalidPassword) { reply.code(401).send({ error: 'Invalid password' }) return } if (err.userNotFound) { reply.code(401).send({ error: 'User not found' }) return } if (err.statusCode === 401) { reply.code(401).send({ error: 'Authentication failed' }) return } reply.send(err) }) ``` -------------------------------- ### Apply Global Authentication with basicAuth Source: https://github.com/fastify/fastify-basic-auth/blob/main/_autodocs/api-reference/integration-patterns.md Use `addHook` to apply basicAuth to all subsequent routes. The `validate` function can perform complex checks, and `authenticate` options can configure the realm. ```javascript const fastify = require('fastify')() await fastify.register(require('@fastify/basic-auth'), { validate: async (username, password) => { // Validate against a database const user = await users.findOne({ username }) if (!user || !(await user.verifyPassword(password))) { throw new Error('Invalid credentials') } // You can store user info for later access return { userId: user.id } }, authenticate: { realm: 'My API' } }) fastify.after(() => { // All subsequent routes require authentication fastify.addHook('onRequest', fastify.basicAuth) fastify.get('/data', async (req, reply) => { return { data: 'sensitive' } }) fastify.post('/users', async (req, reply) => { return { created: true } }) }) ``` -------------------------------- ### Integration with @fastify/auth Source: https://github.com/fastify/fastify-basic-auth/blob/main/README.md Combine @fastify/basic-auth with @fastify/auth for centralized authentication. Use `fastify.auth` with `fastify.basicAuth` in hooks like `preHandler` or `onRequest`. ```javascript const fastify = require('fastify')() const authenticate = {realm: 'Westeros'} fastify.register(require('@fastify/auth')) fastify.register(require('@fastify/basic-auth'), { validate, authenticate }) async function validate (username, password, req, reply) { if (username !== 'Tyrion' || password !== 'wine') { return new Error('Winter is coming') } } fastify.after(() => { // use preHandler to authenticate all the routes fastify.addHook('preHandler', fastify.auth([fastify.basicAuth])) fastify.route({ method: 'GET', url: '/', // use onRequest to authenticate just this one onRequest: fastify.auth([fastify.basicAuth]), handler: async (req, reply) => { return { hello: 'world' } } }) }) ``` -------------------------------- ### Custom Header and Dynamic Realm Configuration Source: https://github.com/fastify/fastify-basic-auth/blob/main/_autodocs/configuration.md This snippet demonstrates using a custom header for authentication and dynamically setting the realm based on the incoming request's hostname. It also specifies the custom header name. ```javascript const fastify = require('fastify')() await fastify.register(require('@fastify/basic-auth'), { validate: validateCredentials, authenticate: { header: 'X-API-Auth', realm: (req) => { // Different realm based on request return `${req.hostname} API` } }, header: 'X-API-Auth' }) ``` -------------------------------- ### Import Fastify Basic Auth (CommonJS Default) Source: https://github.com/fastify/fastify-basic-auth/blob/main/_autodocs/api-reference/fastify-basic-auth.md Import the plugin using the CommonJS require syntax for the default export. ```javascript // CommonJS default const basicAuth = require('@fastify/basic-auth') ``` -------------------------------- ### FastifyInstance Type Extension for Basic Auth Hook Source: https://github.com/fastify/fastify-basic-auth/blob/main/_autodocs/api-reference/fastify-basic-auth.md This TypeScript code demonstrates how the Fastify Basic Auth plugin extends the global FastifyInstance interface. This ensures that when using TypeScript, the `fastify.basicAuth` property is correctly typed as an `onRequestHookHandler`, `preValidationHookHandler`, or `preHandlerHookHandler`, providing type safety for hook usage. ```typescript interface FastifyInstance { basicAuth: onRequestHookHandler | preValidationHookHandler | preHandlerHookHandler } ``` -------------------------------- ### Customizing the Credentials Header Source: https://github.com/fastify/fastify-basic-auth/blob/main/README.md Illustrates how to use the `header` option to specify a custom HTTP header from which to retrieve authentication credentials. ```APIDOC ## Custom Credentials Header ### Description Allows specifying a custom header name to retrieve authentication credentials from, overriding the default `Authorization` or `Proxy-Authorization`. ### Method `fastify.register()` ### Parameters - **`header`** (String): The name of the custom header containing the credentials. ### Request Example ```javascript fastify.register(require('@fastify/basic-auth'), { validate, header: 'x-custom-auth' }) ``` ### Response Authenticates requests based on credentials found in the specified custom header. ``` -------------------------------- ### Database Authentication with bcrypt Source: https://github.com/fastify/fastify-basic-auth/blob/main/_autodocs/api-reference/usage-examples.md Shows how to validate user credentials against a database using bcrypt for password hashing. The validate function checks user existence and compares the provided password with the stored hash. ```javascript const fastify = require('fastify')() const bcrypt = require('bcrypt') const db = { users: { admin: '$2b$10$n9qo8uLOickgx2ZMRZoHyea.4xuwEAXR7mD1j7z.3GI2' } } await fastify.register(require('@fastify/basic-auth'), { validate: async (username, password, req, reply) => { const user = await db.users[username] if (!user) { throw new Error('User not found') } const valid = await bcrypt.compare(password, user) if (!valid) { throw new Error('Invalid password') } req.user = { username } } }) fastify.after(() => { fastify.addHook('onRequest', fastify.basicAuth) fastify.get('/profile', (req, reply) => { return { user: req.user } }) }) ``` -------------------------------- ### Register Basic Auth with Default Authentication Header Source: https://github.com/fastify/fastify-basic-auth/blob/main/README.md Register the basic-auth plugin with `authenticate: true` to enable the `WWW-Authenticate: Basic` header. Ensure the `validate` function is defined. ```javascript fastify.register(require('@fastify/basic-auth'), { validate, authenticate: true // WWW-Authenticate: Basic }) ``` -------------------------------- ### Import Fastify Basic Auth (CommonJS Named) Source: https://github.com/fastify/fastify-basic-auth/blob/main/_autodocs/api-reference/fastify-basic-auth.md Import the plugin using the CommonJS require syntax for a named export. ```javascript // CommonJS named const { fastifyBasicAuth } = require('@fastify/basic-auth') ``` -------------------------------- ### Authenticate Option: No Challenge Header Source: https://github.com/fastify/fastify-basic-auth/blob/main/_autodocs/configuration.md Configure the 'authenticate' option to 'false' to prevent any 'WWW-Authenticate' or 'Proxy-Authenticate' header from being sent when authentication fails. This is the default behavior. ```javascript authenticate: false ``` -------------------------------- ### Wrap Plugin with fastify-plugin Source: https://github.com/fastify/fastify-basic-auth/blob/main/_autodocs/api-reference/internal-utilities.md This snippet shows how to wrap the fastify-basic-auth plugin using fastify-plugin. It specifies Fastify version compatibility and provides a plugin name for debugging. This allows the 'basicAuth' decorator to be available immediately on the Fastify instance. ```javascript module.exports = fp(fastifyBasicAuth, { fastify: '5.x', name: '@fastify/basic-auth' }) module.exports.default = fastifyBasicAuth module.exports.fastifyBasicAuth = fastifyBasicAuth ``` -------------------------------- ### Header Option: Standard Authorization Source: https://github.com/fastify/fastify-basic-auth/blob/main/_autodocs/configuration.md Use the default 'Authorization' header to read credentials. This setting is case-insensitive and is the standard for Basic Authentication. ```javascript header: 'Authorization' ``` -------------------------------- ### CommonJS Module Import Source: https://github.com/fastify/fastify-basic-auth/blob/main/_autodocs/README.md Import the plugin using require() for CommonJS environments. ```javascript const basicAuth = require('@fastify/basic-auth') const { fastifyBasicAuth } = require('@fastify/basic-auth') ``` -------------------------------- ### Authenticate Option - Object with Realm (String) Source: https://github.com/fastify/fastify-basic-auth/blob/main/_autodocs/types.md Configures the WWW-Authenticate header with a static realm string. ```typescript authenticate: { realm: 'My API' } // Produces: "WWW-Authenticate: Basic realm=\"My API\"" ``` -------------------------------- ### HTTP Response Header (Success) Source: https://github.com/fastify/fastify-basic-auth/blob/main/_autodocs/quick-reference.md Standard HTTP 200 OK response for successful authentication. ```http HTTP/1.1 200 OK ``` -------------------------------- ### Configure Basic Auth for HTTP Proxy Source: https://github.com/fastify/fastify-basic-auth/blob/main/_autodocs/api-reference/integration-patterns.md Use proxyMode: true to enable HTTP proxy authentication. This changes the behavior to read from the Proxy-Authorization header and return 407 Proxy Authentication Required. ```javascript const fastify = require('fastify')() await fastify.register(require('@fastify/basic-auth'), { proxyMode: true, validate: async (username, password) => { const proxy = await proxies.findOne({ username }) if (!proxy || !(await proxy.verifyPassword(password))) { throw new Error('Proxy authentication failed') } }, authenticate: { realm: 'Proxy Server' } }) fastify.after(() => { fastify.addHook('onRequest', fastify.basicAuth) // Handle proxy requests fastify.all('*', async (req, reply) => { // Forward to target service return await proxyRequest(req) }) }) ``` -------------------------------- ### Register Basic Auth with Function Realm Source: https://github.com/fastify/fastify-basic-auth/blob/main/README.md Use a function for the `realm` property within the `authenticate` object to dynamically set the realm based on the request. The function should return the realm string. ```javascript fastify.register(require('@fastify/basic-auth'), { validate, authenticate: { realm(req) { return 'example' // WWW-Authenticate: Basic realm="example" } } }) ``` -------------------------------- ### Custom Realm for Basic Auth Source: https://github.com/fastify/fastify-basic-auth/blob/main/_autodocs/quick-reference.md Configure a custom realm for the Basic Authentication challenge. The realm is typically used to identify the protected resource. ```javascript authenticate: { realm: (req) => `${req.hostname} API` } ``` -------------------------------- ### Timing-Safe Comparison for Credentials Source: https://github.com/fastify/fastify-basic-auth/blob/main/_autodocs/quick-reference.md Use `crypto.timingSafeEqual` for comparing credentials to prevent timing attacks. This is crucial for security when handling sensitive information like passwords. ```javascript import crypto from 'node:crypto' async function validate(username, password) { const expectedUser = Buffer.from('admin') const expectedPass = Buffer.from('secret') const userMatch = crypto.timingSafeEqual( Buffer.from(username), expectedUser ) const passMatch = crypto.timingSafeEqual( Buffer.from(password), expectedPassword ) if (userMatch && passMatch) return throw new Error('Invalid') } ``` -------------------------------- ### Configure Dynamic Realm for Basic Auth Source: https://github.com/fastify/fastify-basic-auth/blob/main/_autodocs/api-reference/integration-patterns.md Set the authentication realm dynamically using a function that inspects the request object. This allows for different realms based on hostnames or other request properties. ```javascript const fastify = require('fastify')() await fastify.register(require('@fastify/basic-auth'), { validate: async (username, password) => { if (username === 'user' && password === 'pass') { return } throw new Error('Invalid credentials') }, authenticate: { realm: (req) => { // Different realm based on hostname const host = req.hostname if (host === 'api.example.com') { return 'API Server' } else if (host === 'admin.example.com') { return 'Admin Panel' } return 'Protected Area' } } }) fastify.after(() => { fastify.addHook('onRequest', fastify.basicAuth) fastify.get('/', (req, reply) => { return { realm: req.headers['www-authenticate'] } }) }) ``` -------------------------------- ### Strict vs. Non-Strict Credentials Header Format Source: https://github.com/fastify/fastify-basic-auth/blob/main/_autodocs/configuration.md Shows the difference in the Authorization header format when strictCredentials is true (exact format) versus false (whitespace permitted). ```text Basic ``` ```text Basic ``` -------------------------------- ### Per-Route Authentication Selection with @fastify/auth Source: https://github.com/fastify/fastify-basic-auth/blob/main/_autodocs/api-reference/integration-patterns.md Register multiple authentication plugins and use fastify.auth within route options to specify which authentication strategy to use for individual routes. This allows for fine-grained control over authentication requirements. ```javascript await fastify.register(require('@fastify/auth')) await fastify.register(require('@fastify/basic-auth'), { validate: validateBasic }) await fastify.register(require('@fastify/bearer-auth'), { keys: ['secret-token'] }) fastify.after(() => { // Route 1: Basic auth only fastify.get('/basic-only', { onRequest: fastify.auth([fastify.basicAuth]), handler: (req, reply) => ({ method: 'basic' }) }) // Route 2: Bearer auth only fastify.get('/bearer-only', { onRequest: fastify.auth([fastify.bearerAuth]), handler: (req, reply) => ({ method: 'bearer' }) }) // Route 3: Either basic or bearer fastify.get('/either', { onRequest: fastify.auth([fastify.basicAuth, fastify.bearerAuth]), handler: (req, reply) => ({ authenticated: true }) }) }) ``` -------------------------------- ### Dynamic Realm Configuration Source: https://github.com/fastify/fastify-basic-auth/blob/main/_autodocs/api-reference/usage-examples.md Configure a dynamic realm based on the incoming request's hostname. This allows for different authentication realms for different subdomains or API endpoints. ```javascript const fastify = require('fastify')() await fastify.register(require('@fastify/basic-auth'), { validate: async (username, password) => { if (username === 'user' && password === 'pass') { return } throw new Error('Invalid credentials') }, authenticate: { realm: (req) => { // Return different realm based on request if (req.hostname === 'api.example.com') { return 'API Server' } else if (req.hostname === 'admin.example.com') { return 'Admin Panel' } return 'Protected Area' } } }) ``` -------------------------------- ### Hook Handler Usage Source: https://github.com/fastify/fastify-basic-auth/blob/main/_autodocs/quick-reference.md Utilize the `fastify.basicAuth` hook handler within your Fastify routes or globally. ```APIDOC fastify.basicAuth(req, reply, next) // Use as: // - fastify.addHook('onRequest', fastify.basicAuth) // - fastify.route({ onRequest: fastify.basicAuth, ... }) // - fastify.auth([fastify.basicAuth]) ```