Socket
Socket
Sign inDemoInstall

passport-saml

Package Overview
Dependencies
Maintainers
2
Versions
68
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

passport-saml - npm Package Compare versions

Comparing version 0.14.0 to 0.15.0

136

lib/passport-saml/saml.js

@@ -111,2 +111,3 @@ var zlib = require('zlib');

var signer;
var samlMessageToSign = {};
switch(this.options.signatureAlgorithm) {

@@ -122,3 +123,15 @@ case 'sha256':

}
signer.update(querystring.stringify(samlMessage));
if (samlMessage.SAMLRequest) {
samlMessageToSign.SAMLRequest = samlMessage.SAMLRequest;
}
if (samlMessage.SAMLResponse) {
samlMessageToSign.SAMLResponse = samlMessage.SAMLResponse;
}
if (samlMessage.RelayState) {
samlMessageToSign.RelayState = samlMessage.RelayState;
}
if (samlMessage.SigAlg) {
samlMessageToSign.SigAlg = samlMessage.SigAlg;
}
signer.update(querystring.stringify(samlMessageToSign));
samlMessage.Signature = signer.sign(this.options.privateCert, 'base64');

@@ -218,2 +231,10 @@ };

if (typeof(req.user.nameQualifier) !== 'undefined') {
request['samlp:LogoutRequest']['saml:NameID']['@NameQualifier'] = req.user.nameQualifier;
}
if (typeof(req.user.spNameQualifier) !== 'undefined') {
request['samlp:LogoutRequest']['saml:NameID']['@SPNameQualifier'] = req.user.spNameQualifier;
}
if (req.user.sessionIndex) {

@@ -342,2 +363,76 @@ request['samlp:LogoutRequest']['saml2p:SessionIndex'] = {

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 ? '
' : '\n';
return ('' + s) // Forces the conversion to string.
.replace(/&/g, '&') // This MUST be the 1st replacement.
.replace(/'/g, ''') // The 4 other predefined entities, required.
.replace(/"/g, '"')
.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) {

@@ -585,2 +680,3 @@ var request = this.generateLogoutRequest(req);

var subject = assertion.Subject;
var subjectConfirmation, confirmData;
if (subject) {

@@ -593,28 +689,30 @@ var nameID = subject[0].NameID;

profile.nameIDFormat = nameID[0].$.Format;
profile.nameQualifier = nameID[0].$.NameQualifier;
profile.spNameQualifier = nameID[0].$.SPNameQualifier;
}
}
}
var subjectConfirmation = subject[0].SubjectConfirmation ?
subject[0].SubjectConfirmation[0] : null;
var confirmData = subjectConfirmation && subjectConfirmation.SubjectConfirmationData ?
subjectConfirmation.SubjectConfirmationData[0] : null;
if (subject[0].SubjectConfirmation && subject[0].SubjectConfirmation.length > 1) {
msg = 'Unable to process multiple SubjectConfirmations in SAML assertion';
throw new Error(msg);
}
subjectConfirmation = subject[0].SubjectConfirmation ?
subject[0].SubjectConfirmation[0] : null;
confirmData = subjectConfirmation && subjectConfirmation.SubjectConfirmationData ?
subjectConfirmation.SubjectConfirmationData[0] : null;
if (subject[0].SubjectConfirmation && subject[0].SubjectConfirmation.length > 1) {
msg = 'Unable to process multiple SubjectConfirmations in SAML assertion';
throw new Error(msg);
}
if (subjectConfirmation) {
if (confirmData && confirmData.$) {
var subjectNotBefore = confirmData.$.NotBefore;
var subjectNotOnOrAfter = confirmData.$.NotOnOrAfter;
if (subjectConfirmation) {
if (confirmData && confirmData.$) {
var subjectNotBefore = confirmData.$.NotBefore;
var subjectNotOnOrAfter = confirmData.$.NotOnOrAfter;
var subjErr = self.checkTimestampsValidityError(
nowMs, subjectNotBefore, subjectNotOnOrAfter);
if (subjErr) {
throw subjErr;
var subjErr = self.checkTimestampsValidityError(
nowMs, subjectNotBefore, subjectNotOnOrAfter);
if (subjErr) {
throw subjErr;
}
}
}
}
// Test to see that if we have a SubjectConfirmation InResponseTo that it matches

@@ -621,0 +719,0 @@ // the 'InResponseTo' attribute set in the Response

@@ -22,2 +22,3 @@ var passport = require('passport-strategy');

this._passReqToCallback = !!options.passReqToCallback;
this._authnRequestBinding = options.authnRequestBinding || 'HTTP-Redirect';
}

@@ -78,10 +79,27 @@

} else {
var operation = {
'login-request': 'getAuthorizeUrl',
'logout-request': 'getLogoutUrl'
var requestHandler = {
'login-request': function() {
if (self._authnRequestBinding === '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();
}

@@ -88,0 +106,0 @@ };

2

package.json
{
"name": "passport-saml",
"version": "0.14.0",
"version": "0.15.0",
"licenses": [

@@ -5,0 +5,0 @@ {

@@ -65,2 +65,3 @@ Passport-SAML

* `skipRequestCompression`: if set to true, the SAML request from the service provider won't be compressed.
* `authnRequestBinding`: if set to `HTTP-POST`, will request authentication from IDP via HTTP POST binding, otherwise defaults to HTTP Redirect
* InResponseTo Validation

@@ -112,3 +113,3 @@ * `validateInResponseTo`: if truthy, then InResponseTo will be validated from incoming SAML responses

Passport-SAML uses the HTTP Redirect Binding for its `AuthnRequest`s, and expects to receive the messages back via the HTTP POST binding.
Passport-SAML uses the HTTP Redirect Binding for its `AuthnRequest`s (unless overridden with the `authnRequestBinding` parameter), and expects to receive the messages back via the HTTP POST binding.

@@ -115,0 +116,0 @@ Authentication requests sent by Passport-SAML can be signed using RSA-SHA1. To sign them you need to provide a private key in the PEM format via the `privateCert` configuration key. For example:

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc