diff options
Diffstat (limited to 'lib/web/auth')
| -rw-r--r-- | lib/web/auth/index.js | 1 | ||||
| -rw-r--r-- | lib/web/auth/ldap/index.js | 8 | ||||
| -rw-r--r-- | lib/web/auth/saml/index.js | 95 | 
3 files changed, 103 insertions, 1 deletions
diff --git a/lib/web/auth/index.js b/lib/web/auth/index.js index 4b618101..db5ff11d 100644 --- a/lib/web/auth/index.js +++ b/lib/web/auth/index.js @@ -37,6 +37,7 @@ if (config.isMattermostEnable) authRouter.use(require('./mattermost'))  if (config.isDropboxEnable) authRouter.use(require('./dropbox'))  if (config.isGoogleEnable) authRouter.use(require('./google'))  if (config.isLDAPEnable) authRouter.use(require('./ldap')) +if (config.isSAMLEnable) authRouter.use(require('./saml'))  if (config.isEmailEnable) authRouter.use(require('./email'))  // logout diff --git a/lib/web/auth/ldap/index.js b/lib/web/auth/ldap/index.js index 9a63578a..cc0d29ad 100644 --- a/lib/web/auth/ldap/index.js +++ b/lib/web/auth/ldap/index.js @@ -24,9 +24,15 @@ passport.use(new LDAPStrategy({    }  }, function (user, done) {    var uuid = user.uidNumber || user.uid || user.sAMAccountName +  var username = uuid + +  if (config.ldap.usernameField && user[config.ldap.usernameField]) { +    username = user[config.ldap.usernameField] +  } +    var profile = {      id: 'LDAP-' + uuid, -    username: uuid, +    username: username,      displayName: user.displayName,      emails: user.mail ? [user.mail] : [],      avatarUrl: null, diff --git a/lib/web/auth/saml/index.js b/lib/web/auth/saml/index.js new file mode 100644 index 00000000..386293ae --- /dev/null +++ b/lib/web/auth/saml/index.js @@ -0,0 +1,95 @@ +'use strict' + +const Router = require('express').Router +const passport = require('passport') +const SamlStrategy = require('passport-saml').Strategy +const config = require('../../../config') +const models = require('../../../models') +const logger = require('../../../logger') +const {urlencodedParser} = require('../../utils') +const fs = require('fs') +const intersection = function (array1, array2) { return array1.filter((n) => array2.includes(n)) } + +let samlAuth = module.exports = Router() + +passport.use(new SamlStrategy({ +  callbackUrl: config.serverurl + '/auth/saml/callback', +  entryPoint: config.saml.idpSsoUrl, +  issuer: config.saml.issuer || config.serverurl, +  cert: fs.readFileSync(config.saml.idpCert, 'utf-8'), +  identifierFormat: config.saml.identifierFormat +}, function (user, done) { +  // check authorization if needed +  if (config.saml.externalGroups && config.saml.grouptAttribute) { +    var externalGroups = intersection(config.saml.externalGroups, user[config.saml.groupAttribute]) +    if (externalGroups.length > 0) { +      logger.error('saml permission denied: ' + externalGroups.join(', ')) +      return done('Permission denied', null) +    } +  } +  if (config.saml.requiredGroups && config.saml.grouptAttribute) { +    if (intersection(config.saml.requiredGroups, user[config.saml.groupAttribute]).length === 0) { +      logger.error('saml permission denied') +      return done('Permission denied', null) +    } +  } +  // user creation +  var uuid = user[config.saml.attribute.id] || user.nameID +  var profile = { +    provider: 'saml', +    id: 'SAML-' + uuid, +    username: user[config.saml.attribute.username] || user.nameID, +    emails: user[config.saml.attribute.email] ? [user[config.saml.attribute.email]] : [] +  } +  if (profile.emails.length === 0 && config.saml.identifierFormat === 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress') { +    profile.emails.push(user.nameID) +  } +  var stringifiedProfile = JSON.stringify(profile) +  models.User.findOrCreate({ +    where: { +      profileid: profile.id.toString() +    }, +    defaults: { +      profile: stringifiedProfile +    } +  }).spread(function (user, created) { +    if (user) { +      var needSave = false +      if (user.profile !== stringifiedProfile) { +        user.profile = stringifiedProfile +        needSave = true +      } +      if (needSave) { +        user.save().then(function () { +          if (config.debug) { logger.debug('user login: ' + user.id) } +          return done(null, user) +        }) +      } else { +        if (config.debug) { logger.debug('user login: ' + user.id) } +        return done(null, user) +      } +    } +  }).catch(function (err) { +    logger.error('saml auth failed: ' + err) +    return done(err, null) +  }) +})) + +samlAuth.get('/auth/saml', +  passport.authenticate('saml', { +    successReturnToOrRedirect: config.serverurl + '/', +    failureRedirect: config.serverurl + '/' +  }) +) + +samlAuth.post('/auth/saml/callback', urlencodedParser, +  passport.authenticate('saml', { +    successReturnToOrRedirect: config.serverurl + '/', +    failureRedirect: config.serverurl + '/' +  }) +) + +samlAuth.get('/auth/saml/metadata', function (req, res) { +  res.type('application/xml') +  res.send(passport._strategy('saml').generateServiceProviderMetadata()) +})  | 
