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
						
					
					
				| # 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).
 |