{"_id":"@brainhubeu/hadron-auth","_rev":"26-b85af8369f81d91bb750645ef7cc0a6c","name":"@brainhubeu/hadron-auth","dist-tags":{"latest":"0.0.2"},"versions":{"0.0.1":{"name":"@brainhubeu/hadron-auth","version":"0.0.1","keywords":["security","hadron"],"author":{"name":"Brainhub"},"license":"MIT","_id":"@brainhubeu/hadron-auth@0.0.1","maintainers":[{"name":"brainhub-adam","email":"adam@brainhub.pl"},{"name":"caderek","email":"maciej.caderek@gmail.com"},{"name":"drymek","email":"marcin@dryka.pl"},{"name":"dyoda","email":"lukasz.pluszczewski@gmail.com"},{"name":"szymon.morawski","email":"szymon.morawski@brainhub.pl"}],"dist":{"shasum":"5d8ba0166dd23fec21ba2c12778d3ebc61a9ee12","tarball":"https://registry.npmjs.org/@brainhubeu/hadron-auth/-/hadron-auth-0.0.1.tgz","fileCount":33,"integrity":"sha512-j1XfgWv+2Iq1kcS7LqAIj6eGTY+/3K7KOzIAeKMB3UX2txGPrPBiCdqx+RdWNsx/Bvy+F52nfxe3hm6NKtNokQ==","signatures":[{"sig":"MEQCIDCMgV997VMxFxSbsYlWeOqUwXvc71O2qgHvaWw+DfFgAiBz0TJELJXVnWjQn7IM+1Oc5d3b81ug4CGBcewkGr2EPA==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":72941,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbLKHeCRA9TVsSAnZWagAA1xcP/igU0tuLTASofPvKFP0v\nwYh3fwUTzMBrUTu8GWjDQnOAXYADIAv4pttW5PQXo+4I83v+nIgYOTHtzGhf\no6E7fGB/kpE0wkpC24uviYLX/iP/3orHznsXKhj6G02wr1u/16JDTRUQoqE2\nTuO8L0f585103wQcyxGITdGP7d9WGMhBjPml5pKf4F0qh1JAOaC8OT/f///z\nuJxQk79XralEvmD7iigR2ZKoOceXCqlY774GZ2Q3vca+JNEXbf3JQaFregwP\nf+nUWM93wRyzIbLoap1JAB9/Br7rpBVlLVs6ItBcCS1WBGQf0L3ss+OrSAZZ\n4Q9JYkN4fKFLzYputHLQw2PCXKmO9pCAJikmOZuU2AOBtRwaW4Ufb6VfzstJ\nB7Mil+pb6FGtWUZ14KnEcJdwBhQz+PC0MsXe8khQJaF1m8I9kWhwnO0L4RYF\nUkbAlp8QXg0SYOfb/RuFhw375JLts4xVlln8hqQyo51wU2uyNKU1TNNo19EG\nzsd/1IseUBLHfy3yJyu6kfYxXp23sijQmXb0fVjJKjQ09EeOZGPrD1KkH17p\n5KQ3KOdhaGrTnWNO9LSkc6L17beoY77jYpEwZYlSgq866bcrMkfXOmaSUZ6V\n2AzrnifduSWcHTVEyFKmlowGmBu9lxAp92kCbL2TyRqCSXAtLomDGLSK+zhB\nvFBd\r\n=u5vl\r\n-----END PGP SIGNATURE-----\r\n"},"main":"dist/index.js","files":["dist","LICENSE"],"scripts":{"test":"echo \"Error: no test specified\" && exit 1","prepare":"tsc"},"_npmUser":{"name":"szymon.morawski","email":"szymon.morawski@brainhub.pl"},"_npmVersion":"5.5.1","description":"Security package for hadron","directories":{},"_nodeVersion":"8.6.0","dependencies":{"bcrypt":"2.0.0","jsonwebtoken":"8.3.0","@types/bcrypt":"^2.0.0","glob-to-regexp":"^0.4.0","@types/jsonwebtoken":"^7.2.7"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/hadron-auth_0.0.1_1529651678508_0.5941395336202835","host":"s3://npm-registry-packages"}},"0.0.2":{"name":"@brainhubeu/hadron-auth","version":"0.0.2","keywords":["security","hadron"],"author":{"name":"Brainhub"},"license":"MIT","_id":"@brainhubeu/hadron-auth@0.0.2","maintainers":[{"name":"brainhub-adam","email":"adam@brainhub.pl"},{"name":"brainhubeu-ci","email":"dev@brainhub.pl"},{"name":"caderek","email":"maciej.caderek@gmail.com"},{"name":"drymek","email":"marcin@dryka.pl"},{"name":"dyoda","email":"lukasz.pluszczewski@gmail.com"},{"name":"kkoscielniak","email":"krystiankoscielniak@gmail.com"},{"name":"piotr-s-brainhub","email":"piotr.sroczkowski@brainhub.pl"},{"name":"szulcd2","email":"szulcd2@gmail.com"},{"name":"szymon.morawski","email":"szymon.morawski@brainhub.pl"}],"dist":{"shasum":"a7dde2baa5181421e79e25157d8ccd1baadb23f9","tarball":"https://registry.npmjs.org/@brainhubeu/hadron-auth/-/hadron-auth-0.0.2.tgz","fileCount":33,"integrity":"sha512-Wb8Li12icaRcmjatBz3J2jwG0LtbjRwdty4egs0aja9YL1pxzkj5Ck8wJ05de4n4KnNRyofWxyB3ObFfWZ+1EQ==","signatures":[{"sig":"MEUCIQCrln0Zz7TVHxeo4ncvGszFC7oe9gTQoWrGs4qOkthrkwIgMPMn8ejvTjmUFOa+yYJxmSroZ2tduUe3dfSpFjjpl8U=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":74012,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbrOnvCRA9TVsSAnZWagAAd6oP/AqEY9O7A+aUngsXZoh+\nAr4eowioXXsIGMQzAmdnC60+BX5LFS/5y3xVv8/ZcQrRcjepaNP4c+sPqg6f\ngkAeeymGVHO5PV60fcSA+vtMY/x1+8GJ+FUcB9g7KNrN1pP26KDkiLPZ4viI\n1dC5gc5Erkq6EFFC3kIFtE0PzLQP9fY1itsyCxJ+D4HEmWYvxBoNz/JB3iMc\nO1+L4AjIbYrUGKY0c5DZ+4nABB4LnCUD/oOTzOjY4bgM5qBC51E8bRHSfzhh\nrDB11VngBB/LvhK5wL4S5qCIww9y88MtTdAaRbrLAjII0Db8APSCLGItBArb\nKWbFdzeCvvOjPTFfu+NDBPUC96TIP9sX3M/Yo+52HsIcPeBejVs2Yq39bA0d\nIWzPpD4F4JFtW7DaghW9BnMugfC+Tu/QIefJdG0Qd/u4yk7G36hePqOdyb2c\n12OP6VjSO/4WpbFuWfoxrKBEqzZJLugRSWpnAu6xglpbPR0YN5gq3+3g8M6q\ng+JBbcVSdmr1ug6e0mFnOpkt9C95Pmb2nXHtsnjiGphgYtutqPOqPlPg5Kl3\ngeGR7BuW3LpwiwwXmgwAZoi5AGUiAphl9a7/1pl0HaZBsmxfAacoRFSKZzlF\nVmDCcsaBmjzBT8lThoydr35ryMWyC9laft/7/bJpZK/WeKCGhv3XSCreCifB\n9e9d\r\n=jFTE\r\n-----END PGP SIGNATURE-----\r\n"},"main":"dist/index.js","scripts":{"test":"echo \"Error: no test specified\" && exit 1","prepare":"tsc"},"_npmUser":{"name":"szymon.morawski","email":"szymon.morawski@brainhub.pl"},"_npmVersion":"5.5.1","description":"Security package for hadron","directories":{},"_nodeVersion":"8.6.0","dependencies":{"bcrypt":"2.0.0","jsonwebtoken":"8.3.0","@types/bcrypt":"^2.0.0","glob-to-regexp":"^0.4.0","@types/jsonwebtoken":"^7.2.7"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/hadron-auth_0.0.2_1538058734730_0.1524291410699603","host":"s3://npm-registry-packages"}}},"time":{"created":"2018-06-22T07:14:38.021Z","modified":"2024-10-25T13:04:44.654Z","0.0.1":"2018-06-22T07:14:38.606Z","0.0.2":"2018-09-27T14:32:14.923Z"},"author":{"name":"Brainhub"},"license":"MIT","keywords":["security","hadron"],"description":"Security package for hadron","maintainers":[{"email":"angjeziorska@gmail.com","name":"angjez"},{"email":"mateusz.jarzebowski.bownik@gmail.com","name":"matt-jb"},{"email":"filip.kublin@brainhub.pl","name":"fkublin"},{"email":"cypherq@gmail.com","name":"benedyktdryl"},{"email":"dariusz.luber@gmail.com","name":"dluber"},{"email":"devops@brainhub.pl","name":"brainhubeu-devops"},{"email":"anna.lach@brainhub.pl","name":"annalach"},{"email":"szymon.morawski@brainhub.pl","name":"szymon.morawski"},{"email":"lukasz.pluszczewski@gmail.com","name":"dyoda"},{"email":"dev@brainhub.pl","name":"brainhubeu-ci"},{"email":"robert_hebel@icloud.com","name":"roberthebel"}],"readme":"## Installation\n\n```bash\nnpm install @brainhubeu/hadron-auth --save\n```\n\n## Overview\n\n**hadron-auth** provides back-end authorization layer for routes You will choose.\n\n### Configuration with Hadron Core\n\nIf You want to use **hadron-auth** with **hadron-core** You should also use **hadron-typeorm** and **hadron-express**.\nAll You need to provide is two schemas for typeorm:\n\n* `User` (id, username, and roles many-to-many relation required)\n  Here is the example schema:\n\n```javascript\n// schemas/User\nconst userSchema = {\n  name: 'User',\n  columns: {\n    id: {\n      primary: true,\n      type: 'int',\n      generated: true,\n    },\n    username: {\n      type: 'varchar',\n      unique: true,\n    },\n    passwordHash: {\n      type: 'varchar',\n    },\n    addedOn: {\n      type: 'timestamp',\n    },\n  },\n  relations: {\n    roles: {\n      target: 'Role',\n      type: 'many-to-many',\n      joinTable: {\n        name: 'user_role',\n      },\n      onDelete: 'CASCADE',\n    },\n  },\n};\n\nmodule.exports = userSchema;\n```\n\n* `Role` (id and name required)\n  Example schema:\n\n```javascript\n// schemas/Role\nconst roleSchema = {\n  name: 'Role',\n  columns: {\n    id: {\n      primary: true,\n      type: 'int',\n      generated: true,\n    },\n    name: {\n      type: 'varchar',\n      unique: true,\n    },\n    addedOn: {\n      type: 'timestamp',\n    },\n  },\n};\n\nmodule.exports = roleSchema;\n```\n\nDon't forget to add schemas to Your database config, example below:\n\n```javascript\n// config/db.js\nconst userSchema = require('../schemas/User');\nconst roleSchema = require('../schemas/Role');\n\nconst connection = {\n  name: 'mysql-connection',\n  type: 'mysql',\n  host: 'localhost',\n  port: 3306,\n  username: 'root',\n  password: 'my-secret-pw',\n  database: 'done-it',\n  entitySchemas: [roleSchema, userSchema],\n  synchronize: true,\n};\n\nmodule.exports = connection,\n```\n\nNow You need to prepare Your hadron configuration file, where You can add secured routes, for example:\n\n```javascript\n// index.js\nconst config = {\n  routes: {\n    helloWorldRoute: {\n      path: '/',\n      methods: ['GET'],\n      callback: () => 'Hello World',\n    },\n    adminRoute: {\n      path: '/admin',\n      methods: ['GET'],\n      callback: () => 'Hello Admin',\n    },\n    userRoute: {\n      path: '/user',\n      methods: ['GET'],\n      callback: () => 'Hello User',\n    },\n  },\n  securedRoutes: [\n    {\n      path: '/admin/*',\n      methods: ['GET', 'POST', 'PUT', 'DELETE'],\n      roles: 'Admin',\n    },\n    {\n      path: '/user/*',\n      roles: ['Admin', 'User'],\n    },\n  ],\n};\n```\n\nFinally You need to add **hadron-auth** to hadron initialization method:\n\n```javascript\nconst hadron = require('@brainhubeu/hadron-core').default;\nconst hadronExpress = require('@brainhubeu/hadron-express');\nconst hadronTypeOrm = require('@brainhubeu/hadron-typeorm');\nconst hadronAuth = require('@brainhubeu/hadron-auth');\nconst express = require('express');\n\nconst expressApp = express();\n\nconst hadronInit = async () => {\n  const config = {\n    routes: {\n      helloWorldRoute: {\n        path: '/',\n        methods: ['GET'],\n        callback: () => 'Hello World',\n      },\n      adminRoute: {\n        path: '/admin',\n        methods: ['GET'],\n        callback: () => 'Hello Admin',\n      },\n      userRoute: {\n        path: '/user',\n        methods: ['GET'],\n        callback: () => 'Hello User',\n      },\n    },\n    securedRoutes: [\n      {\n        path: '/admin/*',\n        methods: ['GET', 'POST', 'PUT', 'DELETE'],\n        roles: 'Admin',\n      },\n      {\n        path: '/user/*',\n        roles: ['Admin', 'User'],\n      },\n    ],\n  };\n\n  const container = await hadron(\n    expressApp,\n    [hadronAuth, hadronExpress, hadronTypeOrm],\n    config,\n  );\n};\n```\n\n---\n\nWarning, You should pass hadronAuth as first to hadron packages array.\n\n---\n\nNow Your routes are secured, by default, **hadron-auth** authorize user by **JWT Token**, passed as `Authorization` header.\n\n### Creating custom auth middleware\n\nYou can pass Your own function in hadron configuration to check if a user is authorized to the secured route.\nHere is the skeleton for the authorization middleware:\n\n```javascript\nconst authorizationMiddleware = (container) => {\n  return (req, res, next) => {};\n};\n```\n\n**hadron-auth** provides `isAllowed` function, to check if a user is allowed to specified route:\n\n```javascript\nisAllowed(path, method, user, allRoles);\n```\n\nWhere:\n\n* `path` - path to secured route, for example /api/admin/1\n* `method` - HTTP method\n* `user` - User object, which need to contain roles\n* `allRoles` - All roles stored in database (only role names)\n\nHere is an example authorization middleware:\n\n```javascript\nconst jwt = require('jsonwebtoken');\nconst { isRouteSecure, isAllowed } = require('@brainhubeu/hadron-auth');\n\nconst errorResponse = {\n  message: 'Unauthorized',\n};\n\nconst expressMiddlewareAuthorization = (container) => {\n  return async (req, res, next) => {\n    try {\n      if (!isRouteSecure(req.path)) {\n        return next();\n      }\n\n      const userRepository = container.take('userRepository');\n      const roleRepository = container.take('roleRepository');\n\n      const token = req.headers.authorization;\n\n      const decoded: any = jwt.decode(token);\n\n      const user = await userRepository.findOne({\n        where: { id: decoded.id },\n        relations: ['roles'],\n      });\n\n      if (!user) {\n        return res.status(403).json({ error: errorResponse });\n      }\n\n      const allRoles = await roleRepository.find();\n\n      if (\n        isAllowed(req.path, req.method, user, allRoles.map((role) => role.name))\n      ) {\n        return next();\n      }\n\n      return res.status(403).json({ error: errorResponse });\n    } catch (error) {\n      return res.status(403).json({ error: errorResponse });\n    }\n  };\n};\n\nmodule.exports = expressMiddlewareAuthorization;\n```\n\nTo use it, You need to pass an expressMiddlewareAuthorization function as `authorizationMiddleware` key in hadron config.\n\n```javascript\nconst config = {\n  authorizationMiddleware: YourCustomFunction,\n};\n```\n\n### Usage:\n\n```javascript\nconst securedRoutes = [\n  {\n    path: '/api/**',\n    methods: ['GET'],\n    roles: ['Admin', 'User'],\n  },\n  {\n    path: '/api/**',\n    methods: ['POST', 'PUT', 'DELETE'],\n    roles: 'Admin',\n  },\n  {\n    path: '/admin/*',\n    roles: 'Admin',\n  },\n  {\n    path: 'product/info',\n    methods: ['GET'],\n    roles: [['Admin', 'User'], 'Manager'],\n  },\n];\n```\n\n* `Path` - here we can specify the route path we want to secure, we can use a static path like `/api/admin/tasks` or by pattern:\n  * `/api/admin/*` - route after `/api/admin/` is secured, for example `/api/admin/tasks` - is secured, but `/api/admin/tasks/5` - will be not secured\n  * `/api/admin/**` - every route after `/api/admin` is secured\n* `methods` - an array of strings, where You can pass role names, if You will not provide any role, then the route is secured and user with **ANY** role can access this if a user does not have any role he will be unauthorized.\n* `roles` - here You can pass single role name, an array of role names or array of arrays of strings, which add some logic functionality, for example, if we declare:\n\n```javascript\nroles[(['Admin', 'User'], 'Manager')];\n```\n\nThe user needs Admin **AND** User **OR** Manager role to access the route.\n","readmeFilename":"README.md"}