You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

114 lines
3.9 KiB

  1. 'use strict'
  2. const Promise = require('bluebird')
  3. const express = require('express')
  4. const router = express.Router()
  5. const passport = require('passport')
  6. const ExpressBrute = require('express-brute')
  7. const ExpressBruteMongooseStore = require('express-brute-mongoose')
  8. const moment = require('moment')
  9. /**
  10. * Setup Express-Brute
  11. */
  12. const EBstore = new ExpressBruteMongooseStore(db.Bruteforce)
  13. const bruteforce = new ExpressBrute(EBstore, {
  14. freeRetries: 5,
  15. minWait: 60 * 1000,
  16. maxWait: 5 * 60 * 1000,
  17. refreshTimeoutOnRequest: false,
  18. failCallback (req, res, next, nextValidRequestDate) {
  19. req.flash('alert', {
  20. class: 'error',
  21. title: 'Too many attempts!',
  22. message: "You've made too many failed attempts in a short period of time, please try again " + moment(nextValidRequestDate).fromNow() + '.',
  23. iconClass: 'fa-times'
  24. })
  25. res.redirect('/login')
  26. }
  27. })
  28. /**
  29. * Login form
  30. */
  31. router.get('/login', function (req, res, next) {
  32. res.render('auth/login', {
  33. usr: res.locals.usr
  34. })
  35. })
  36. router.post('/login', bruteforce.prevent, function (req, res, next) {
  37. new Promise((resolve, reject) => {
  38. // [1] LOCAL AUTHENTICATION
  39. passport.authenticate('local', function (err, user, info) {
  40. if (err) { return reject(err) }
  41. if (!user) { return reject(new Error('INVALID_LOGIN')) }
  42. resolve(user)
  43. })(req, res, next)
  44. }).catch({ message: 'INVALID_LOGIN' }, err => {
  45. if (appconfig.auth.ldap && appconfig.auth.ldap.enabled) {
  46. // [2] LDAP AUTHENTICATION
  47. return new Promise((resolve, reject) => {
  48. passport.authenticate('ldapauth', function (err, user, info) {
  49. if (err) { return reject(err) }
  50. if (info && info.message) { return reject(new Error(info.message)) }
  51. if (!user) { return reject(new Error('INVALID_LOGIN')) }
  52. resolve(user)
  53. })(req, res, next)
  54. })
  55. } else {
  56. throw err
  57. }
  58. }).then((user) => {
  59. // LOGIN SUCCESS
  60. return req.logIn(user, function (err) {
  61. if (err) { return next(err) }
  62. req.brute.reset(function () {
  63. return res.redirect('/')
  64. })
  65. }) || true
  66. }).catch(err => {
  67. // LOGIN FAIL
  68. if (err.message === 'INVALID_LOGIN') {
  69. req.flash('alert', {
  70. title: 'Invalid login',
  71. message: 'The email or password is invalid.'
  72. })
  73. return res.redirect('/login')
  74. } else {
  75. req.flash('alert', {
  76. title: 'Login error',
  77. message: err.message
  78. })
  79. return res.redirect('/login')
  80. }
  81. })
  82. })
  83. /**
  84. * Social Login
  85. */
  86. router.get('/login/ms', passport.authenticate('windowslive', { scope: ['wl.signin', 'wl.basic', 'wl.emails'] }))
  87. router.get('/login/google', passport.authenticate('google', { scope: ['profile', 'email'] }))
  88. router.get('/login/facebook', passport.authenticate('facebook', { scope: ['public_profile', 'email'] }))
  89. router.get('/login/github', passport.authenticate('github', { scope: ['user:email'] }))
  90. router.get('/login/slack', passport.authenticate('slack', { scope: ['identity.basic', 'identity.email'] }))
  91. router.get('/login/azure', passport.authenticate('azure_ad_oauth2'))
  92. router.get('/login/ms/callback', passport.authenticate('windowslive', { failureRedirect: '/login', successRedirect: '/' }))
  93. router.get('/login/google/callback', passport.authenticate('google', { failureRedirect: '/login', successRedirect: '/' }))
  94. router.get('/login/facebook/callback', passport.authenticate('facebook', { failureRedirect: '/login', successRedirect: '/' }))
  95. router.get('/login/github/callback', passport.authenticate('github', { failureRedirect: '/login', successRedirect: '/' }))
  96. router.get('/login/slack/callback', passport.authenticate('slack', { failureRedirect: '/login', successRedirect: '/' }))
  97. router.get('/login/azure/callback', passport.authenticate('azure_ad_oauth2', { failureRedirect: '/login', successRedirect: '/' }))
  98. /**
  99. * Logout
  100. */
  101. router.get('/logout', function (req, res) {
  102. req.logout()
  103. res.redirect('/')
  104. })
  105. module.exports = router