You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					159 lines
				
				5.8 KiB
			
		
		
			
		
	
	
					159 lines
				
				5.8 KiB
			| 
											3 years ago
										 | # fastify-auth
 | ||
|  | 
 | ||
|  |  | ||
|  | [](https://www.npmjs.com/package/fastify-auth) | ||
|  | [](https://snyk.io/test/github/fastify/fastify-auth) | ||
|  | [](https://coveralls.io/github/fastify/fastify-auth?branch=master) | ||
|  | [](https://standardjs.com/) | ||
|  | 
 | ||
|  | This module does not provide an authentication strategy, but it provides a very fast utility to handle authentication (also multiple strategies) in your routes, without adding overhead.   | ||
|  | Check out the complete example [here](https://github.com/fastify/fastify-auth/blob/master/example.js). | ||
|  | 
 | ||
|  | ## Install
 | ||
|  | ``` | ||
|  | npm i fastify-auth | ||
|  | ``` | ||
|  | 
 | ||
|  | ## Usage
 | ||
|  | As said above, `fastify-auth` does not provide an authentication strategy, so you must provide authentication by yourself, with a decorator or another plugin. | ||
|  | 
 | ||
|  | In the following example, you will find a very simple implementation that should help you understand how to use this module: | ||
|  | ```js | ||
|  | fastify | ||
|  |   .decorate('verifyJWTandLevel', function (request, reply, done) { | ||
|  |     // your validation logic | ||
|  |     done() // pass an error if the authentication fails | ||
|  |   }) | ||
|  |   .decorate('verifyUserAndPassword', function (request, reply, done) { | ||
|  |     // your validation logic | ||
|  |     done() // pass an error if the authentication fails | ||
|  |   }) | ||
|  |   .register(require('fastify-auth')) | ||
|  |   .after(() => { | ||
|  |     fastify.route({ | ||
|  |       method: 'POST', | ||
|  |       url: '/auth-multiple', | ||
|  |       preHandler: fastify.auth([ | ||
|  |         fastify.verifyJWTandLevel, | ||
|  |         fastify.verifyUserAndPassword | ||
|  |       ]), | ||
|  |       handler: (req, reply) => { | ||
|  |         req.log.info('Auth route') | ||
|  |         reply.send({ hello: 'world' }) | ||
|  |       } | ||
|  |     }) | ||
|  |   }) | ||
|  | ``` | ||
|  | 
 | ||
|  | The default relationship of these customized authentication is `or`, while we could also use `and`: | ||
|  | ```js | ||
|  | fastify | ||
|  |   .decorate('verifyAdmin', function (request, reply, done) { | ||
|  |     // your validation logic | ||
|  |     done() // pass an error if the authentication fails | ||
|  |   }) | ||
|  |   .decorate('verifyReputation', function (request, reply, done) { | ||
|  |     // your validation logic | ||
|  |     done() // pass an error if the authentication fails | ||
|  |   }) | ||
|  |   .register(require('fastify-auth')) | ||
|  |   .after(() => { | ||
|  |     fastify.route({ | ||
|  |       method: 'POST', | ||
|  |       url: '/auth-multiple', | ||
|  |       preHandler: fastify.auth([ | ||
|  |         fastify.verifyAdmin, | ||
|  |         fastify.verifyReputation | ||
|  |       ], { | ||
|  |         relation: 'and' | ||
|  |       }), | ||
|  |       handler: (req, reply) => { | ||
|  |         req.log.info('Auth route') | ||
|  |         reply.send({ hello: 'world' }) | ||
|  |       } | ||
|  |     }) | ||
|  |   }) | ||
|  | ``` | ||
|  | _For more examples, please check `example-composited.js`_ | ||
|  | 
 | ||
|  | This plugin support `callback` and `Promise` returned by the functions. Note that an `async` function does not have to use the `done` parameter: | ||
|  | ```js | ||
|  | fastify | ||
|  |   .decorate('asyncVerifyJWTandLevel', async function (request, reply) { | ||
|  |     // your async validation logic | ||
|  |     await validation() | ||
|  |     // throws an error if the authentication fails | ||
|  |   }) | ||
|  |   .decorate('asyncVerifyUserAndPassword', function (request, reply) { | ||
|  |     // return a promise that throws an error if the authentication fails | ||
|  |     return myPromiseValidation() | ||
|  |   }) | ||
|  |   .register(require('fastify-auth')) | ||
|  |   .after(() => { | ||
|  |     fastify.route({ | ||
|  |       method: 'POST', | ||
|  |       url: '/auth-multiple', | ||
|  |       preHandler: fastify.auth([ | ||
|  |         fastify.asyncVerifyJWTandLevel, | ||
|  |         fastify.asyncVerifyUserAndPassword | ||
|  |       ]), | ||
|  |       handler: (req, reply) => { | ||
|  |         req.log.info('Auth route') | ||
|  |         reply.send({ hello: 'world' }) | ||
|  |       } | ||
|  |     }) | ||
|  |   }) | ||
|  | ``` | ||
|  | 
 | ||
|  | 
 | ||
|  | Keep in mind that route definition should either be done as [a plugin](https://github.com/fastify/fastify/blob/master/docs/Plugins.md) or within `.after()` callback. | ||
|  | For a complete example implementation, see [example.js](example.js). | ||
|  | 
 | ||
|  | `fastify-auth` will run all your authentication methods and your request will continue if at least one succeeds, otherwise it will return an error to the client. | ||
|  | Any successful authentication will automatically stop `fastify-auth` from trying the rest, unless you provide the `run: 'all'` parameter: | ||
|  | ```js | ||
|  | fastify.route({ | ||
|  |   method: 'GET', | ||
|  |   url: '/run-all', | ||
|  |   preHandler: fastify.auth([ | ||
|  |     (request, reply, done) => { console.log('executed 1'); done() }, | ||
|  |     (request, reply, done) => { console.log('executed 2'); done() }, | ||
|  |     (request, reply, done) => { console.log('executed 3'); done(new Error('you are not authenticated')) }, | ||
|  |     (request, reply, done) => { console.log('executed 4'); done() }, | ||
|  |     (request, reply, done) => { console.log('executed 5'); done(new Error('you shall not pass')) } | ||
|  |   ], { run: 'all' }), | ||
|  |   handler: (req, reply) => { reply.send({ hello: 'world' }) } | ||
|  | }) | ||
|  | ``` | ||
|  | This example will show all the console logs and will reply always with `401: you are not authenticated`. | ||
|  | The `run` parameter is useful if you are adding to the request business data read from auth-tokens. | ||
|  | 
 | ||
|  | 
 | ||
|  | You can use this plugin on route level, as in the above example or on hook level, by using the `preHandler` hook: | ||
|  | ```js | ||
|  | fastify.addHook('preHandler', fastify.auth([ | ||
|  |   fastify.verifyJWTandLevel, | ||
|  |   fastify.verifyUserAndPassword | ||
|  | ])) | ||
|  | 
 | ||
|  | fastify.route({ | ||
|  |   method: 'POST', | ||
|  |   url: '/auth-multiple', | ||
|  |   handler: (req, reply) => { | ||
|  |     req.log.info('Auth route') | ||
|  |     reply.send({ hello: 'world' }) | ||
|  |   } | ||
|  | }) | ||
|  | ``` | ||
|  | 
 | ||
|  | The difference between the two approaches is that if you use the route level `preHandler` function the authentication will run just for the selected route. Whereas if you use the `preHandler` hook the authentication will run for all the routes declared inside the current plugin (and its descendants). | ||
|  | 
 | ||
|  | ## Acknowledgements
 | ||
|  | 
 | ||
|  | This project is kindly sponsored by: | ||
|  | - [LetzDoIt](https://www.letzdoitapp.com/) | ||
|  | 
 | ||
|  | ## License
 | ||
|  | 
 | ||
|  | Licensed under [MIT](./LICENSE). |