feathers-authentication-hooks
Important: The
setField
hook from this repository has moved to feathers-hooks-common. Also see the documentation
A hook that helps limiting and associating user requests
$ npm install feathers-authentication-hooks --save
feathers-authentication-hooks
contains a Feathers hook that allows to set query or data properties based on other existing properties (like an authenticated user or organization id).
Note:
feathers-authentication-hooks
v1.0.0 and later requires Feathers 4 or later.
setField
The setField
hook allows to set a field on the hook context based on the value of another field on the hook context.
Options
from
required - The property on the hook context to use. Can be an array (e.g.[ 'params', 'user', 'id' ]
) or a dot separated string (e.g.'params.user.id'
).as
required - The property on the hook context to set. Can be an array (e.g.[ 'params', 'query', 'userId' ]
) or a dot separated string (e.g.'params.query.userId'
).allowUndefined
(default:false
) - If set tofalse
, an error will be thrown if the value offrom
isundefined
in an external request (params.provider
is set). On internal calls (or if set to truetrue
for external calls) the hook will do nothing.
Important: This hook should be used after the authenticate hook when accessing user fields (from
params.user
).
Examples
Limit all external access of the users
service to the authenticated user:
Note: For MongoDB, Mongoose and NeDB
params.user.id
needs to be changed toparams.user._id
. For any other custom id accordingly.
const { authenticate } = require('@feathersjs/authentication');
const { setField } = require('feathers-authentication-hooks');
app.service('users').hooks({
before: {
all: [
authenticate('jwt'),
setField({
from: 'params.user.id',
as: 'params.query.id'
})
]
}
})
Only allow access to invoices for the users organization:
const { authenticate } = require('@feathersjs/authentication');
const { setField } = require('feathers-authentication-hooks');
app.service('invoices').hooks({
before: {
all: [
authenticate('jwt'),
setField({
from: 'params.user.organizationId',
as: 'params.query.organizationId'
})
]
}
})
Set the current user id as userId
when creating a message and only allow users to edit and remove their own messages:
const { authenticate } = require('@feathersjs/authentication');
const { setField } = require('feathers-authentication-hooks');
const setUserId = setField({
from: 'params.user.id',
as: 'data.userId'
});
const limitToUser = setField({
from: 'params.user.id',
as: 'params.query.userId'
});
app.service('messages').hooks({
before: {
all: [
authenticate('jwt')
],
create: [
setUserId
],
patch: [
limitToUser
],
update: [
limitToUser
]
remove: [
limitToUser
]
}
})
Migrating to v1.0.0
The previous versions of feathers-authentication-hooks
contained several hooks that required more detailed configuration and knowledge about the application and authentication. Due to improvements in the database adapters in Feathers 4 those hooks can now all be replaced with the setField
hook and a more explicit configuration.
queryWithCurrentUser
Before:
const hooks = require('feathers-authentication-hooks');
app.service('messages').before({
find: [
hooks.queryWithCurrentUser({ idField: 'id', as: 'sentBy' })
]
});
Now:
const { setField } = require('feathers-authentication-hooks');
app.service('messages').before({
find: [
setField({
from: 'params.user.id',
as: 'params.query.sentBy'
})
]
});
Dot separated paths in queries (previously with the expandPaths
option) are possible by passing an array as the field name (using Lodash _.set internally):
const { setField } = require('feathers-authentication-hooks');
app.service('messages').before({
find: [
setField({
from: 'params.user.id',
as: [ 'params', 'query', 'nested.document.sentBy' ]
})
]
});
restrictToOwner
Due to improvements in the Feathers 4 database adapters restricting to an owner works the exact same as a queryWithCurrentUser
. It will now throw a NotFound
instead of a Forbidden
error which is also more secure since an unauthorized user does not get the information if the record exists and no longer make an additional request.
Before:
const hooks = require('feathers-authentication-hooks');
app.service('messages').before({
remove: [
hooks.restrictToOwner({ idField: 'id', ownerField: 'sentBy' })
]
});
Now:
const { setField } = require('feathers-authentication-hooks');
app.service('messages').before({
remove: [
setField({
from: 'params.user.id',
as: 'params.query.userId'
})
]
});
associateCurrentUser
The associateCurrentUser
can also be replaced by setField
by setting data
instead of params.query.*
Before:
const hooks = require('feathers-authentication-hooks');
app.service('messages').before({
create: [
hooks.associateCurrentUser({ idField: 'id', as: 'sentBy' })
]
});
Now:
const { setField } = require('feathers-authentication-hooks');
app.service('messages').before({
create: [
setField({
from: 'params.user.id',
as: 'data.sentBy'
})
]
});
License
Copyright (c) 2019
Licensed under the MIT license.