/**
*
* @fileOverview This file exports the <i>authenticate</i> module that allows simple-cas to redirect
* to redirect user to CAS sign-in page, get a ticket, come back to this route again,
* validate a ticket and set cas session once ticket is validated.
*/
const url = require('url');
const protocol1 = require('./protocol1');
const protocol2 = require('./protocol2');
const protocol3 = require('./protocol3');
const CAS = require('../index');
/**
*
* @param options CAS configuration object
* @param route explicitly declared current route,
* for example your.app.com/login, in this case route is login.
* which will be used for redirection after authentication.
* @return {Function}
*/
function authenticate(options, route) {
return (req, res, next) => {
// support dynamic options maker
if (req.data) {
options.host = req.data.host;
options.service = req.data.service;
CAS.configure({ host: req.data.host, service: req.data.service });
}
if (req.data.protocolVersion) {
options.protocolVersion = req.data.protocolVersion;
CAS.configure({ protocolVersion: req.data.protocolVersion });
}
if (!options.service || !route || !options.host) {
throw new Error('Must supply a valid CAS parameters object(host and service declared) and redirect route');
}
switch (options.protocolVersion) {
case 1:
Object.defineProperty(options.paths, 'serviceValidate', { value: '/cas/serviceValidate' });
Object.defineProperty(options, 'validateTicketProtocol', { value: protocol1 });
break;
case 2:
Object.defineProperty(options.paths, 'serviceValidate', { value: '/cas/serviceValidate' });
Object.defineProperty(options, 'validateTicketProtocol', { value: protocol2 });
break;
case 3:
Object.defineProperty(options.paths, 'serviceValidate', { value: '/cas/p3/serviceValidate' });
Object.defineProperty(options, 'validateTicketProtocol', { value: protocol3 });
break;
default:
Object.defineProperty(options.paths, 'serviceValidate', { value: '/cas/serviceValidate' });
Object.defineProperty(options, 'validateTicketProtocol', { value: protocol2 });
}
// got back with a ticket
if (req.query.ticket) {
// putting making url from config to send to ticket validate package as one object
const urlFormatter = {};
urlFormatter.protocol = options.protocol;
urlFormatter.pathname = options.paths.serviceValidate;
urlFormatter.query = {};
urlFormatter.host = options.host;
const fullValidateUrl = url.format(urlFormatter);
const fullServiceUrl = options.service + route;
const servicePackage = {};
servicePackage.fullValidateUrl = fullValidateUrl;
servicePackage.fullServiceUrl = fullServiceUrl;
servicePackage.ticket = req.query.ticket;
servicePackage.validate = options.validateTicketProtocol;
// validate ticket and set session
CAS.validateService(servicePackage).then((msg) => {
req.session.cas = {};
req.session.cas.user = msg.user;
next();
}).catch((err) => {
throw new Error(err);
});
} else {
// there is no ticket in route, redirect user to cas login page
options.pathname = options.paths.login;
options.query = options.query || {};
options.query.service = options.service;
res.redirect(307, `${url.format(options)}${route}&renew=false`);
}
};
}
module.exports = authenticate;