auth.js 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. const http = require("http");
  2. const jsl = require("svjsl");
  3. const fs = require("fs-extra");
  4. const crypto = require("crypto");
  5. const settings = require("../settings");
  6. jsl.unused([http]);
  7. var previousDaemonHash;
  8. var tokenList;
  9. /**
  10. * Initializes the auth module
  11. */
  12. const init = () => {
  13. return new Promise(resolve => {
  14. fs.exists(settings.auth.tokenListFile, exists => {
  15. if(!exists)
  16. fs.writeFileSync(settings.auth.tokenListFile, JSON.stringify([], null, 4));
  17. refreshTokens();
  18. setInterval(() => daemonInterval(), settings.auth.daemonInterval);
  19. return resolve();
  20. });
  21. });
  22. };
  23. /**
  24. * To be called on interval to check if the tokens should be refreshed
  25. */
  26. function daemonInterval()
  27. {
  28. let tokenFileRaw = fs.readFileSync(settings.auth.tokenListFile).toString();
  29. let tokenHash = crypto.createHash("md5").update(tokenFileRaw).digest("hex");
  30. if(previousDaemonHash == undefined)
  31. return;
  32. else if(previousDaemonHash != tokenHash)
  33. {
  34. previousDaemonHash = tokenHash;
  35. refreshTokens();
  36. }
  37. }
  38. /**
  39. * Refreshes the auth tokens in memory
  40. */
  41. function refreshTokens()
  42. {
  43. try
  44. {
  45. let tokens = JSON.parse(fs.readFileSync(settings.auth.tokenListFile).toString());
  46. tokenList = tokens;
  47. }
  48. catch(err)
  49. {
  50. tokenList = [];
  51. fs.writeFileSync(settings.auth.tokenListFile, JSON.stringify([], null, 4));
  52. }
  53. }
  54. /**
  55. * @typedef {Object} Authorization
  56. * @prop {Boolean} isAuthorized
  57. * @prop {String} token
  58. */
  59. /**
  60. * Checks if the requester has provided an auth header and if the auth header is valid
  61. * @param {http.IncomingMessage} req
  62. * @param {http.ServerResponse} [res] If not provided, users will not get the `Token-Valid` response header
  63. * @returns {Authorization}
  64. */
  65. const authByHeader = (req, res) => {
  66. let isAuthorized = false;
  67. let requestersToken = "";
  68. if(req.headers && req.headers[settings.auth.tokenHeaderName])
  69. {
  70. if(Array.isArray(tokenList) && tokenList.length > 0)
  71. {
  72. tokenList.forEach(tokenObj => {
  73. if(tokenObj.token == req.headers[settings.auth.tokenHeaderName].toString())
  74. {
  75. requestersToken = req.headers[settings.auth.tokenHeaderName].toString();
  76. isAuthorized = true;
  77. }
  78. });
  79. }
  80. if(res && typeof res.setHeader == "function")
  81. res.setHeader(settings.auth.tokenValidHeader, (isAuthorized ? "1" : "0"));
  82. }
  83. return {
  84. isAuthorized: isAuthorized,
  85. token: requestersToken
  86. };
  87. };
  88. module.exports = { init, authByHeader };