Commit fff0340f authored by Wolfgang Knopki's avatar Wolfgang Knopki
Browse files

Merge branch 'saml-integration' into 'mnt'

Saml integration

See merge request !1
parents 3eb99d26 9d956240
Pipeline #978 canceled with stages
......@@ -29,5 +29,9 @@
"mail_smtp_secure": true,
"mail_smtp_require_tls": true,
"mail_smtp_user": "your.smtp.user",
"mail_smtp_pass": "your.secret.smtp.password"
"mail_smtp_pass": "your.secret.smtp.password",
"path" : "http://localhost:9666/saml/SSO",
"entryPoint" : "https://m4lab.hft-stuttgart.de/idp/saml2/idp/SSOService.php",
"issuer" : "spacedeck.m4lab.hft-stuttgart.de"
}
......@@ -57,6 +57,7 @@ router.post('/', function(req, res) {
});
});
router.delete('/current', function(req, res, next) {
if (req.user) {
var token = req.cookies['sdsession'];
......
......@@ -9,11 +9,155 @@ const router = express.Router();
const mailer = require('../helpers/mailer');
const _ = require('underscore');
const fs = require('fs')
const SamlStrategy = require('passport-saml').Strategy
const passport = require('passport')
const Saml2js = require('saml2js');
const db = require('../models/db');
const Sequelize = require('sequelize');
const Op = Sequelize.Op;
const uuidv4 = require('uuid/v4');
// =========== PASSPORT =======
passport.serializeUser(function (user, done) {
done(null, user);
});
passport.deserializeUser(function (user, done) {
done(null, user);
});
var samlStrategy = new SamlStrategy({
// URL that goes from the Identity Provider -> Service Provider
callbackUrl: config.path,
entryPoint: config.entryPoint,
issuer: config.issuer,
identifierFormat: null,
validateInResponseTo: false,
disableRequestedAuthnContext: true
},
function (profile, done) {
return done(null, {
id: profile.nameID,
idFormat: profile.nameIDFormat,
email: profile.email,
firstName: profile.givenName,
lastName: profile.sn
});
});
passport.use(samlStrategy);
// to generate Service Provider's XML metadata
router.get('/saml/metadata',
function(req, res) {
res.type('application/xml');
var spMetadata = samlStrategy.generateServiceProviderMetadata(fs.readFileSync('/cert/certificate.pem', 'utf8'));
res.status(200).send(spMetadata);
}
);
router.post('/saml/SSO', passport.authenticate('saml', { failureRedirect: '/login', failureFlash: true}), function(req, res){
const xmlResponse = req.body.SAMLResponse;
const parser = new Saml2js(xmlResponse);
const response = parser.toObject();
const email = response["mail"];
console.log(parser.toJSON());
console.log("Nickname "+ response["givenName"])
const nickname = response["givenName"];
//check, if user exists, if not create.
db.User.findAll({where: {email: email}})
.then(users => {
if (users.length == 0) {
crypto.randomBytes(16, function(ex, buf) {
var token = buf.toString('hex');
var u = {
_id: uuidv4(),
email: email,
account_type: "email",
nickname: nickname,
password_hash: "00000",
prefs_language: req.i18n.locale,
confirmation_token: token
};
db.User.create(u)
.error(err => {
res.sendStatus(400);
})
.then(u => {
var homeFolder = {
_id: uuidv4(),
name: req.i18n.__("home"),
space_type: "folder",
creator_id: u._id
};
db.Space.create(homeFolder)
.error(err => {
res.sendStatus(400);
})
.then(homeFolder => {
u.home_folder_id = homeFolder._id;
u.save()
.then(() => {
// home folder created,
// auto accept pending invites
db.Membership.update({
"state": "active"
}, {
where: {
"email_invited": u.email,
"state": "pending"
}
});
res.status(201).json({});
})
.error(err => {
res.status(400).json(err);
});
})
});
});
}
}).then(user =>{
db.User.findOne({where: {email: email}})
.error(err => {
res.sendStatus(404);
})
.then(user => {
crypto.randomBytes(48, function(ex, buf) {
var token = buf.toString('hex');
var session = {
user_id: user._id,
token: token,
ip: req.ip,
device: "web",
created_at: new Date(),
url : "/"
};
db.Session.create(session)
.error(err => {
console.error("Error creating Session:",err);
res.redirect(500, "/");
})
.then(() => {
var domain = (process.env.NODE_ENV == "production") ? new URL(config.get('endpoint')).hostname : req.headers.hostname;
console.log("session set successfully");
res.cookie('sdsession', token, { domain: domain, httpOnly: true });
res.redirect(302, "/")
});
});
});
});
});
router.get('/', (req, res) => {
res.render('index', { config:config, user:req.user });
});
......@@ -90,9 +234,16 @@ router.get('/account', (req, res) => {
res.render('spacedeck');
});
router.get('/login', (req, res) => {
res.render('spacedeck', { config:config, user:req.user });
});
router.get('/login', passport.authenticate('saml',
{
successRedirect: '/',
failureRedirect: '/login'
})
);
// res.render('spacedeck', { config:config, user:req.user });
//});
router.get('/logout', (req, res) => {
res.render('spacedeck', { config:config, user:req.user });
......@@ -134,4 +285,4 @@ router.get('/spaces/:id', (req, res) => {
res.render('spacedeck', { config:config, user:req.user });
});
module.exports = router;
module.exports = {router: router, passport:passport};
......@@ -22,7 +22,6 @@ const helmet = require('helmet');
const express = require('express');
const app = express();
const serveStatic = require('serve-static');
const isProduction = app.get('env') === 'production';
// workaround for libssl_conf.so error triggered by phantomjs
......@@ -92,7 +91,7 @@ spaceRouter.use('/:id', require('./routes/api/space_exports'));
app.use('/api/sessions', require('./routes/api/sessions'));
//app.use('/api/webgrabber', require('./routes/api/webgrabber'));
app.use('/', require('./routes/root'));
if (config.get('storage_local_path')) {
app.use('/storage', serveStatic(config.get('storage_local_path')+"/"+config.get('storage_bucket'), {
......@@ -108,6 +107,13 @@ if (app.get('env') == 'development') {
app.use(require('./middlewares/500'));
}
const root = require('./routes/root');
const passport = root.passport;
app.use(passport.initialize());
app.use(passport.session());
app.use('/', root.router);
module.exports = app;
// CONNECT TO DATABASE
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment