Commit e1abf3ad authored by Peter Loer's avatar Peter Loer
Browse files

Merge pull request #129 from cheton/master

Adds HTTP-POST binding support for the SAML <AuthnRequest>
parents 8fa3381d ee5e9215
......@@ -357,6 +357,80 @@ SAML.prototype.getAuthorizeUrl = function (req, callback) {
});
};
SAML.prototype.getAuthorizeForm = function (req, callback) {
var self = this;
// The quoteattr() function is used in a context, where the result will not be evaluated by javascript
// but must be interpreted by an XML or HTML parser, and it must absolutely avoid breaking the syntax
// of an element attribute.
var quoteattr = function(s, preserveCR) {
preserveCR = preserveCR ? '&#13;' : '\n';
return ('' + s) // Forces the conversion to string.
.replace(/&/g, '&amp;') // This MUST be the 1st replacement.
.replace(/'/g, '&apos;') // The 4 other predefined entities, required.
.replace(/"/g, '&quot;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
// Add other replacements here for HTML only
// Or for XML, only if the named entities are defined in its DTD.
.replace(/\r\n/g, preserveCR) // Must be before the next replacement.
.replace(/[\r\n]/g, preserveCR);
};
var getAuthorizeFormHelper = function(err, buffer) {
if (err) {
return callback(err);
}
var operation = 'authorize';
var additionalParameters = self.getAdditionalParams(req, operation);
var samlMessage = {
SAMLRequest: buffer.toString('base64')
};
Object.keys(additionalParameters).forEach(function(k) {
samlMessage[k] = additionalParameters[k] || '';
});
var formInputs = Object.keys(samlMessage).map(function(k) {
return '<input type="hidden" name="' + k + '" value="' + quoteattr(samlMessage[k]) + '" />';
}).join('\r\n');
callback(null, [
'<!DOCTYPE html>',
'<html>',
'<head>',
'<meta charset="utf-8">',
'<meta http-equiv="x-ua-compatible" content="ie=edge">',
'</head>',
'<body onload="document.forms[0].submit()">',
'<noscript>',
'<p><strong>Note:</strong> Since your browser does not support JavaScript, you must press the button below once to proceed.</p>',
'</noscript>',
'<form method="post" action="' + encodeURI(self.options.entryPoint) + '">',
formInputs,
'<input type="submit" value="Submit" />',
'</form>',
'<script>document.forms[0].style.display="none";</script>', // Hide the form if JavaScript is enabled
'</body>',
'</html>'
].join('\r\n'));
};
self.generateAuthorizeRequest(req, self.options.passive, function(err, request) {
if (err) {
return callback(err);
}
if (self.options.skipRequestCompression) {
getAuthorizeFormHelper(null, new Buffer(request, 'utf8'));
} else {
zlib.deflateRaw(request, getAuthorizeFormHelper);
}
});
};
SAML.prototype.getLogoutUrl = function(req, callback) {
var request = this.generateLogoutRequest(req);
var operation = 'logout';
......
......@@ -28,6 +28,11 @@ Strategy.prototype.authenticate = function (req, options) {
options.samlFallback = options.samlFallback || 'login-request';
// Supported binding options:
// "HTTP-Redirect" - HTTP Redirect (GET) Binding
// "HTTP-POST" - HTTP POST Binding
options.samlBinding = options.samlBinding || 'HTTP-Redirect';
function validateCallback(err, profile, loggedOut) {
if (err) {
return self.error(err);
......@@ -74,14 +79,31 @@ Strategy.prototype.authenticate = function (req, options) {
} else if (req.body && req.body.SAMLRequest) {
this._saml.validatePostRequest(req.body, validateCallback);
} else {
var operation = {
'login-request': 'getAuthorizeUrl',
'logout-request': 'getLogoutUrl'
var requestHandler = {
'login-request': function() {
if (options.samlBinding === 'HTTP-POST') {
this._saml.getAuthorizeForm(req, function(err, data) {
if (err) {
self.error(err);
} else {
var res = req.res;
res.send(data);
}
});
} else { // Defaults to HTTP-Redirect
this._saml.getAuthorizeUrl(req, redirectIfSuccess);
}
}.bind(self),
'logout-request': function() {
this._saml.getLogoutUrl(req, redirectIfSuccess);
}.bind(self)
}[options.samlFallback];
if (!operation) {
if (typeof requestHandler !== 'function') {
return self.fail();
}
this._saml[operation](req, redirectIfSuccess);
requestHandler();
}
};
......
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