authentication.js 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. import easyNoPassword from 'easy-no-password';
  2. import express from 'express';
  3. import crypto from 'crypto';
  4. import log from './log.js';
  5. import { throwError, errorGuard, errorMiddleware } from './error.js';
  6. import { isInWhiteList } from './whitelist.js'
  7. import { WHITELIST_PATH } from './settings.js'
  8. const sha256 = (data) => {
  9. return crypto.createHash('sha256').update(data, 'binary').digest('hex');
  10. };
  11. // Auth Middleware
  12. export const authentication = ({
  13. prefix = 'auth',
  14. secret,
  15. // eslint-disable-next-line no-unused-vars
  16. onSendToken = ({ remote, userEmail, userId, token, req }) =>
  17. Promise.resolve(),
  18. // eslint-disable-next-line no-unused-vars
  19. onLogin = (req, userId) => {},
  20. // eslint-disable-next-line no-unused-vars
  21. onLogout = (req) => {},
  22. } = {}) => {
  23. const router = express.Router();
  24. const enp = easyNoPassword(secret);
  25. // Verify token
  26. router.get(
  27. `/${prefix}/verify/:userId/:token`,
  28. errorGuard(async (req, res) => {
  29. const {
  30. params: { token, userId },
  31. } = req;
  32. const isValid = await new Promise((resolve, reject) => {
  33. enp.isValid(token, userId, (err, isValid) => {
  34. if (err) {
  35. reject(err);
  36. }
  37. resolve(isValid);
  38. });
  39. });
  40. if (!isValid) {
  41. throwError('Token invalid or has expired', 403);
  42. } else {
  43. onLogin(userId, req);
  44. res.json({ message: 'success' });
  45. }
  46. })
  47. );
  48. // Allow to check authentification
  49. router.get(
  50. `/${prefix}/check`,
  51. errorGuard(async (req, res) => {
  52. if (req.session.userId) {
  53. res.json({ message: 'success' });
  54. } else {
  55. throwError('Not authenticated', 403);
  56. }
  57. })
  58. );
  59. // Get token
  60. router.post(
  61. `/${prefix}/`,
  62. errorGuard(async (req, res, next) => {
  63. const {
  64. body: { userEmail },
  65. ricochetOrigin,
  66. } = req;
  67. if (!userEmail) {
  68. throwError("Missing mandatory 'email' parameter", 400);
  69. }
  70. if (! await isInWhiteList(WHITELIST_PATH, userEmail)) {
  71. log.warn(userEmail + " not in whitelist.", 403);
  72. throwError(userEmail + " not in whitelist.", 403);
  73. }
  74. const userId = sha256(userEmail.toLowerCase());
  75. enp.createToken(userId, (err, token) => {
  76. if (err) {
  77. throwError('Unknown error', 500);
  78. }
  79. return onSendToken({
  80. remote: ricochetOrigin,
  81. userEmail,
  82. userId,
  83. token,
  84. req,
  85. }).then(
  86. () => {
  87. res.json({ message: 'Token sent' });
  88. },
  89. (e) => {
  90. log.error({ error: e }, 'Error while sending email');
  91. const errorObject = new Error(e);
  92. errorObject.statusCode = 503;
  93. next(errorObject);
  94. }
  95. );
  96. });
  97. })
  98. );
  99. // Logout
  100. router.get(
  101. `/${prefix}/logout/`,
  102. errorGuard(async (req, res) => {
  103. onLogout(req);
  104. res.json({ message: 'logged out' });
  105. })
  106. );
  107. router.use(errorMiddleware);
  108. return router;
  109. };
  110. export default authentication;