diff options
author | Eugene Sokolov <eug-vs@keemail.me> | 2020-07-05 13:38:33 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-07-05 13:38:33 +0300 |
commit | 96398e544463651413ea80821c09ae7573f46cb1 (patch) | |
tree | df77b6f65247d87dbfde8000e918c83985624fc3 | |
parent | da76bb1bd8797c4e1dc657c489f597bf64918ceb (diff) | |
parent | 1c2f3c9e5b39826266d64f4227e53fff139ea948 (diff) | |
download | which-api-96398e544463651413ea80821c09ae7573f46cb1.tar.gz |
Merge pull request #17 from which-ecosystem/security
Prepare release-level backend security
-rw-r--r-- | config/default.json | 3 | ||||
-rw-r--r-- | hooks/tryAuthenticate.ts | 5 | ||||
-rw-r--r-- | populateDb.ts | 11 | ||||
-rw-r--r-- | services/feedback/feedback.hooks.ts | 23 | ||||
-rw-r--r-- | services/polls/polls.hooks.ts | 6 | ||||
-rw-r--r-- | services/users/users.hooks.ts | 16 | ||||
-rw-r--r-- | services/votes/votes.hooks.ts | 6 |
7 files changed, 57 insertions, 13 deletions
diff --git a/config/default.json b/config/default.json index 278b076..7d1ef26 100644 --- a/config/default.json +++ b/config/default.json @@ -10,6 +10,9 @@ "local": { "usernameField": "\\username", "passwordField": "password" + }, + "jwtOptions": { + "expiresIn": "10 days" } } } diff --git a/hooks/tryAuthenticate.ts b/hooks/tryAuthenticate.ts index e179417..71306ba 100644 --- a/hooks/tryAuthenticate.ts +++ b/hooks/tryAuthenticate.ts @@ -3,6 +3,9 @@ import { authenticate } from '@feathersjs/authentication'; export default async (context: HookContext): Promise<HookContext> => { - return authenticate('jwt')(context).catch(() => context); + if (context.params?.headers?.authorization && context.path !== 'authentication') { + return authenticate('jwt')(context); + } + return context; }; diff --git a/populateDb.ts b/populateDb.ts index e25005d..1565f44 100644 --- a/populateDb.ts +++ b/populateDb.ts @@ -56,9 +56,8 @@ const createPoll = (authorId: string): Promise<Poll> => { contents: { left: generateImageData(), right: generateImageData() - }, - authorId - }); + } + }, { user: { _id: authorId }, authenticated: true }); }; const createUser = (username: string): Promise<User> => { @@ -69,18 +68,18 @@ const createUser = (username: string): Promise<User> => { }); }; -const createVote = (userId: string, pollId: string): Promise<Vote> => { +const createVote = (authorId: string, pollId: string): Promise<Vote> => { return app.service('votes').create({ pollId, which: _.sample(choices) - }, { user: { _id: userId }, authenticated: true }); + }, { user: { _id: authorId }, authenticated: true }); }; const createFeedback = (userId: string): Promise<Feedback> => { return app.service('feedback').create({ version: 'v1.0.0', score: _.sample([1, 2, 3, 4, 5]), - content: 'Absolutely amazing!' + contents: 'Absolutely amazing!' }, { user: { _id: userId }, authenticated: true }); }; diff --git a/services/feedback/feedback.hooks.ts b/services/feedback/feedback.hooks.ts index 56e9000..5bc2552 100644 --- a/services/feedback/feedback.hooks.ts +++ b/services/feedback/feedback.hooks.ts @@ -1,9 +1,30 @@ +import { populate, discard, disallow } from 'feathers-hooks-common'; import requireAuth from '../../hooks/requireAuth'; import signAuthority from '../../hooks/signAuthority'; +import sortByDate from '../../hooks/sortByDate'; + + +const populateAuthor = populate({ + schema: { + include: { + service: 'users', + nameAs: 'author', + parentField: 'authorId', + childField: '_id' + } + } +}); export default { before: { - create: [requireAuth, signAuthority] + create: [requireAuth, signAuthority], + find: sortByDate, + remove: disallow('external'), + patch: disallow('external'), + update: disallow('external') + }, + after: { + all: [populateAuthor, discard('authorId')] } }; diff --git a/services/polls/polls.hooks.ts b/services/polls/polls.hooks.ts index e3d04e7..35eae29 100644 --- a/services/polls/polls.hooks.ts +++ b/services/polls/polls.hooks.ts @@ -1,4 +1,5 @@ import { HookContext } from '@feathersjs/feathers'; +import { disallow } from 'feathers-hooks-common'; import { Types } from 'mongoose'; import bluebird from 'bluebird'; import _ from 'lodash'; import { Poll } from 'which-types'; @@ -46,7 +47,10 @@ const convertPoll = async (context: HookContext): Promise<HookContext> => { export default { before: { find: sortByDate, - create: signAuthority + create: signAuthority, + remove: disallow('external'), + update: disallow('external'), + patch: disallow('external') }, after: { all: convertPoll diff --git a/services/users/users.hooks.ts b/services/users/users.hooks.ts index 48843be..125f418 100644 --- a/services/users/users.hooks.ts +++ b/services/users/users.hooks.ts @@ -1,7 +1,9 @@ import _ from 'lodash'; import { hooks } from '@feathersjs/authentication-local'; -import { discard } from 'feathers-hooks-common'; +import { discard, disallow } from 'feathers-hooks-common'; import { HookContext } from '@feathersjs/feathers'; +import { NotAuthenticated } from '@feathersjs/errors'; +import requireAuth from '../../hooks/requireAuth'; const hashPassword = hooks.hashPassword('password'); @@ -12,6 +14,13 @@ const ignoreCaseRegex = async (context: HookContext): Promise<HookContext> => { return context; }; +const compareUser = async (context: HookContext): Promise<HookContext> => { + if (context.arguments[0] !== context.params.user._id) { + throw new NotAuthenticated('You can only PATCH/UPDATE your own user!'); + } + return context; +}; + export default { after: { all: hooks.protect('password'), @@ -20,8 +29,9 @@ export default { before: { find: ignoreCaseRegex, create: hashPassword, - patch: hashPassword, - update: hashPassword + patch: [hashPassword, requireAuth, compareUser], + update: [hashPassword, requireAuth, compareUser], + remove: disallow('external') } }; diff --git a/services/votes/votes.hooks.ts b/services/votes/votes.hooks.ts index 56e9000..923e897 100644 --- a/services/votes/votes.hooks.ts +++ b/services/votes/votes.hooks.ts @@ -1,9 +1,13 @@ +import { disallow } from 'feathers-hooks-common'; import requireAuth from '../../hooks/requireAuth'; import signAuthority from '../../hooks/signAuthority'; export default { before: { - create: [requireAuth, signAuthority] + create: [requireAuth, signAuthority], + remove: disallow('external'), + update: disallow('external'), + patch: disallow('external') } }; |