auth.js 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. 'use strict'
  2. /* global appconfig, appdata, db, lang, winston */
  3. const fs = require('fs')
  4. const _ = require('lodash')
  5. module.exports = function (passport) {
  6. // Serialization user methods
  7. passport.serializeUser(function (user, done) {
  8. done(null, user._id)
  9. })
  10. passport.deserializeUser(function (id, done) {
  11. db.User.findById(id).then((user) => {
  12. if (user) {
  13. done(null, user)
  14. } else {
  15. done(new Error(lang.t('auth:errors:usernotfound')), null)
  16. }
  17. return true
  18. }).catch((err) => {
  19. done(err, null)
  20. })
  21. })
  22. // Local Account
  23. if (appconfig.auth.local && appconfig.auth.local.enabled) {
  24. const LocalStrategy = require('passport-local').Strategy
  25. passport.use('local',
  26. new LocalStrategy({
  27. usernameField: 'email',
  28. passwordField: 'password'
  29. }, (uEmail, uPassword, done) => {
  30. db.User.findOne({ email: uEmail, provider: 'local' }).then((user) => {
  31. if (user) {
  32. return user.validatePassword(uPassword).then(() => {
  33. return done(null, user) || true
  34. }).catch((err) => {
  35. return done(err, null)
  36. })
  37. } else {
  38. return done(new Error('INVALID_LOGIN'), null)
  39. }
  40. }).catch((err) => {
  41. done(err, null)
  42. })
  43. }
  44. ))
  45. }
  46. // Google ID
  47. if (appconfig.auth.google && appconfig.auth.google.enabled) {
  48. const GoogleStrategy = require('passport-google-oauth20').Strategy
  49. passport.use('google',
  50. new GoogleStrategy({
  51. clientID: appconfig.auth.google.clientId,
  52. clientSecret: appconfig.auth.google.clientSecret,
  53. callbackURL: appconfig.host + '/login/google/callback'
  54. }, (accessToken, refreshToken, profile, cb) => {
  55. db.User.processProfile(profile).then((user) => {
  56. return cb(null, user) || true
  57. }).catch((err) => {
  58. return cb(err, null) || true
  59. })
  60. }
  61. ))
  62. }
  63. // Microsoft Accounts
  64. if (appconfig.auth.microsoft && appconfig.auth.microsoft.enabled) {
  65. const WindowsLiveStrategy = require('passport-windowslive').Strategy
  66. passport.use('windowslive',
  67. new WindowsLiveStrategy({
  68. clientID: appconfig.auth.microsoft.clientId,
  69. clientSecret: appconfig.auth.microsoft.clientSecret,
  70. callbackURL: appconfig.host + '/login/ms/callback'
  71. }, function (accessToken, refreshToken, profile, cb) {
  72. db.User.processProfile(profile).then((user) => {
  73. return cb(null, user) || true
  74. }).catch((err) => {
  75. return cb(err, null) || true
  76. })
  77. }
  78. ))
  79. }
  80. // Facebook
  81. if (appconfig.auth.facebook && appconfig.auth.facebook.enabled) {
  82. const FacebookStrategy = require('passport-facebook').Strategy
  83. passport.use('facebook',
  84. new FacebookStrategy({
  85. clientID: appconfig.auth.facebook.clientId,
  86. clientSecret: appconfig.auth.facebook.clientSecret,
  87. callbackURL: appconfig.host + '/login/facebook/callback',
  88. profileFields: ['id', 'displayName', 'email']
  89. }, function (accessToken, refreshToken, profile, cb) {
  90. db.User.processProfile(profile).then((user) => {
  91. return cb(null, user) || true
  92. }).catch((err) => {
  93. return cb(err, null) || true
  94. })
  95. }
  96. ))
  97. }
  98. // GitHub
  99. if (appconfig.auth.github && appconfig.auth.github.enabled) {
  100. const GitHubStrategy = require('passport-github2').Strategy
  101. passport.use('github',
  102. new GitHubStrategy({
  103. clientID: appconfig.auth.github.clientId,
  104. clientSecret: appconfig.auth.github.clientSecret,
  105. callbackURL: appconfig.host + '/login/github/callback',
  106. scope: ['user:email']
  107. }, (accessToken, refreshToken, profile, cb) => {
  108. db.User.processProfile(profile).then((user) => {
  109. return cb(null, user) || true
  110. }).catch((err) => {
  111. return cb(err, null) || true
  112. })
  113. }
  114. ))
  115. }
  116. // Slack
  117. if (appconfig.auth.slack && appconfig.auth.slack.enabled) {
  118. const SlackStrategy = require('passport-slack').Strategy
  119. passport.use('slack',
  120. new SlackStrategy({
  121. clientID: appconfig.auth.slack.clientId,
  122. clientSecret: appconfig.auth.slack.clientSecret,
  123. callbackURL: appconfig.host + '/login/slack/callback'
  124. }, (accessToken, refreshToken, profile, cb) => {
  125. db.User.processProfile(profile).then((user) => {
  126. return cb(null, user) || true
  127. }).catch((err) => {
  128. return cb(err, null) || true
  129. })
  130. }
  131. ))
  132. }
  133. // LDAP
  134. if (appconfig.auth.ldap && appconfig.auth.ldap.enabled) {
  135. const LdapStrategy = require('passport-ldapauth').Strategy
  136. passport.use('ldapauth',
  137. new LdapStrategy({
  138. server: {
  139. url: appconfig.auth.ldap.url,
  140. bindDn: appconfig.auth.ldap.bindDn,
  141. bindCredentials: appconfig.auth.ldap.bindCredentials,
  142. searchBase: appconfig.auth.ldap.searchBase,
  143. searchFilter: appconfig.auth.ldap.searchFilter,
  144. searchAttributes: ['displayName', 'name', 'cn', 'mail'],
  145. tlsOptions: (appconfig.auth.ldap.tlsEnabled) ? {
  146. ca: [
  147. fs.readFileSync(appconfig.auth.ldap.tlsCertPath)
  148. ]
  149. } : {}
  150. },
  151. usernameField: 'email',
  152. passReqToCallback: false
  153. }, (profile, cb) => {
  154. profile.provider = 'ldap'
  155. profile.id = profile.dn
  156. db.User.processProfile(profile).then((user) => {
  157. return cb(null, user) || true
  158. }).catch((err) => {
  159. return cb(err, null) || true
  160. })
  161. }
  162. ))
  163. }
  164. // AZURE AD
  165. if (appconfig.auth.azure && appconfig.auth.azure.enabled) {
  166. const AzureAdOAuth2Strategy = require('passport-azure-ad-oauth2').Strategy
  167. const jwt = require('jsonwebtoken')
  168. passport.use('azure_ad_oauth2',
  169. new AzureAdOAuth2Strategy({
  170. clientID: appconfig.auth.azure.clientId,
  171. clientSecret: appconfig.auth.azure.clientSecret,
  172. callbackURL: appconfig.host + '/login/azure/callback',
  173. resource: appconfig.auth.azure.resource,
  174. tenant: appconfig.auth.azure.tenant
  175. }, (accessToken, refreshToken, params, profile, cb) => {
  176. let waadProfile = jwt.decode(params.id_token)
  177. waadProfile.id = waadProfile.oid
  178. waadProfile.provider = 'azure'
  179. db.User.processProfile(waadProfile).then((user) => {
  180. return cb(null, user) || true
  181. }).catch((err) => {
  182. return cb(err, null) || true
  183. })
  184. }
  185. ))
  186. }
  187. // OAuth 2
  188. if (appconfig.auth.oauth2 && appconfig.auth.oauth2.enabled) {
  189. const OAuth2Strategy = require('passport-oauth2').Strategy
  190. passport.use('oauth2',
  191. new OAuth2Strategy({
  192. authorizationURL: appconfig.auth.oauth2.authorizationURL,
  193. tokenURL: appconfig.auth.oauth2.tokenURL,
  194. clientID: appconfig.auth.oauth2.clientId,
  195. clientSecret: appconfig.auth.oauth2.clientSecret,
  196. callbackURL: appconfig.host + '/login/oauth2/callback'
  197. }, (accessToken, refreshToken, profile, cb) => {
  198. db.User.processProfile(profile).then((user) => {
  199. return cb(null, user) || true
  200. }).catch((err) => {
  201. return cb(err, null) || true
  202. })
  203. }
  204. ))
  205. }
  206. // OpenID Connect
  207. if (appconfig.auth.oidc && appconfig.auth.oidc.enabled) {
  208. const OIDCStrategy = require('passport-openidconnect').Strategy
  209. passport.use('oidc', new OIDCStrategy({
  210. userInfoURL: appconfig.auth.oidc.userInfoUrl,
  211. authorizationURL: appconfig.auth.oidc.authorizationURL,
  212. tokenURL: appconfig.auth.oidc.tokenURL,
  213. clientID: appconfig.auth.oidc.clientId,
  214. clientSecret: appconfig.auth.oidc.clientSecret,
  215. issuer: appconfig.auth.oidc.issuer,
  216. callbackURL: appconfig.host + '/login/oidc/callback'
  217. }, (iss, sub, profile, jwtClaims, accessToken, refreshToken, params, cb) => {
  218. db.User.processProfile({
  219. id: jwtClaims.sub,
  220. provider: 'oidc',
  221. email: _.get(jwtClaims, appconfig.auth.oidc.emailClaim),
  222. name: _.get(jwtClaims, appconfig.auth.oidc.usernameClaim)
  223. }).then((user) => {
  224. return cb(null, user) || true
  225. }).catch((err) => {
  226. return cb(err, null) || true
  227. })
  228. }
  229. ))
  230. }
  231. // Create users for first-time
  232. db.onReady.then(() => {
  233. return db.User.findOne({ provider: 'local', email: 'guest' }).then((c) => {
  234. if (c < 1) {
  235. // Create guest account
  236. return db.User.create({
  237. provider: 'local',
  238. email: 'guest',
  239. name: 'Guest',
  240. password: '',
  241. rights: [{
  242. role: 'read',
  243. path: '/',
  244. exact: false,
  245. deny: !appconfig.public
  246. }]
  247. }).then(() => {
  248. winston.info('[AUTH] Guest account created successfully!')
  249. }).catch((err) => {
  250. winston.error('[AUTH] An error occured while creating guest account:')
  251. winston.error(err)
  252. })
  253. }
  254. }).then(() => {
  255. if (process.env.WIKI_JS_HEROKU) {
  256. return db.User.findOne({ provider: 'local', email: process.env.WIKI_ADMIN_EMAIL }).then((c) => {
  257. if (c < 1) {
  258. // Create root admin account (HEROKU ONLY)
  259. return db.User.create({
  260. provider: 'local',
  261. email: process.env.WIKI_ADMIN_EMAIL,
  262. name: 'Administrator',
  263. password: '$2a$04$MAHRw785Xe/Jd5kcKzr3D.VRZDeomFZu2lius4gGpZZ9cJw7B7Mna', // admin123 (default)
  264. rights: [{
  265. role: 'admin',
  266. path: '/',
  267. exact: false,
  268. deny: false
  269. }]
  270. }).then(() => {
  271. winston.info('[AUTH] Root admin account created successfully!')
  272. }).catch((err) => {
  273. winston.error('[AUTH] An error occured while creating root admin account:')
  274. winston.error(err)
  275. })
  276. } else { return true }
  277. })
  278. } else { return true }
  279. })
  280. })
  281. }