diff options
| -rw-r--r-- | config/default.json | 18 | ||||
| -rw-r--r-- | package-lock.json | 167 | ||||
| -rw-r--r-- | package.json | 2 | ||||
| -rw-r--r-- | src/app.js | 2 | ||||
| -rw-r--r-- | src/services/auth/auth.service.js | 22 | ||||
| -rw-r--r-- | src/services/index.js | 2 | ||||
| -rw-r--r-- | src/services/users/user.hooks.js | 21 | ||||
| -rw-r--r-- | src/services/users/user.service.js | 6 | 
8 files changed, 239 insertions, 1 deletions
| diff --git a/config/default.json b/config/default.json new file mode 100644 index 0000000..ddc720f --- /dev/null +++ b/config/default.json @@ -0,0 +1,18 @@ +{ +  "authentication": { +    "secret": "2JtbBy2ycQ1V3kQfPcSgXYmFsB7", +    "service": "users", +    "entity": "user", +    "authStrategies": [ +      "jwt", +      "local" +    ], +    "local": { +      "usernameField": "\\username", +      "passwordField": "password" +    }, +    "jwtOptions": { +      "expiresIn": "30 days" +    } +  } +} diff --git a/package-lock.json b/package-lock.json index bde86c1..42c907a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,11 +14,50 @@          "@feathersjs/feathers": "^4.5.8"        }      }, +    "@feathersjs/authentication": { +      "version": "4.5.10", +      "resolved": "https://registry.npmjs.org/@feathersjs/authentication/-/authentication-4.5.10.tgz", +      "integrity": "sha512-4YfgDfP2GzzW2D76KA5CyHqgCDCJIzZKHKKv55FxgSLs/vOKfufkCMVreOanoRN9eul3Fj6TCbrPT6+QUc+XkQ==", +      "requires": { +        "@feathersjs/errors": "^4.5.10", +        "@feathersjs/feathers": "^4.5.10", +        "@feathersjs/transport-commons": "^4.5.10", +        "@types/jsonwebtoken": "^8.5.0", +        "debug": "^4.2.0", +        "jsonwebtoken": "^8.5.1", +        "lodash": "^4.17.20", +        "long-timeout": "^0.1.1", +        "uuid": "^8.3.1" +      } +    }, +    "@feathersjs/authentication-local": { +      "version": "4.5.10", +      "resolved": "https://registry.npmjs.org/@feathersjs/authentication-local/-/authentication-local-4.5.10.tgz", +      "integrity": "sha512-hoZWutBvNxpjMKKh/CZ5lo71cO5z2asad9DnWClnVLnM2DE1o4NjE5+9A0b/NfK+DdXnbXQk0pEYOxrDersM0w==", +      "requires": { +        "@feathersjs/authentication": "^4.5.10", +        "@feathersjs/errors": "^4.5.10", +        "@feathersjs/feathers": "^4.5.10", +        "bcryptjs": "^2.4.3", +        "debug": "^4.2.0", +        "lodash": "^4.17.20" +      } +    },      "@feathersjs/commons": {        "version": "4.5.10",        "resolved": "https://registry.npmjs.org/@feathersjs/commons/-/commons-4.5.10.tgz",        "integrity": "sha512-3d6HaknbSY3fuA+BIrIxQhxGlA7EKCmH4YK3KR+f2cg7vZYHNEl+Cf5XC2fP2V7kWrdVgLy2AeB3t6oxCIFGtQ=="      }, +    "@feathersjs/configuration": { +      "version": "4.5.10", +      "resolved": "https://registry.npmjs.org/@feathersjs/configuration/-/configuration-4.5.10.tgz", +      "integrity": "sha512-afXD1js1NZovMcQnOENOKRuEpg/S6BM8/qRMzOGkOQ4T+aLT8FUN/7JI5osVvrX90gupGXaTzQ1oxJ6ypXpNOA==", +      "requires": { +        "@feathersjs/feathers": "^4.5.10", +        "config": "^3.3.2", +        "debug": "^4.2.0" +      } +    },      "@feathersjs/errors": {        "version": "4.5.10",        "resolved": "https://registry.npmjs.org/@feathersjs/errors/-/errors-4.5.10.tgz", @@ -122,6 +161,14 @@          "@types/range-parser": "*"        }      }, +    "@types/jsonwebtoken": { +      "version": "8.5.0", +      "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-8.5.0.tgz", +      "integrity": "sha512-9bVao7LvyorRGZCw0VmH/dr7Og+NdjYSsKAxB43OQoComFbBgsEpoR9JW6+qSq/ogwVBg8GI2MfAlk4SYI4OLg==", +      "requires": { +        "@types/node": "*" +      } +    },      "@types/mime": {        "version": "2.0.3",        "resolved": "https://registry.npmjs.org/@types/mime/-/mime-2.0.3.tgz", @@ -251,6 +298,11 @@        "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz",        "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog=="      }, +    "bcryptjs": { +      "version": "2.4.3", +      "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz", +      "integrity": "sha1-mrVie5PmBiH/fNrF2pczAn3x0Ms=" +    },      "better-assert": {        "version": "1.0.2",        "resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz", @@ -338,6 +390,11 @@        "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",        "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI="      }, +    "buffer-equal-constant-time": { +      "version": "1.0.1", +      "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", +      "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=" +    },      "bytes": {        "version": "3.1.0",        "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", @@ -373,6 +430,14 @@        "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",        "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="      }, +    "config": { +      "version": "3.3.2", +      "resolved": "https://registry.npmjs.org/config/-/config-3.3.2.tgz", +      "integrity": "sha512-NlGfBn2565YA44Irn7GV5KHlIGC3KJbf0062/zW5ddP9VXIuRj0m7HVyFAWvMZvaHPEglyGfwmevGz3KosIpCg==", +      "requires": { +        "json5": "^2.1.1" +      } +    },      "content-disposition": {        "version": "0.5.3",        "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", @@ -474,6 +539,14 @@        "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.2.0.tgz",        "integrity": "sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw=="      }, +    "ecdsa-sig-formatter": { +      "version": "1.0.11", +      "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", +      "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", +      "requires": { +        "safe-buffer": "^5.0.1" +      } +    },      "ee-first": {        "version": "1.1.1",        "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -844,6 +917,50 @@        "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz",        "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4="      }, +    "json5": { +      "version": "2.1.3", +      "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz", +      "integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==", +      "requires": { +        "minimist": "^1.2.5" +      } +    }, +    "jsonwebtoken": { +      "version": "8.5.1", +      "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz", +      "integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==", +      "requires": { +        "jws": "^3.2.2", +        "lodash.includes": "^4.3.0", +        "lodash.isboolean": "^3.0.3", +        "lodash.isinteger": "^4.0.4", +        "lodash.isnumber": "^3.0.3", +        "lodash.isplainobject": "^4.0.6", +        "lodash.isstring": "^4.0.1", +        "lodash.once": "^4.0.0", +        "ms": "^2.1.1", +        "semver": "^5.6.0" +      } +    }, +    "jwa": { +      "version": "1.4.1", +      "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", +      "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", +      "requires": { +        "buffer-equal-constant-time": "1.0.1", +        "ecdsa-sig-formatter": "1.0.11", +        "safe-buffer": "^5.0.1" +      } +    }, +    "jws": { +      "version": "3.2.2", +      "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", +      "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", +      "requires": { +        "jwa": "^1.4.1", +        "safe-buffer": "^5.0.1" +      } +    },      "kareem": {        "version": "2.3.1",        "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.3.1.tgz", @@ -862,6 +979,46 @@        "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz",        "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA=="      }, +    "lodash.includes": { +      "version": "4.3.0", +      "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", +      "integrity": "sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8=" +    }, +    "lodash.isboolean": { +      "version": "3.0.3", +      "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", +      "integrity": "sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY=" +    }, +    "lodash.isinteger": { +      "version": "4.0.4", +      "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", +      "integrity": "sha1-YZwK89A/iwTDH1iChAt3sRzWg0M=" +    }, +    "lodash.isnumber": { +      "version": "3.0.3", +      "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", +      "integrity": "sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w=" +    }, +    "lodash.isplainobject": { +      "version": "4.0.6", +      "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", +      "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=" +    }, +    "lodash.isstring": { +      "version": "4.0.1", +      "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", +      "integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=" +    }, +    "lodash.once": { +      "version": "4.1.1", +      "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", +      "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=" +    }, +    "long-timeout": { +      "version": "0.1.1", +      "resolved": "https://registry.npmjs.org/long-timeout/-/long-timeout-0.1.1.tgz", +      "integrity": "sha1-lyHXiLR+C8taJMLivuGg2lXatRQ=" +    },      "media-typer": {        "version": "0.3.0",        "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -909,6 +1066,11 @@          "brace-expansion": "^1.1.7"        }      }, +    "minimist": { +      "version": "1.2.5", +      "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", +      "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" +    },      "mkdirp-classic": {        "version": "0.5.3",        "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", @@ -1590,6 +1752,11 @@        "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",        "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM="      }, +    "uuid": { +      "version": "8.3.1", +      "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.1.tgz", +      "integrity": "sha512-FOmRr+FmWEIG8uhZv6C2bTgEVXsHk08kE7mPlrBbEe+c3r9pjceVPgupIfNIhc4yx55H69OXANrUaSuu9eInKg==" +    },      "vary": {        "version": "1.1.2",        "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", diff --git a/package.json b/package.json index ab2c639..5893b20 100644 --- a/package.json +++ b/package.json @@ -7,6 +7,8 @@    },    "author": "eug-vs",    "dependencies": { +    "@feathersjs/authentication-local": "^4.5.10", +    "@feathersjs/configuration": "^4.5.10",      "@feathersjs/express": "^4.5.10",      "@feathersjs/feathers": "^4.5.10",      "@feathersjs/socketio": "^4.5.10", @@ -1,6 +1,7 @@  const feathers = require('@feathersjs/feathers');  const express = require('@feathersjs/express');  const socketio = require('@feathersjs/socketio'); +const configuration = require('@feathersjs/configuration');  const cors = require('cors')  const services = require('./services'); @@ -14,6 +15,7 @@ app.use(express.static(__dirname));  app.use(express.errorHandler());  app.use(cors()); +app.configure(configuration());  app.configure(express.rest());  app.configure(socketio());  app.configure(services); diff --git a/src/services/auth/auth.service.js b/src/services/auth/auth.service.js new file mode 100644 index 0000000..9e92a02 --- /dev/null +++ b/src/services/auth/auth.service.js @@ -0,0 +1,22 @@ +const { AuthenticationService, JWTStrategy } = require('@feathersjs/authentication'); +const { LocalStrategy } = require('@feathersjs/authentication-local'); +const _ = require('lodash'); + +class NoHashingLocalStrategy extends LocalStrategy { +  async comparePassword (entity, password) { +    const { entityPasswordField, errorMessage } = this.configuration; +    const entityPassword = _.get(entity, entityPasswordField); +    if (entityPassword !== password) throw new Error(errorMessage); +    return entity; +  } +} + +module.exports = app => { +  const authentication = new AuthenticationService(app); + +  authentication.register('local', new NoHashingLocalStrategy()); +  authentication.register('jwt', new JWTStrategy()); + +  app.use('/authentication', authentication); +}; + diff --git a/src/services/index.js b/src/services/index.js index f2d65d0..b8ef1db 100644 --- a/src/services/index.js +++ b/src/services/index.js @@ -1,9 +1,11 @@  const Users = require('./users/user.service.js');  const Events = require('./events/event.service.js'); +const Auth = require('./auth/auth.service.js');  module.exports = app => {    app.configure(Users);    app.configure(Events); +  app.configure(Auth);    app.get('/ping', (req, res) => res.send('pong'));  }; diff --git a/src/services/users/user.hooks.js b/src/services/users/user.hooks.js new file mode 100644 index 0000000..daeda68 --- /dev/null +++ b/src/services/users/user.hooks.js @@ -0,0 +1,21 @@ +const { hooks } = require ('@feathersjs/authentication-local'); +const { NotAuthenticated } = require('@feathersjs/errors'); + +const compareUser = async context => { +  if (context.id !== context.params.user._id.toString()) { +    throw new NotAuthenticated('You can only PATCH/UPDATE your own user!'); +  } +  return context; +}; + + +module.exports = { +  after: { +    all: hooks.protect('password') +  }, +  before: { +    patch: [compareUser], +    update: [compareUser] +  } +}; + diff --git a/src/services/users/user.service.js b/src/services/users/user.service.js index 67f2ae6..afb3b9e 100644 --- a/src/services/users/user.service.js +++ b/src/services/users/user.service.js @@ -1,7 +1,11 @@  const service = require('feathers-mongoose');  const Model = require('./user.model.js'); +const hooks = require('./user.hooks.js');  const UserService = service({ Model }) -module.exports = app => app.use('/users', UserService); +module.exports = app => { +  app.use('/users', UserService); +  app.service('users').hooks(hooks); +}; | 
