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.

117 lines
4.2 KiB

  1. /* global wiki */
  2. const Promise = require('bluebird')
  3. const express = require('express')
  4. const router = express.Router()
  5. const ExpressBrute = require('express-brute')
  6. const ExpressBruteRedisStore = require('express-brute-redis')
  7. const moment = require('moment')
  8. const _ = require('lodash')
  9. /**
  10. * Setup Express-Brute
  11. */
  12. const EBstore = new ExpressBruteRedisStore({
  13. client: wiki.redis
  14. })
  15. const bruteforce = new ExpressBrute(EBstore, {
  16. freeRetries: 5,
  17. minWait: 60 * 1000,
  18. maxWait: 5 * 60 * 1000,
  19. refreshTimeoutOnRequest: false,
  20. failCallback (req, res, next, nextValidRequestDate) {
  21. req.flash('alert', {
  22. class: 'error',
  23. title: wiki.lang.t('auth:errors.toomanyattempts'),
  24. message: wiki.lang.t('auth:errors.toomanyattemptsmsg', { time: moment(nextValidRequestDate).fromNow() }),
  25. iconClass: 'fa-times'
  26. })
  27. res.redirect('/login')
  28. }
  29. })
  30. /**
  31. * Login form
  32. */
  33. router.get('/login', function (req, res, next) {
  34. res.render('auth/login', {
  35. authStrategies: _.reject(wiki.auth.strategies, { key: 'local' }),
  36. hasMultipleStrategies: Object.keys(wiki.config.auth.strategies).length > 1
  37. })
  38. })
  39. router.post('/login', bruteforce.prevent, function (req, res, next) {
  40. new Promise((resolve, reject) => {
  41. // [1] LOCAL AUTHENTICATION
  42. wiki.auth.passport.authenticate('local', function (err, user, info) {
  43. if (err) { return reject(err) }
  44. if (!user) { return reject(new Error('INVALID_LOGIN')) }
  45. resolve(user)
  46. })(req, res, next)
  47. }).catch({ message: 'INVALID_LOGIN' }, err => {
  48. if (_.has(wiki.config.auth.strategy, 'ldap')) {
  49. // [2] LDAP AUTHENTICATION
  50. return new Promise((resolve, reject) => {
  51. wiki.auth.passport.authenticate('ldapauth', function (err, user, info) {
  52. if (err) { return reject(err) }
  53. if (info && info.message) { return reject(new Error(info.message)) }
  54. if (!user) { return reject(new Error('INVALID_LOGIN')) }
  55. resolve(user)
  56. })(req, res, next)
  57. })
  58. } else {
  59. throw err
  60. }
  61. }).then((user) => {
  62. // LOGIN SUCCESS
  63. return req.logIn(user, function (err) {
  64. if (err) { return next(err) }
  65. req.brute.reset(function () {
  66. return res.redirect('/')
  67. })
  68. }) || true
  69. }).catch(err => {
  70. // LOGIN FAIL
  71. if (err.message === 'INVALID_LOGIN') {
  72. req.flash('alert', {
  73. title: wiki.lang.t('auth:errors.invalidlogin'),
  74. message: wiki.lang.t('auth:errors.invalidloginmsg')
  75. })
  76. return res.redirect('/login')
  77. } else {
  78. req.flash('alert', {
  79. title: wiki.lang.t('auth:errors.loginerror'),
  80. message: err.message
  81. })
  82. return res.redirect('/login')
  83. }
  84. })
  85. })
  86. /**
  87. * Social Login
  88. */
  89. router.get('/login/ms', wiki.auth.passport.authenticate('windowslive', { scope: ['wl.signin', 'wl.basic', 'wl.emails'] }))
  90. router.get('/login/google', wiki.auth.passport.authenticate('google', { scope: ['profile', 'email'] }))
  91. router.get('/login/facebook', wiki.auth.passport.authenticate('facebook', { scope: ['public_profile', 'email'] }))
  92. router.get('/login/github', wiki.auth.passport.authenticate('github', { scope: ['user:email'] }))
  93. router.get('/login/slack', wiki.auth.passport.authenticate('slack', { scope: ['identity.basic', 'identity.email'] }))
  94. router.get('/login/azure', wiki.auth.passport.authenticate('azure_ad_oauth2'))
  95. router.get('/login/ms/callback', wiki.auth.passport.authenticate('windowslive', { failureRedirect: '/login', successRedirect: '/' }))
  96. router.get('/login/google/callback', wiki.auth.passport.authenticate('google', { failureRedirect: '/login', successRedirect: '/' }))
  97. router.get('/login/facebook/callback', wiki.auth.passport.authenticate('facebook', { failureRedirect: '/login', successRedirect: '/' }))
  98. router.get('/login/github/callback', wiki.auth.passport.authenticate('github', { failureRedirect: '/login', successRedirect: '/' }))
  99. router.get('/login/slack/callback', wiki.auth.passport.authenticate('slack', { failureRedirect: '/login', successRedirect: '/' }))
  100. router.get('/login/azure/callback', wiki.auth.passport.authenticate('azure_ad_oauth2', { failureRedirect: '/login', successRedirect: '/' }))
  101. /**
  102. * Logout
  103. */
  104. router.get('/logout', function (req, res) {
  105. req.logout()
  106. res.redirect('/')
  107. })
  108. module.exports = router