fastify-basic-auth
Advanced tools
Comparing version 2.2.0 to 2.3.0
81
index.js
'use strict' | ||
const fp = require('fastify-plugin') | ||
const auth = require('basic-auth') | ||
const { Unauthorized } = require('http-errors') | ||
const warning = require('process-warning')() | ||
warning.create('FastifyWarning.fastify-basic-auth', 'FST_MODULE_DEP_fastify-basic-auth'.toUpperCase(), 'fastify-basic-auth has been deprecated. Use @fastify/basic-auth@3.0.0 instead.') | ||
warning.emit('FST_MODULE_DEP_fastify-basic-auth'.toUpperCase()) | ||
async function basicPlugin (fastify, opts) { | ||
if (typeof opts.validate !== 'function') { | ||
throw new Error('Basic Auth: Missing validate function') | ||
} | ||
const authenticateHeader = getAuthenticateHeader(opts.authenticate) | ||
const header = (opts.header && opts.header.toLowerCase()) || 'authorization' | ||
const validate = opts.validate.bind(fastify) | ||
fastify.decorate('basicAuth', basicAuth) | ||
function basicAuth (req, reply, next) { | ||
const credentials = auth.parse(req.headers[header]) | ||
if (credentials == null) { | ||
done(new Unauthorized('Missing or bad formatted authorization header')) | ||
} else { | ||
const result = validate(credentials.name, credentials.pass, req, reply, done) | ||
if (result && typeof result.then === 'function') { | ||
result.then(done, done) | ||
} | ||
} | ||
function done (err) { | ||
if (err !== undefined) { | ||
// We set the status code to be 401 if it is not set | ||
if (!err.statusCode) { | ||
err.statusCode = 401 | ||
} | ||
if (err.statusCode === 401) { | ||
switch (typeof authenticateHeader) { | ||
case 'string': | ||
reply.header('WWW-Authenticate', authenticateHeader) | ||
break | ||
case 'function': | ||
reply.header('WWW-Authenticate', authenticateHeader(req)) | ||
break | ||
} | ||
} | ||
next(err) | ||
} else { | ||
next() | ||
} | ||
} | ||
} | ||
} | ||
function getAuthenticateHeader (authenticate) { | ||
if (!authenticate) return false | ||
if (authenticate === true) { | ||
return 'Basic' | ||
} | ||
if (typeof authenticate === 'object') { | ||
const realm = authenticate.realm | ||
switch (typeof realm) { | ||
case 'undefined': | ||
return 'Basic' | ||
case 'boolean': | ||
return 'Basic' | ||
case 'string': | ||
return `Basic realm="${realm}"` | ||
case 'function': | ||
return function (req) { | ||
return `Basic realm="${realm(req)}"` | ||
} | ||
} | ||
} | ||
throw new Error('Basic Auth: Invalid authenticate option') | ||
} | ||
module.exports = fp(basicPlugin, { | ||
fastify: '3.x', | ||
name: 'fastify-basic-auth' | ||
}) | ||
module.exports = require('fastify-basic-auth-deprecated') |
{ | ||
"name": "fastify-basic-auth", | ||
"version": "2.2.0", | ||
"description": "Fastify basic auth plugin", | ||
"version": "2.3.0", | ||
"main": "index.js", | ||
"types": "index.d.ts", | ||
"scripts": { | ||
"test": "standard && tap test.js && tsd" | ||
}, | ||
"license": "MIT", | ||
"repository": { | ||
"type": "git", | ||
"url": "git+https://github.com/fastify/fastify-basic-auth.git" | ||
"url": "git://github.com/fastify/fastify-basic-auth.git" | ||
}, | ||
"keywords": [ | ||
"fastify", | ||
"basic", | ||
"auth", | ||
"authentication", | ||
"plugin" | ||
], | ||
"author": "Tomas Della Vedova - @delvedor (http://delved.org)", | ||
"license": "MIT", | ||
"bugs": { | ||
"url": "https://github.com/fastify/fastify-basic-auth/issues" | ||
}, | ||
"homepage": "https://github.com/fastify/fastify-basic-auth#readme", | ||
"devDependencies": { | ||
"@types/node": "^16.0.0", | ||
"fastify": "^3.0.0", | ||
"fastify-auth": "^1.0.0", | ||
"standard": "^16.0.1", | ||
"tap": "^15.0.2", | ||
"tsd": "^0.17.0" | ||
}, | ||
"homepage": "https://github.com/fastify/fastify-basic-auth", | ||
"dependencies": { | ||
"basic-auth": "^2.0.1", | ||
"fastify-plugin": "^3.0.0", | ||
"http-errors": "^1.7.3" | ||
}, | ||
"engines": { | ||
"node": ">=10.0.0" | ||
"process-warning": "^1.0.0", | ||
"fastify-basic-auth-deprecated": "npm:fastify-basic-auth@2.2.0" | ||
} | ||
} |
196
README.md
# fastify-basic-auth | ||
![CI](https://github.com/fastify/fastify-basic-auth/workflows/CI/badge.svg?branch=master) | ||
[![NPM version](https://img.shields.io/npm/v/fastify-basic-auth.svg?style=flat)](https://www.npmjs.com/package/fastify-basic-auth) | ||
[![Known Vulnerabilities](https://snyk.io/test/github/fastify/fastify-basic-auth/badge.svg)](https://snyk.io/test/github/fastify/fastify-basic-auth) | ||
[![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat)](https://standardjs.com/) | ||
A simple basic auth plugin for Fastify. | ||
## Install | ||
``` | ||
npm i fastify-basic-auth | ||
``` | ||
## Usage | ||
This plugin decorates the fastify instance with a `basicAuth` function, which you can use inside any hook before your route handler, or with [`fastify-auth`](https://github.com/fastify/fastify-auth). | ||
```js | ||
const fastify = require('fastify')() | ||
const authenticate = {realm: 'Westeros'} | ||
fastify.register(require('fastify-basic-auth'), { validate, authenticate }) | ||
// `this` inside validate is `fastify` | ||
function validate (username, password, req, reply, done) { | ||
if (username === 'Tyrion' && password === 'wine') { | ||
done() | ||
} else { | ||
done(new Error('Winter is coming')) | ||
} | ||
} | ||
fastify.after(() => { | ||
fastify.addHook('onRequest', fastify.basicAuth) | ||
fastify.get('/', (req, reply) => { | ||
reply.send({ hello: 'world' }) | ||
}) | ||
}) | ||
``` | ||
Promises and *async/await* are supported as well! | ||
```js | ||
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') | ||
} | ||
} | ||
``` | ||
Use with `onRequest`: | ||
```js | ||
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') | ||
} | ||
} | ||
fastify.after(() => { | ||
fastify.route({ | ||
method: 'GET', | ||
url: '/', | ||
onRequest: fastify.basicAuth, | ||
handler: async (req, reply) => { | ||
return { hello: 'world' } | ||
} | ||
}) | ||
}) | ||
``` | ||
Use with [`fastify-auth`](https://github.com/fastify/fastify-auth): | ||
```js | ||
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 error handler | ||
On failed authentication, *fastify-basic-auth* will call the Fastify | ||
[generic error | ||
handler](https://www.fastify.io/docs/latest/Server/#seterrorhandler) with an error. | ||
*fastify-basic-auth* sets the `err.statusCode` property to `401`. | ||
In order to properly `401` errors: | ||
```js | ||
fastify.setErrorHandler(function (err, req, reply) { | ||
if (err.statusCode === 401) { | ||
// this was unauthorized! Display the correct page/message. | ||
reply.code(401).send({ was: 'unauthorized' }) | ||
return | ||
} | ||
reply.send(err) | ||
}) | ||
``` | ||
## Options | ||
### `validate` <Function> (required) | ||
The `validate` function is called on each request made, | ||
and is passed the `username`, `password`, `req` and `reply` | ||
parameters in that order. An optional fifth parameter, `done` may be | ||
used to signify a valid request when called with no arguments, | ||
or an invalid request when called with an `Error` object. Alternatively, | ||
the `validate` function may return a promise, resolving for valid | ||
requests and rejecting for invalid. This can also be achieved using | ||
an `async/await` function, and throwing for invalid requests. | ||
See code above for examples. | ||
### `authenticate` <Boolean|Object> (optional, default: false) | ||
When supplied, the `authenticate` option will cause the | ||
[`WWW-Authenticate` header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/WWW-Authenticate) to be added. It may also be used to set the `realm` value. | ||
This can be useful in situations where we want to trigger client-side authentication interfaces - for instance the browser authentication dialog. | ||
As a boolean setting `authenticate` to `true` will set a header like so: `WWW-Authenticate: Basic`. When `false`, no header is added. This is the default. | ||
```js | ||
fastify.register(require('fastify-basic-auth'), { | ||
validate, | ||
authenticate: true // WWW-Authenticate: Basic | ||
}) | ||
fastify.register(require('fastify-basic-auth'), { | ||
validate, | ||
authenticate: false // no authenticate header, same as omitting authenticate option | ||
}) | ||
``` | ||
When supplied as an object the `authenticate` option may have a `realm` key. | ||
If the `realm` key is supplied, it will be appended to the header value: | ||
```js | ||
fastify.register(require('fastify-basic-auth'), { | ||
validate, | ||
authenticate: {realm: 'example'} // WWW-Authenticate: Basic realm="example" | ||
}) | ||
``` | ||
The `realm` key could also be a function: | ||
```js | ||
fastify.register(require('fastify-basic-auth'), { | ||
validate, | ||
authenticate: { | ||
realm(req) { | ||
return 'example' // WWW-Authenticate: Basic realm="example" | ||
} | ||
} | ||
}) | ||
``` | ||
### `header` String (optional) | ||
When supplied, the header option is the name of the header to get | ||
credentials from for validation. | ||
```js | ||
fastify.register(require('fastify-basic-auth'), { | ||
validate, | ||
header: 'x-forwarded-authorization' | ||
}) | ||
``` | ||
## License | ||
Licensed under [MIT](./LICENSE). | ||
`fastify-basic-auth@2.3.0` has been deprecated. Please use | ||
`@fastify/basic-auth@3.0.0` instead. |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Deprecated
MaintenanceThe maintainer of the package marked it as deprecated. This could indicate that a single version should not be used, or that the package is no longer maintained and any new vulnerabilities will not be fixed.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
Trivial Package
Supply chain riskPackages less than 10 lines of code are easily copied into your own project and may not warrant the additional supply chain risk of an external dependency.
Found 1 instance in 1 package
No contributors or author data
MaintenancePackage does not specify a list of contributors or an author in package.json.
Found 1 instance in 1 package
No bug tracker
MaintenancePackage does not have a linked bug tracker in package.json.
Found 1 instance in 1 package
No repository
Supply chain riskPackage does not have a linked source code repository. Without this field, a package will have no reference to the location of the source code use to generate the package.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
2
0
857
3
5
2
1
5
1
3
+ Addedfastify-basic-auth-deprecated@npm:fastify-basic-auth@2.2.0
+ Addedprocess-warning@^1.0.0
+ Addedfastify-basic-auth@2.2.0(transitive)
+ Addedprocess-warning@1.0.0(transitive)
- Removedbasic-auth@^2.0.1
- Removedfastify-plugin@^3.0.0
- Removedhttp-errors@^1.7.3