mirror of
https://github.com/netzbegruenung/meteor-accounts-saml.git
synced 2024-04-29 18:34:53 +02:00
parent
e27099cc1c
commit
f45724839d
188
.npm/package/npm-shrinkwrap.json
generated
188
.npm/package/npm-shrinkwrap.json
generated
|
@ -1,10 +1,22 @@
|
||||||
{
|
{
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"arraybuffer-to-string": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/arraybuffer-to-string/-/arraybuffer-to-string-1.0.1.tgz",
|
||||||
|
"integrity": "sha1-V6vLXkxJSOTtEEoxGQOKNqPU/ZQ="
|
||||||
|
},
|
||||||
"async": {
|
"async": {
|
||||||
"version": "2.3.0",
|
"version": "2.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/async/-/async-2.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/async/-/async-2.3.0.tgz",
|
||||||
"integrity": "sha1-EBPRBRBH3TIP4k5JTVxm7K9hR9k="
|
"integrity": "sha1-EBPRBRBH3TIP4k5JTVxm7K9hR9k=",
|
||||||
|
"dependencies": {
|
||||||
|
"lodash": {
|
||||||
|
"version": "4.17.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz",
|
||||||
|
"integrity": "sha512-svL3uiZf1RwhH+cWrfZn3A4+U58wbP0tGVTLQPbjplZxZ8ROD9VLuNgsRniTlLe7OlSqR79RUehXgpBW/s0IQw=="
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"body-parser": {
|
"body-parser": {
|
||||||
"version": "1.17.1",
|
"version": "1.17.1",
|
||||||
|
@ -16,17 +28,92 @@
|
||||||
"resolved": "https://registry.npmjs.org/bytes/-/bytes-2.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/bytes/-/bytes-2.4.0.tgz",
|
||||||
"integrity": "sha1-fZcZb51br39pNeJZhVSe3SpsIzk="
|
"integrity": "sha1-fZcZb51br39pNeJZhVSe3SpsIzk="
|
||||||
},
|
},
|
||||||
|
"content-type": {
|
||||||
|
"version": "1.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
|
||||||
|
"integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA=="
|
||||||
|
},
|
||||||
"debug": {
|
"debug": {
|
||||||
"version": "2.6.1",
|
"version": "2.6.1",
|
||||||
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.1.tgz",
|
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.1.tgz",
|
||||||
"integrity": "sha1-eYVQkLosTjEVzH2HaUkdWPBJE1E=",
|
"integrity": "sha1-eYVQkLosTjEVzH2HaUkdWPBJE1E="
|
||||||
|
},
|
||||||
|
"ee-first": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
|
||||||
|
"integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
|
||||||
|
},
|
||||||
|
"http-errors": {
|
||||||
|
"version": "1.6.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz",
|
||||||
|
"integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ms": {
|
"depd": {
|
||||||
"version": "0.7.2",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz",
|
"resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz",
|
||||||
"integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U="
|
"integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k="
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"iconv-lite": {
|
||||||
|
"version": "0.4.15",
|
||||||
|
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.15.tgz",
|
||||||
|
"integrity": "sha1-/iZaIYrGpXz+hUkn6dBMGYJe3es="
|
||||||
|
},
|
||||||
|
"inherits": {
|
||||||
|
"version": "2.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
|
||||||
|
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
|
||||||
|
},
|
||||||
|
"media-typer": {
|
||||||
|
"version": "0.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
|
||||||
|
"integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g="
|
||||||
|
},
|
||||||
|
"mime-types": {
|
||||||
|
"version": "2.1.17",
|
||||||
|
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz",
|
||||||
|
"integrity": "sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo="
|
||||||
|
},
|
||||||
|
"ms": {
|
||||||
|
"version": "0.7.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz",
|
||||||
|
"integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U="
|
||||||
|
},
|
||||||
|
"on-finished": {
|
||||||
|
"version": "2.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
|
||||||
|
"integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc="
|
||||||
|
},
|
||||||
|
"qs": {
|
||||||
|
"version": "6.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz",
|
||||||
|
"integrity": "sha1-E+JtKK1rD/qpExLNO/cI7TUecjM="
|
||||||
|
},
|
||||||
|
"raw-body": {
|
||||||
|
"version": "2.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.2.0.tgz",
|
||||||
|
"integrity": "sha1-mUl2z2pQlqQRYoQEkvC9xdbn+5Y="
|
||||||
|
},
|
||||||
|
"setprototypeof": {
|
||||||
|
"version": "1.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz",
|
||||||
|
"integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ="
|
||||||
|
},
|
||||||
|
"statuses": {
|
||||||
|
"version": "1.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz",
|
||||||
|
"integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew=="
|
||||||
|
},
|
||||||
|
"type-is": {
|
||||||
|
"version": "1.6.15",
|
||||||
|
"resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.15.tgz",
|
||||||
|
"integrity": "sha1-yrEPtJCeRByChC6v4a1kbIGARBA="
|
||||||
|
},
|
||||||
|
"unpipe": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
|
||||||
|
"integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw="
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -85,9 +172,9 @@
|
||||||
"integrity": "sha1-R5Y2v6P+Ox3r1SCH8KyyBLTxnIg="
|
"integrity": "sha1-R5Y2v6P+Ox3r1SCH8KyyBLTxnIg="
|
||||||
},
|
},
|
||||||
"encodeurl": {
|
"encodeurl": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
|
||||||
"integrity": "sha1-eePVhlU0aQn+bw9Fpd5oEDspTSA="
|
"integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k="
|
||||||
},
|
},
|
||||||
"escape-html": {
|
"escape-html": {
|
||||||
"version": "1.0.3",
|
"version": "1.0.3",
|
||||||
|
@ -114,7 +201,24 @@
|
||||||
"http-errors": {
|
"http-errors": {
|
||||||
"version": "1.6.1",
|
"version": "1.6.1",
|
||||||
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.1.tgz",
|
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.1.tgz",
|
||||||
"integrity": "sha1-X4uO2YrKVFZWv1cplzh/kEpyIlc="
|
"integrity": "sha1-X4uO2YrKVFZWv1cplzh/kEpyIlc=",
|
||||||
|
"dependencies": {
|
||||||
|
"inherits": {
|
||||||
|
"version": "2.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
|
||||||
|
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
|
||||||
|
},
|
||||||
|
"setprototypeof": {
|
||||||
|
"version": "1.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz",
|
||||||
|
"integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ="
|
||||||
|
},
|
||||||
|
"statuses": {
|
||||||
|
"version": "1.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz",
|
||||||
|
"integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew=="
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"iconv-lite": {
|
"iconv-lite": {
|
||||||
"version": "0.4.15",
|
"version": "0.4.15",
|
||||||
|
@ -137,14 +241,21 @@
|
||||||
"integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g="
|
"integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g="
|
||||||
},
|
},
|
||||||
"mime-db": {
|
"mime-db": {
|
||||||
"version": "1.27.0",
|
"version": "1.30.0",
|
||||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.27.0.tgz",
|
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz",
|
||||||
"integrity": "sha1-gg9XIpa70g7CXtVeW13oaeVDbrE="
|
"integrity": "sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE="
|
||||||
},
|
},
|
||||||
"mime-types": {
|
"mime-types": {
|
||||||
"version": "2.1.15",
|
"version": "2.1.15",
|
||||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.15.tgz",
|
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.15.tgz",
|
||||||
"integrity": "sha1-pOv1BkCUVpI3uM9wBGd20J/JKu0="
|
"integrity": "sha1-pOv1BkCUVpI3uM9wBGd20J/JKu0=",
|
||||||
|
"dependencies": {
|
||||||
|
"mime-db": {
|
||||||
|
"version": "1.27.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.27.0.tgz",
|
||||||
|
"integrity": "sha1-gg9XIpa70g7CXtVeW13oaeVDbrE="
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"ms": {
|
"ms": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
|
@ -159,12 +270,19 @@
|
||||||
"on-finished": {
|
"on-finished": {
|
||||||
"version": "2.3.0",
|
"version": "2.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
|
||||||
"integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc="
|
"integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=",
|
||||||
|
"dependencies": {
|
||||||
|
"ee-first": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
|
||||||
|
"integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"parseurl": {
|
"parseurl": {
|
||||||
"version": "1.3.1",
|
"version": "1.3.2",
|
||||||
"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz",
|
||||||
"integrity": "sha1-yKuMkiO6NIiKpkopeyiFO+wY2lY="
|
"integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M="
|
||||||
},
|
},
|
||||||
"qs": {
|
"qs": {
|
||||||
"version": "6.4.0",
|
"version": "6.4.0",
|
||||||
|
@ -185,6 +303,11 @@
|
||||||
"version": "2.4.0",
|
"version": "2.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/bytes/-/bytes-2.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/bytes/-/bytes-2.4.0.tgz",
|
||||||
"integrity": "sha1-fZcZb51br39pNeJZhVSe3SpsIzk="
|
"integrity": "sha1-fZcZb51br39pNeJZhVSe3SpsIzk="
|
||||||
|
},
|
||||||
|
"unpipe": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
|
||||||
|
"integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw="
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -206,7 +329,19 @@
|
||||||
"type-is": {
|
"type-is": {
|
||||||
"version": "1.6.15",
|
"version": "1.6.15",
|
||||||
"resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.15.tgz",
|
"resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.15.tgz",
|
||||||
"integrity": "sha1-yrEPtJCeRByChC6v4a1kbIGARBA="
|
"integrity": "sha1-yrEPtJCeRByChC6v4a1kbIGARBA=",
|
||||||
|
"dependencies": {
|
||||||
|
"media-typer": {
|
||||||
|
"version": "0.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
|
||||||
|
"integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g="
|
||||||
|
},
|
||||||
|
"mime-types": {
|
||||||
|
"version": "2.1.17",
|
||||||
|
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz",
|
||||||
|
"integrity": "sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo="
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"unpipe": {
|
"unpipe": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
|
@ -227,6 +362,11 @@
|
||||||
"version": "0.1.19",
|
"version": "0.1.19",
|
||||||
"resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.1.19.tgz",
|
"resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.1.19.tgz",
|
||||||
"integrity": "sha1-Yx/Ad3bv2EEYvyUXGzftTQdaCrw="
|
"integrity": "sha1-Yx/Ad3bv2EEYvyUXGzftTQdaCrw="
|
||||||
|
},
|
||||||
|
"xpath.js": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/xpath.js/-/xpath.js-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-jg+qkfS4K8E7965sqaUl8mRngXiKb3WZGfONgE18pr03FUQiuSV6G+Ej4tS55B+rIQSFEIw3phdVAQ4pPqNWfQ=="
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -235,6 +375,16 @@
|
||||||
"resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.17.tgz",
|
"resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.17.tgz",
|
||||||
"integrity": "sha1-F76T6q4/O3eTWceVtBlwWogX6Gg=",
|
"integrity": "sha1-F76T6q4/O3eTWceVtBlwWogX6Gg=",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"lodash": {
|
||||||
|
"version": "4.17.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz",
|
||||||
|
"integrity": "sha512-svL3uiZf1RwhH+cWrfZn3A4+U58wbP0tGVTLQPbjplZxZ8ROD9VLuNgsRniTlLe7OlSqR79RUehXgpBW/s0IQw=="
|
||||||
|
},
|
||||||
|
"sax": {
|
||||||
|
"version": "1.2.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
|
||||||
|
"integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw=="
|
||||||
|
},
|
||||||
"xmlbuilder": {
|
"xmlbuilder": {
|
||||||
"version": "4.2.1",
|
"version": "4.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-4.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-4.2.1.tgz",
|
||||||
|
|
|
@ -53,7 +53,8 @@ Npm.depends({
|
||||||
"xpath.js": "1.0.7",
|
"xpath.js": "1.0.7",
|
||||||
"xmldom": "0.1.27",
|
"xmldom": "0.1.27",
|
||||||
"connect": "3.6.0",
|
"connect": "3.6.0",
|
||||||
"querystring": "0.2.0"
|
"querystring": "0.2.0",
|
||||||
|
"arraybuffer-to-string": "1.0.1"
|
||||||
// "xml-encryption": "0.10.0"
|
// "xml-encryption": "0.10.0"
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -100,6 +100,9 @@ Accounts.registerLoginHandler(function(loginRequest) {
|
||||||
};
|
};
|
||||||
localFindStructure = 'profile.' + Meteor.settings.saml[0].localProfileMatchAttribute;
|
localFindStructure = 'profile.' + Meteor.settings.saml[0].localProfileMatchAttribute;
|
||||||
}
|
}
|
||||||
|
if (Meteor.settings.debug) {
|
||||||
|
console.log("Looking for user with " + localFindStructure + "=" + loginResult.profile.nameID);
|
||||||
|
}
|
||||||
var user = Meteor.users.findOne({
|
var user = Meteor.users.findOne({
|
||||||
//profile[Meteor.settings.saml[0].localProfileMatchAttribute]: loginResult.profile.nameID
|
//profile[Meteor.settings.saml[0].localProfileMatchAttribute]: loginResult.profile.nameID
|
||||||
[localFindStructure]: loginResult.profile.nameID
|
[localFindStructure]: loginResult.profile.nameID
|
||||||
|
@ -109,7 +112,7 @@ Accounts.registerLoginHandler(function(loginRequest) {
|
||||||
if (Meteor.settings.saml[0].dynamicProfile) {
|
if (Meteor.settings.saml[0].dynamicProfile) {
|
||||||
if (Meteor.settings.debug) {
|
if (Meteor.settings.debug) {
|
||||||
console.log("User not found. Will dynamically create one with '" + Meteor.settings.saml[0].localProfileMatchAttribute + "' = " + loginResult.profile[Meteor.settings.saml[0].localProfileMatchAttribute]);
|
console.log("User not found. Will dynamically create one with '" + Meteor.settings.saml[0].localProfileMatchAttribute + "' = " + loginResult.profile[Meteor.settings.saml[0].localProfileMatchAttribute]);
|
||||||
console.log("Identity handle: " + profileOrEmail + " = " + JSON.stringify(profileOrEmailValue));
|
console.log("Identity handle: " + profileOrEmail + " = " + JSON.stringify(profileOrEmailValue) + " || username = " + loginResult.profile.nameID);
|
||||||
}
|
}
|
||||||
Accounts.createUser({
|
Accounts.createUser({
|
||||||
//email: loginResult.profile.email,
|
//email: loginResult.profile.email,
|
||||||
|
@ -119,6 +122,9 @@ Accounts.registerLoginHandler(function(loginRequest) {
|
||||||
|
|
||||||
//[Meteor.settings.saml[0].localProfileMatchAttribute]: loginResult.profile[Meteor.settings.saml[0].localProfileMatchAttribute]
|
//[Meteor.settings.saml[0].localProfileMatchAttribute]: loginResult.profile[Meteor.settings.saml[0].localProfileMatchAttribute]
|
||||||
});
|
});
|
||||||
|
if (Meteor.settings.debug) {
|
||||||
|
console.log("Trying to find user");
|
||||||
|
}
|
||||||
user = Meteor.users.findOne({
|
user = Meteor.users.findOne({
|
||||||
"username": loginResult.profile.nameID
|
"username": loginResult.profile.nameID
|
||||||
});
|
});
|
||||||
|
@ -275,6 +281,9 @@ middleware = function(req, res, next) {
|
||||||
break;
|
break;
|
||||||
case "logout":
|
case "logout":
|
||||||
// This is where we receive SAML LogoutResponse
|
// This is where we receive SAML LogoutResponse
|
||||||
|
if (Meteor.settings.debug) {
|
||||||
|
console.log("Handling call to 'logout' endpoint." + req.query.SAMLResponse);
|
||||||
|
}
|
||||||
_saml = new SAML(service);
|
_saml = new SAML(service);
|
||||||
_saml.validateLogoutResponse(req.query.SAMLResponse, function(err, result) {
|
_saml.validateLogoutResponse(req.query.SAMLResponse, function(err, result) {
|
||||||
if (!err) {
|
if (!err) {
|
||||||
|
@ -318,7 +327,9 @@ middleware = function(req, res, next) {
|
||||||
});
|
});
|
||||||
res.end();
|
res.end();
|
||||||
} else {
|
} else {
|
||||||
// TBD thinking of sth meaning full.
|
if (Meteor.settings.debug) {
|
||||||
|
console.log("Couldn't validate SAML Logout Response..");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
break;
|
break;
|
||||||
|
|
538
saml_utils.js
538
saml_utils.js
|
@ -10,12 +10,13 @@ const crypto = Npm.require('crypto');
|
||||||
const xmldom = Npm.require('xmldom');
|
const xmldom = Npm.require('xmldom');
|
||||||
const querystring = Npm.require('querystring');
|
const querystring = Npm.require('querystring');
|
||||||
const xmlbuilder = Npm.require('xmlbuilder');
|
const xmlbuilder = Npm.require('xmlbuilder');
|
||||||
|
const array2string = Npm.require('arraybuffer-to-string');
|
||||||
|
|
||||||
// var prefixMatch = new RegExp(/(?!xmlns)^.*:/);
|
// var prefixMatch = new RegExp(/(?!xmlns)^.*:/);
|
||||||
|
|
||||||
|
|
||||||
SAML = function(options) {
|
SAML = function(options) {
|
||||||
this.options = this.initialize(options);
|
this.options = this.initialize(options);
|
||||||
};
|
};
|
||||||
|
|
||||||
// var stripPrefix = function(str) {
|
// var stripPrefix = function(str) {
|
||||||
|
@ -23,200 +24,200 @@ SAML = function(options) {
|
||||||
// };
|
// };
|
||||||
|
|
||||||
SAML.prototype.initialize = function(options) {
|
SAML.prototype.initialize = function(options) {
|
||||||
if (!options) {
|
if (!options) {
|
||||||
options = {};
|
options = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!options.protocol) {
|
if (!options.protocol) {
|
||||||
options.protocol = 'https://';
|
options.protocol = 'https://';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!options.path) {
|
if (!options.path) {
|
||||||
options.path = '/saml/consume';
|
options.path = '/saml/consume';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!options.issuer) {
|
if (!options.issuer) {
|
||||||
options.issuer = 'onelogin_saml';
|
options.issuer = 'onelogin_saml';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.identifierFormat === undefined) {
|
if (options.identifierFormat === undefined) {
|
||||||
options.identifierFormat = 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress';
|
options.identifierFormat = 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.authnContext === undefined) {
|
if (options.authnContext === undefined) {
|
||||||
options.authnContext = 'urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport';
|
options.authnContext = 'urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport';
|
||||||
}
|
}
|
||||||
|
|
||||||
return options;
|
return options;
|
||||||
};
|
};
|
||||||
|
|
||||||
SAML.prototype.generateUniqueID = function() {
|
SAML.prototype.generateUniqueID = function() {
|
||||||
const chars = 'abcdef0123456789';
|
const chars = 'abcdef0123456789';
|
||||||
let uniqueID = 'id-';
|
let uniqueID = 'id-';
|
||||||
for (let i = 0; i < 20; i++) {
|
for (let i = 0; i < 20; i++) {
|
||||||
uniqueID += chars.substr(Math.floor((Math.random() * 15)), 1);
|
uniqueID += chars.substr(Math.floor((Math.random() * 15)), 1);
|
||||||
}
|
}
|
||||||
return uniqueID;
|
return uniqueID;
|
||||||
};
|
};
|
||||||
|
|
||||||
SAML.prototype.generateInstant = function() {
|
SAML.prototype.generateInstant = function() {
|
||||||
return new Date().toISOString();
|
return new Date().toISOString();
|
||||||
};
|
};
|
||||||
|
|
||||||
SAML.prototype.signRequest = function(xml) {
|
SAML.prototype.signRequest = function(xml) {
|
||||||
const signer = crypto.createSign('RSA-SHA1');
|
const signer = crypto.createSign('RSA-SHA1');
|
||||||
signer.update(xml);
|
signer.update(xml);
|
||||||
return signer.sign(this.options.privateKey, 'base64');
|
return signer.sign(this.options.privateKey, 'base64');
|
||||||
};
|
};
|
||||||
|
|
||||||
SAML.prototype.generateAuthorizeRequest = function(req) {
|
SAML.prototype.generateAuthorizeRequest = function(req) {
|
||||||
let id = `_${ this.generateUniqueID() }`;
|
let id = `_${ this.generateUniqueID() }`;
|
||||||
const instant = this.generateInstant();
|
const instant = this.generateInstant();
|
||||||
|
|
||||||
// Post-auth destination
|
// Post-auth destination
|
||||||
let callbackUrl;
|
let callbackUrl;
|
||||||
if (this.options.callbackUrl) {
|
if (this.options.callbackUrl) {
|
||||||
callbackUrl = this.options.callbackUrl;
|
callbackUrl = this.options.callbackUrl;
|
||||||
} else {
|
} else {
|
||||||
callbackUrl = this.options.protocol + req.headers.host + this.options.path;
|
callbackUrl = this.options.protocol + req.headers.host + this.options.path;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.options.id) {
|
if (this.options.id) {
|
||||||
id = this.options.id;
|
id = this.options.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
let request =
|
let request =
|
||||||
`<samlp:AuthnRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ID="${ id }" Version="2.0" IssueInstant="${ instant
|
`<samlp:AuthnRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ID="${ id }" Version="2.0" IssueInstant="${ instant
|
||||||
}" ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" AssertionConsumerServiceURL="${ callbackUrl }" Destination="${
|
}" ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" AssertionConsumerServiceURL="${ callbackUrl }" Destination="${
|
||||||
this.options.entryPoint }">` +
|
this.options.entryPoint }">` +
|
||||||
`<saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">${ this.options.issuer }</saml:Issuer>\n`;
|
`<saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">${ this.options.issuer }</saml:Issuer>\n`;
|
||||||
|
|
||||||
if (this.options.identifierFormat) {
|
if (this.options.identifierFormat) {
|
||||||
request += `<samlp:NameIDPolicy xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" Format="${ this.options.identifierFormat
|
request += `<samlp:NameIDPolicy xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" Format="${ this.options.identifierFormat
|
||||||
}" AllowCreate="true"></samlp:NameIDPolicy>\n`;
|
}" AllowCreate="true"></samlp:NameIDPolicy>\n`;
|
||||||
}
|
}
|
||||||
|
|
||||||
request +=
|
request +=
|
||||||
'<samlp:RequestedAuthnContext xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" Comparison="exact">' +
|
'<samlp:RequestedAuthnContext xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" Comparison="exact">' +
|
||||||
'<saml:AuthnContextClassRef xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</saml:AuthnContextClassRef></samlp:RequestedAuthnContext>\n' +
|
'<saml:AuthnContextClassRef xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</saml:AuthnContextClassRef></samlp:RequestedAuthnContext>\n' +
|
||||||
'</samlp:AuthnRequest>';
|
'</samlp:AuthnRequest>';
|
||||||
|
|
||||||
return request;
|
return request;
|
||||||
};
|
};
|
||||||
|
|
||||||
SAML.prototype.generateLogoutRequest = function(options) {
|
SAML.prototype.generateLogoutRequest = function(options) {
|
||||||
// options should be of the form
|
// options should be of the form
|
||||||
// nameId: <nameId as submitted during SAML SSO>
|
// nameId: <nameId as submitted during SAML SSO>
|
||||||
// sessionIndex: sessionIndex
|
// sessionIndex: sessionIndex
|
||||||
// --- NO SAMLsettings: <Meteor.setting.saml entry for the provider you want to SLO from
|
// --- NO SAMLsettings: <Meteor.setting.saml entry for the provider you want to SLO from
|
||||||
|
|
||||||
const id = `_${ this.generateUniqueID() }`;
|
const id = `_${ this.generateUniqueID() }`;
|
||||||
const instant = this.generateInstant();
|
const instant = this.generateInstant();
|
||||||
|
|
||||||
let request = `${ '<samlp:LogoutRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ' +
|
let request = `${ '<samlp:LogoutRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ' +
|
||||||
'xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="' }${ id }" Version="2.0" IssueInstant="${ instant
|
'xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="' }${ id }" Version="2.0" IssueInstant="${ instant
|
||||||
}" Destination="${ this.options.idpSLORedirectURL }">` +
|
}" Destination="${ this.options.idpSLORedirectURL }">` +
|
||||||
`<saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">${ this.options.issuer }</saml:Issuer>` +
|
`<saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">${ this.options.issuer }</saml:Issuer>` +
|
||||||
`<saml:NameID Format="${ this.options.identifierFormat }">${ options.nameID }</saml:NameID>` +
|
`<saml:NameID Format="${ this.options.identifierFormat }">${ options.nameID }</saml:NameID>` +
|
||||||
'</samlp:LogoutRequest>';
|
'</samlp:LogoutRequest>';
|
||||||
|
|
||||||
request = `${ '<samlp:LogoutRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ' +
|
request = `${ '<samlp:LogoutRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ' +
|
||||||
'ID="' }${ id }" ` +
|
'ID="' }${ id }" ` +
|
||||||
'Version="2.0" ' +
|
'Version="2.0" ' +
|
||||||
`IssueInstant="${ instant }" ` +
|
`IssueInstant="${ instant }" ` +
|
||||||
`Destination="${ this.options.idpSLORedirectURL }" ` +
|
`Destination="${ this.options.idpSLORedirectURL }" ` +
|
||||||
'>' +
|
'>' +
|
||||||
`<saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">${ this.options.issuer }</saml:Issuer>` +
|
`<saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">${ this.options.issuer }</saml:Issuer>` +
|
||||||
'<saml:NameID xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ' +
|
'<saml:NameID xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ' +
|
||||||
'NameQualifier="http://id.init8.net:8080/openam" ' +
|
'NameQualifier="http://id.init8.net:8080/openam" ' +
|
||||||
`SPNameQualifier="${ this.options.issuer }" ` +
|
`SPNameQualifier="${ this.options.issuer }" ` +
|
||||||
`Format="${ this.options.identifierFormat }">${
|
`Format="${ this.options.identifierFormat }">${
|
||||||
options.nameID }</saml:NameID>` +
|
options.nameID }</saml:NameID>` +
|
||||||
`<samlp:SessionIndex xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol">${ options.sessionIndex }</samlp:SessionIndex>` +
|
`<samlp:SessionIndex xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol">${ options.sessionIndex }</samlp:SessionIndex>` +
|
||||||
'</samlp:LogoutRequest>';
|
'</samlp:LogoutRequest>';
|
||||||
if (Meteor.settings.debug) {
|
if (Meteor.settings.debug) {
|
||||||
console.log('------- SAML Logout request -----------');
|
console.log('------- SAML Logout request -----------');
|
||||||
console.log(request);
|
console.log(request);
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
request,
|
request,
|
||||||
id
|
id
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
SAML.prototype.requestToUrl = function(request, operation, callback) {
|
SAML.prototype.requestToUrl = function(request, operation, callback) {
|
||||||
const self = this;
|
const self = this;
|
||||||
zlib.deflateRaw(request, function(err, buffer) {
|
zlib.deflateRaw(request, function(err, buffer) {
|
||||||
if (err) {
|
if (err) {
|
||||||
return callback(err);
|
return callback(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
const base64 = buffer.toString('base64');
|
const base64 = buffer.toString('base64');
|
||||||
let target = self.options.entryPoint;
|
let target = self.options.entryPoint;
|
||||||
|
|
||||||
if (operation === 'logout') {
|
if (operation === 'logout') {
|
||||||
if (self.options.idpSLORedirectURL) {
|
if (self.options.idpSLORedirectURL) {
|
||||||
target = self.options.idpSLORedirectURL;
|
target = self.options.idpSLORedirectURL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (target.indexOf('?') > 0) {
|
if (target.indexOf('?') > 0) {
|
||||||
target += '&';
|
target += '&';
|
||||||
} else {
|
} else {
|
||||||
target += '?';
|
target += '?';
|
||||||
}
|
}
|
||||||
|
|
||||||
// TBD. We should really include a proper RelayState here
|
// TBD. We should really include a proper RelayState here
|
||||||
let relayState;
|
let relayState;
|
||||||
if (operation === 'logout') {
|
if (operation === 'logout') {
|
||||||
// in case of logout we want to be redirected back to the Meteor app.
|
// in case of logout we want to be redirected back to the Meteor app.
|
||||||
relayState = Meteor.absoluteUrl();
|
relayState = Meteor.absoluteUrl();
|
||||||
} else {
|
} else {
|
||||||
relayState = self.options.provider;
|
relayState = self.options.provider;
|
||||||
}
|
}
|
||||||
|
|
||||||
const samlRequest = {
|
const samlRequest = {
|
||||||
SAMLRequest: base64,
|
SAMLRequest: base64,
|
||||||
RelayState: relayState
|
RelayState: relayState
|
||||||
};
|
};
|
||||||
|
|
||||||
if (self.options.privateCert) {
|
if (self.options.privateCert) {
|
||||||
samlRequest.SigAlg = 'http://www.w3.org/2000/09/xmldsig#rsa-sha1';
|
samlRequest.SigAlg = 'http://www.w3.org/2000/09/xmldsig#rsa-sha1';
|
||||||
samlRequest.Signature = self.signRequest(querystring.stringify(samlRequest));
|
samlRequest.Signature = self.signRequest(querystring.stringify(samlRequest));
|
||||||
}
|
}
|
||||||
|
|
||||||
target += querystring.stringify(samlRequest);
|
target += querystring.stringify(samlRequest);
|
||||||
|
|
||||||
if (Meteor.settings.debug) {
|
if (Meteor.settings.debug) {
|
||||||
console.log(`requestToUrl: ${ target }`);
|
console.log(`requestToUrl: ${ target }`);
|
||||||
}
|
}
|
||||||
if (operation === 'logout') {
|
if (operation === 'logout') {
|
||||||
// in case of logout we want to be redirected back to the Meteor app.
|
// in case of logout we want to be redirected back to the Meteor app.
|
||||||
return callback(null, target);
|
return callback(null, target);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
callback(null, target);
|
callback(null, target);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
SAML.prototype.getAuthorizeUrl = function(req, callback) {
|
SAML.prototype.getAuthorizeUrl = function(req, callback) {
|
||||||
const request = this.generateAuthorizeRequest(req);
|
const request = this.generateAuthorizeRequest(req);
|
||||||
|
|
||||||
this.requestToUrl(request, 'authorize', callback);
|
this.requestToUrl(request, 'authorize', callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
SAML.prototype.getLogoutUrl = function(req, callback) {
|
SAML.prototype.getLogoutUrl = function(req, callback) {
|
||||||
const request = this.generateLogoutRequest(req);
|
const request = this.generateLogoutRequest(req);
|
||||||
|
|
||||||
this.requestToUrl(request, 'logout', callback);
|
this.requestToUrl(request, 'logout', callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
SAML.prototype.certToPEM = function(cert) {
|
SAML.prototype.certToPEM = function(cert) {
|
||||||
cert = cert.match(/.{1,64}/g).join('\n');
|
cert = cert.match(/.{1,64}/g).join('\n');
|
||||||
cert = `-----BEGIN CERTIFICATE-----\n${ cert }`;
|
cert = `-----BEGIN CERTIFICATE-----\n${ cert }`;
|
||||||
cert = `${ cert }\n-----END CERTIFICATE-----\n`;
|
cert = `${ cert }\n-----END CERTIFICATE-----\n`;
|
||||||
return cert;
|
return cert;
|
||||||
};
|
};
|
||||||
|
|
||||||
// functionfindChilds(node, localName, namespace) {
|
// functionfindChilds(node, localName, namespace) {
|
||||||
|
@ -230,7 +231,7 @@ SAML.prototype.certToPEM = function(cert) {
|
||||||
// return res;
|
// return res;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
SAML.prototype.validateStatus = function (doc) {
|
SAML.prototype.validateStatus = function(doc) {
|
||||||
let successStatus = false;
|
let successStatus = false;
|
||||||
let status = '';
|
let status = '';
|
||||||
let messageText = '';
|
let messageText = '';
|
||||||
|
@ -251,81 +252,94 @@ SAML.prototype.validateStatus = function (doc) {
|
||||||
successStatus = true;
|
successStatus = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return { success :successStatus, message :messageText, statusCode : status};
|
return {
|
||||||
|
success: successStatus,
|
||||||
|
message: messageText,
|
||||||
|
statusCode: status
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
SAML.prototype.validateSignature = function(xml, cert) {
|
SAML.prototype.validateSignature = function(xml, cert) {
|
||||||
const self = this;
|
const self = this;
|
||||||
|
|
||||||
const doc = new xmldom.DOMParser().parseFromString(xml);
|
const doc = new xmldom.DOMParser().parseFromString(xml);
|
||||||
const signature = xmlCrypto.xpath(doc, '//*[local-name(.)=\'Signature\' and namespace-uri(.)=\'http://www.w3.org/2000/09/xmldsig#\']')[0];
|
const signature = xmlCrypto.xpath(doc, '//*[local-name(.)=\'Signature\' and namespace-uri(.)=\'http://www.w3.org/2000/09/xmldsig#\']')[0];
|
||||||
|
|
||||||
const sig = new xmlCrypto.SignedXml();
|
const sig = new xmlCrypto.SignedXml();
|
||||||
|
|
||||||
sig.keyInfoProvider = {
|
sig.keyInfoProvider = {
|
||||||
getKeyInfo(/*key*/) {
|
getKeyInfo( /*key*/ ) {
|
||||||
return '<X509Data></X509Data>';
|
return '<X509Data></X509Data>';
|
||||||
},
|
},
|
||||||
getKey(/*keyInfo*/) {
|
getKey( /*keyInfo*/ ) {
|
||||||
return self.certToPEM(cert);
|
return self.certToPEM(cert);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
sig.loadSignature(signature);
|
sig.loadSignature(signature);
|
||||||
|
|
||||||
return sig.checkSignature(xml);
|
return sig.checkSignature(xml);
|
||||||
};
|
};
|
||||||
|
|
||||||
SAML.prototype.validateLogoutResponse = function(samlResponse, callback) {
|
SAML.prototype.validateLogoutResponse = function(samlResponse, callback) {
|
||||||
const self = this;
|
const self = this;
|
||||||
|
const compressedSAMLResponse = new Buffer(samlResponse, 'base64');
|
||||||
const compressedSAMLResponse = new Buffer(samlResponse, 'base64');
|
zlib.inflateRaw(compressedSAMLResponse, function(err, decoded) {
|
||||||
zlib.inflateRaw(compressedSAMLResponse, function(err, decoded) {
|
if (err) {
|
||||||
|
if (Meteor.settings.debug) {
|
||||||
if (err) {
|
console.log("Error while inflating." + err);
|
||||||
if (Meteor.settings.debug) {
|
}
|
||||||
console.log(err);
|
} else {
|
||||||
}
|
console.log("construvting new DOM parser: " + Object.prototype.toString.call(decoded));
|
||||||
} else {
|
console.log(">>>>" + decoded);
|
||||||
const doc = new xmldom.DOMParser().parseFromString(decoded, 'text/xml');
|
const doc = new xmldom.DOMParser().parseFromString(array2string(decoded), 'text/xml');
|
||||||
if (doc) {
|
if (doc) {
|
||||||
const response = doc.getElementsByTagNameNS('urn:oasis:names:tc:SAML:2.0:protocol', 'LogoutResponse');
|
const response = doc.getElementsByTagNameNS('urn:oasis:names:tc:SAML:2.0:protocol', 'LogoutResponse')[0];
|
||||||
if (response) {
|
if (response) {
|
||||||
|
|
||||||
// TBD. Check if this msg corresponds to one we sent
|
// TBD. Check if this msg corresponds to one we sent
|
||||||
const inResponseTo = response.getAttribute('InResponseTo');
|
var inResponseTo;
|
||||||
if (Meteor.settings.debug) {
|
try {
|
||||||
console.log(`In Response to: ${ inResponseTo }`);
|
inResponseTo = response.getAttribute('InResponseTo');
|
||||||
|
if (Meteor.settings.debug) {
|
||||||
|
console.log(`In Response to: ${ inResponseTo }`);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
if (Meteor.settings.debug) {
|
||||||
|
console.log("Caught error: " + e);
|
||||||
|
const msg = doc.getElementsByTagNameNS('urn:oasis:names:tc:SAML:2.0:protocol', 'StatusMessage');
|
||||||
|
console.log("Unexpected msg from IDP. Does your session still exist at IDP? Idp returned: \n" + msg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
let statusValidateObj = self.validateStatus(doc);
|
let statusValidateObj = self.validateStatus(doc);
|
||||||
|
|
||||||
if(statusValidateObj.success) {
|
if (statusValidateObj.success) {
|
||||||
callback(null, inResponseTo);
|
callback(null, inResponseTo);
|
||||||
}else{
|
} else {
|
||||||
callback('Error. Logout not confirmed by IDP', null);
|
callback('Error. Logout not confirmed by IDP', null);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
callback('No Response Found', null);
|
callback('No Response Found', null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
SAML.prototype.validateResponse = function(samlResponse, relayState, callback) {
|
SAML.prototype.validateResponse = function(samlResponse, relayState, callback) {
|
||||||
const self = this;
|
const self = this;
|
||||||
const xml = new Buffer(samlResponse, 'base64').toString('utf8');
|
const xml = new Buffer(samlResponse, 'base64').toString('utf8');
|
||||||
// We currently use RelayState to save SAML provider
|
// We currently use RelayState to save SAML provider
|
||||||
if (Meteor.settings.debug) {
|
if (Meteor.settings.debug) {
|
||||||
console.log(`Validating response with relay state: ${ xml }`);
|
console.log(`Validating response with relay state: ${ xml }`);
|
||||||
}
|
}
|
||||||
const parser = new xml2js.Parser({
|
const parser = new xml2js.Parser({
|
||||||
explicitRoot: true
|
explicitRoot: true
|
||||||
});
|
});
|
||||||
|
|
||||||
const doc = new xmldom.DOMParser().parseFromString(xml, 'text/xml');
|
const doc = new xmldom.DOMParser().parseFromString(xml, 'text/xml');
|
||||||
|
|
||||||
|
@ -408,28 +422,28 @@ SAML.prototype.validateResponse = function(samlResponse, relayState, callback) {
|
||||||
|
|
||||||
const attributeStatement = assertion.getElementsByTagNameNS('urn:oasis:names:tc:SAML:2.0:assertion', 'AttributeStatement')[0];
|
const attributeStatement = assertion.getElementsByTagNameNS('urn:oasis:names:tc:SAML:2.0:assertion', 'AttributeStatement')[0];
|
||||||
if (attributeStatement) {
|
if (attributeStatement) {
|
||||||
if (Meteor.settings.debug) {
|
if (Meteor.settings.debug) {
|
||||||
console.log("Attribute Statement found in SAML response: " + attributeStatement);
|
console.log("Attribute Statement found in SAML response: " + attributeStatement);
|
||||||
}
|
}
|
||||||
const attributes = attributeStatement.getElementsByTagNameNS('urn:oasis:names:tc:SAML:2.0:assertion', 'Attribute');
|
const attributes = attributeStatement.getElementsByTagNameNS('urn:oasis:names:tc:SAML:2.0:assertion', 'Attribute');
|
||||||
if (Meteor.settings.debug) {
|
if (Meteor.settings.debug) {
|
||||||
console.log("Attributes will be processed: " + attributes.length);
|
console.log("Attributes will be processed: " + attributes.length);
|
||||||
}
|
}
|
||||||
if (attributes) {
|
if (attributes) {
|
||||||
for (let i = 0; i < attributes.length; i++) {
|
for (let i = 0; i < attributes.length; i++) {
|
||||||
const value = attributes[i].getElementsByTagNameNS('urn:oasis:names:tc:SAML:2.0:assertion', 'AttributeValue')[0];
|
const value = attributes[i].getElementsByTagNameNS('urn:oasis:names:tc:SAML:2.0:assertion', 'AttributeValue')[0];
|
||||||
if (Meteor.settings.debug) {
|
if (Meteor.settings.debug) {
|
||||||
console.log("Name: " + attributes[i]);
|
console.log("Name: " + attributes[i]);
|
||||||
console.log(`Adding attrinute from SAML response to profile:` + attributes[i].getAttribute('Name') + " = " + value.textContent);
|
console.log(`Adding attrinute from SAML response to profile:` + attributes[i].getAttribute('Name') + " = " + value.textContent);
|
||||||
}
|
}
|
||||||
profile[attributes[i].getAttribute('Name')] = value.textContent;
|
profile[attributes[i].getAttribute('Name')] = value.textContent;
|
||||||
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (Meteor.settings.debug) {
|
if (Meteor.settings.debug) {
|
||||||
console.log("No Attributes found in SAML attribute statement.");
|
console.log("No Attributes found in SAML attribute statement.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!profile.mail && profile['urn:oid:0.9.2342.19200300.100.1.3']) {
|
if (!profile.mail && profile['urn:oid:0.9.2342.19200300.100.1.3']) {
|
||||||
// See http://www.incommonfederation.org/attributesummary.html for definition of attribute OIDs
|
// See http://www.incommonfederation.org/attributesummary.html for definition of attribute OIDs
|
||||||
|
@ -440,10 +454,10 @@ SAML.prototype.validateResponse = function(samlResponse, relayState, callback) {
|
||||||
profile.email = profile.mail;
|
profile.email = profile.mail;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (Meteor.settings.debug) {
|
if (Meteor.settings.debug) {
|
||||||
console.log("No Attribute Statement found in SAML response.");
|
console.log("No Attribute Statement found in SAML response.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!profile.email && profile.nameID && profile.nameIDFormat && profile.nameIDFormat.indexOf('emailAddress') >= 0) {
|
if (!profile.email && profile.nameID && profile.nameIDFormat && profile.nameIDFormat.indexOf('emailAddress') >= 0) {
|
||||||
profile.email = profile.nameID;
|
profile.email = profile.nameID;
|
||||||
|
@ -463,9 +477,9 @@ SAML.prototype.validateResponse = function(samlResponse, relayState, callback) {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}else{
|
} else {
|
||||||
return callback(new Error(`Status is: ${ statusValidateObj.statusCode }`), null, false);
|
return callback(new Error(`Status is: ${ statusValidateObj.statusCode }`), null, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -473,68 +487,74 @@ SAML.prototype.validateResponse = function(samlResponse, relayState, callback) {
|
||||||
let decryptionCert;
|
let decryptionCert;
|
||||||
SAML.prototype.generateServiceProviderMetadata = function(callbackUrl) {
|
SAML.prototype.generateServiceProviderMetadata = function(callbackUrl) {
|
||||||
|
|
||||||
if (!decryptionCert) {
|
if (!decryptionCert) {
|
||||||
decryptionCert = this.options.privateCert;
|
decryptionCert = this.options.privateCert;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.options.callbackUrl && !callbackUrl) {
|
if (!this.options.callbackUrl && !callbackUrl) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
'Unable to generate service provider metadata when callbackUrl option is not set');
|
'Unable to generate service provider metadata when callbackUrl option is not set');
|
||||||
}
|
}
|
||||||
|
|
||||||
const metadata = {
|
const metadata = {
|
||||||
'EntityDescriptor': {
|
'EntityDescriptor': {
|
||||||
'@xmlns': 'urn:oasis:names:tc:SAML:2.0:metadata',
|
'@xmlns': 'urn:oasis:names:tc:SAML:2.0:metadata',
|
||||||
'@xmlns:ds': 'http://www.w3.org/2000/09/xmldsig#',
|
'@xmlns:ds': 'http://www.w3.org/2000/09/xmldsig#',
|
||||||
'@entityID': this.options.issuer,
|
'@entityID': this.options.issuer,
|
||||||
'SPSSODescriptor': {
|
'SPSSODescriptor': {
|
||||||
'@protocolSupportEnumeration': 'urn:oasis:names:tc:SAML:2.0:protocol',
|
'@protocolSupportEnumeration': 'urn:oasis:names:tc:SAML:2.0:protocol',
|
||||||
'SingleLogoutService': {
|
'SingleLogoutService': {
|
||||||
'@Binding': 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect',
|
'@Binding': 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect',
|
||||||
'@Location': `${ Meteor.absoluteUrl() }_saml/logout/${ this.options.provider }/`,
|
'@Location': `${ Meteor.absoluteUrl() }_saml/logout/${ this.options.provider }/`,
|
||||||
'@ResponseLocation': `${ Meteor.absoluteUrl() }_saml/logout/${ this.options.provider }/`
|
'@ResponseLocation': `${ Meteor.absoluteUrl() }_saml/logout/${ this.options.provider }/`
|
||||||
},
|
},
|
||||||
'NameIDFormat': this.options.identifierFormat,
|
'NameIDFormat': this.options.identifierFormat,
|
||||||
'AssertionConsumerService': {
|
'AssertionConsumerService': {
|
||||||
'@index': '1',
|
'@index': '1',
|
||||||
'@isDefault': 'true',
|
'@isDefault': 'true',
|
||||||
'@Binding': 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST',
|
'@Binding': 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST',
|
||||||
'@Location': callbackUrl
|
'@Location': callbackUrl
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (this.options.privateKey) {
|
if (this.options.privateKey) {
|
||||||
if (!decryptionCert) {
|
if (!decryptionCert) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
'Missing decryptionCert while generating metadata for decrypting service provider');
|
'Missing decryptionCert while generating metadata for decrypting service provider');
|
||||||
}
|
}
|
||||||
|
|
||||||
decryptionCert = decryptionCert.replace(/-+BEGIN CERTIFICATE-+\r?\n?/, '');
|
decryptionCert = decryptionCert.replace(/-+BEGIN CERTIFICATE-+\r?\n?/, '');
|
||||||
decryptionCert = decryptionCert.replace(/-+END CERTIFICATE-+\r?\n?/, '');
|
decryptionCert = decryptionCert.replace(/-+END CERTIFICATE-+\r?\n?/, '');
|
||||||
decryptionCert = decryptionCert.replace(/\r\n/g, '\n');
|
decryptionCert = decryptionCert.replace(/\r\n/g, '\n');
|
||||||
|
|
||||||
metadata['EntityDescriptor']['SPSSODescriptor']['KeyDescriptor'] = {
|
metadata['EntityDescriptor']['SPSSODescriptor']['KeyDescriptor'] = {
|
||||||
'ds:KeyInfo': {
|
'ds:KeyInfo': {
|
||||||
'ds:X509Data': {
|
'ds:X509Data': {
|
||||||
'ds:X509Certificate': {
|
'ds:X509Certificate': {
|
||||||
'#text': decryptionCert
|
'#text': decryptionCert
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'EncryptionMethod': [
|
'EncryptionMethod': [
|
||||||
// this should be the set that the xmlenc library supports
|
// this should be the set that the xmlenc library supports
|
||||||
{'@Algorithm': 'http://www.w3.org/2001/04/xmlenc#aes256-cbc'},
|
{
|
||||||
{'@Algorithm': 'http://www.w3.org/2001/04/xmlenc#aes128-cbc'},
|
'@Algorithm': 'http://www.w3.org/2001/04/xmlenc#aes256-cbc'
|
||||||
{'@Algorithm': 'http://www.w3.org/2001/04/xmlenc#tripledes-cbc'}
|
},
|
||||||
]
|
{
|
||||||
};
|
'@Algorithm': 'http://www.w3.org/2001/04/xmlenc#aes128-cbc'
|
||||||
}
|
},
|
||||||
|
{
|
||||||
|
'@Algorithm': 'http://www.w3.org/2001/04/xmlenc#tripledes-cbc'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
return xmlbuilder.create(metadata).end({
|
return xmlbuilder.create(metadata).end({
|
||||||
pretty: true,
|
pretty: true,
|
||||||
indent: ' ',
|
indent: ' ',
|
||||||
newline: '\n'
|
newline: '\n'
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue