/// import { Request, RequestHandler } from 'express' /** * This is the middleware builder. * * Example: * const users = { alice: '1234', bob: 'correcthorsebatterystaple' } * app.use(basicAuth({ users, challenge: true }), myHandler) * * @param options The middleware's options (at least 'users' or 'authorizer' are mandatory). */ declare function expressBasicAuth(options: expressBasicAuth.BasicAuthMiddlewareOptions): RequestHandler declare namespace expressBasicAuth { /** * Time safe string comparison function to protect against timing attacks. * * It is important to provide the arguments in the correct order, as the runtime * depends only on the `userInput` argument. Switching the order would expose the `secret` * to timing attacks. * * @param userInput The user input to be compared * @param secret The secret value the user input should be compared with * * @returns true if `userInput` matches `secret`, false if not */ export function safeCompare(userInput: string, secret: string): boolean /** * The configuration you pass to the middleware can take three forms, either: * - A map of static users ({ bob: 'pa$$w0rd', ... }) ; * - An authorizer function * - An asynchronous authorizer function */ export type BasicAuthMiddlewareOptions = IUsersOptions | (IAuthorizerOptions | IAsyncAuthorizerOptions) /** * express-basic-auth patches the request object to set an `auth` property that lets you retrieve the authed user. * * Example (TypeScript): * app.use(basicAuth({ ... }), (req: basicAuth.IBasicAuthedRequest, res, next) => { * res.end(`Welcome ${req.auth.user} (your password is ${req.auth.password})`) * next() * }) */ export interface IBasicAuthedRequest extends Request { auth: { user: string, password: string } } type Authorizer = (username: string, password: string) => boolean type AsyncAuthorizerCallback = (err: any, authed?: boolean) => void type AsyncAuthorizer = (username: string, password: string, callback: AsyncAuthorizerCallback) => void type ValueOrFunction = T | ((req: IBasicAuthedRequest) => T) interface IBaseOptions { /** * Per default the middleware will not add a WWW-Authenticate challenge header to responses of unauthorized requests. * You can enable that by setting this to true, causing most browsers to show a popup to enter credentials * on unauthorized responses. * * @default false */ challenge?: boolean /** * You can set the realm (the realm identifies the system to authenticate against and can be used by clients to * save credentials) of the challenge by passing a string or a function that gets passed the request and is * expected to return the realm. * * @default undefined */ realm?: ValueOrFunction /** * Per default, the response body for unauthorized responses will be empty. * It can be configured using the unauthorizedResponse option. You can either pass a static response or a * function that gets passed the express request object and is expected to return the response body. * If the response body is a string, it will be used as-is, otherwise it will be sent as JSON. * * @default '' */ unauthorizedResponse?: ValueOrFunction } interface IUsersOptions extends IBaseOptions { /** * If you simply want to check basic auth against one or multiple static credentials, you can pass those * credentials in the users option. * * Example: * const users = { alice: '1234', bob: 'correcthorsebatterystaple' } * app.use(basicAuth({ users, challenge: true }), myHandler) */ users: { [username: string]: string } } interface IAuthorizerOptions extends IBaseOptions { /** * Set to true if your authorizer is asynchronous. */ authorizeAsync?: false /** * You can pass your own authorizer function, to check the credentials however you want. * It will be called with a username and password and is expected to return true or false to indicate that the * credentials were approved or not: * * Example: * app.use(basicAuth({ authorizer })) * * function myAuthorizer(username: string, password: string) { * return username.startsWith('A') && password.startsWith('secret'); * } * * This will authorize all requests with credentials where the username begins with 'A' and the password begins * with 'secret'. In an actual application you would likely look up some data instead ;-) */ authorizer: Authorizer } interface IAsyncAuthorizerOptions extends IBaseOptions { /** * Set it to true to use a asynchronous authorizer. */ authorizeAsync: true /** * You can pass an asynchronous authorizer. It will be passed a callback as the third parameter, which is * expected to be called by standard node convention with an error and a boolean to indicate if the credentials * have been approved or not. * * Example: * app.use(basicAuth({ authorizer, authorizeAsync: true })); * * function authorizer(username, password, authorize) { * if(username.startsWith('A') && password.startsWith('secret')) * return authorize(null, true) * * return authorize(null, false) * } */ authorizer: AsyncAuthorizer } } export = expressBasicAuth