{"_id":"@dshiells/saml2-js","_rev":"1-01a047494ca44f4e8f22d3dbdfdc704d","name":"@dshiells/saml2-js","dist-tags":{"latest":"3.0.3"},"versions":{"3.0.3":{"name":"@dshiells/saml2-js","version":"3.0.3","description":"SAML 2.0 node helpers","author":{"name":"dshiells"},"license":"Apache-2.0","main":"index.js","engines":{"node":">=10.x"},"scripts":{"build":"coffee --bare -c -o lib-js lib","test":"NODE_ENV=test mocha --require coffee-script/register test/*.coffee","test-cov":"NODE_ENV=test nyc --extension .coffee -r html -r text mocha --require coffee-script/register test/*.coffee","prepare":"npm run build"},"repository":{"type":"git","url":"git://github.com/damienshiells/saml2.git"},"keywords":["saml","node"],"bugs":{"url":"https://github.com/damienshiells/saml2/issues"},"devDependencies":{"coffee-script":"^1.12.0","mocha":"^8.2.0","nyc":"^15.0.0"},"dependencies":{"async":"^3.2.0","debug":"^4.3.0","underscore":"^1.8.0","xml-crypto":"^2.0.0","xml-encryption":"^2.0.0","xml2js":"^0.4.0","xmlbuilder2":"^2.4.0","@xmldom/xmldom":"^0.7.0"},"gitHead":"0dfe7ad8f4c71123a7950411bb5d82149eb97277","homepage":"https://github.com/damienshiells/saml2#readme","_id":"@dshiells/saml2-js@3.0.3","_nodeVersion":"16.13.2","_npmVersion":"8.1.2","dist":{"integrity":"sha512-1VQ7lheUP2gVQjHwyg+DJs4Iu+LbjH/cia15h6mi45tvP2DmCu932v8nLwJnnnkpFmi44qiYck168SmME2oc4A==","shasum":"ab77c0ff38686ccb774e2d077520246903cd3aeb","tarball":"https://registry.npmjs.org/@dshiells/saml2-js/-/saml2-js-3.0.3.tgz","fileCount":49,"unpackedSize":241744,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJiCn5DCRA9TVsSAnZWagAAzTkP/jyXDDhKXXdmscXHg+dJ\njzWJ75aF/Nr2whbNTsIdgC9R48ONJl0Z01bPucwz7vfkwU44EZ/CUqy5vWSw\nVsiicjQTkE/CifVKHg8n1bgpJCmWVAZpV7Umgkm3SdaVLeyZuCsyRXsLgqwP\nf/dEPJIOjMZsDaJOb8oGvZkW7g7T/7kBPdfTR/RqcJTbbbR7Zm8ctJpzcyKD\nhwpTV4RPhiYrP/W89Hw43IGpAITo04741WH7+IGDDLgsZL+tn16cvbe143EY\nJtE4vxBRAcARwTdEMRyjWr92AL0HwDfU3iA81HwWROxswawZljG1vYFUb8Ve\nsYOM9Hy7ZHCsUX11k7h+4B+yFCy7+yebuRuA7qSEXtPbhUTfVdb29xJVLGEt\ngC5zKZwHRvu3uXvRg5qVJfI6Fzjji8yTb/TpW2o8kEuiusugBWghj1wmoF8b\neRtxMeWM1YFGw1K1uxpluOMD1LIj4Ml4VvruSCQAv/Z4H2ySbC/4kWpuWB7G\nbjW+91Fw4REpVE/EdPv1vJoX7zsLlikzOT3b9ybtWlM57Yloe+77AksFPYA8\nCzvaNun1Vnx66bOzfyYuzW7BPnr+nkkW9iNwttDBtXUMhUXbbCyMcRl4xbaY\nNNO91JB2aafjbxkDSPlZ/XjVcDKpyQztrHRYz6s569MX620Vq6//D62FXPxR\np7aS\r\n=78aQ\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHCEp0d1Z2IZy+E/6B4qatMYr0bI4WA0o2mUfnDD+5JhAiA7DqCwt00zn6DY8wYwAmDHNfUskgCDzKoP7h3c4LfB6w=="}]},"_npmUser":{"name":"dshiells","email":"damienshiells@gmail.com"},"directories":{},"maintainers":[{"name":"dshiells","email":"damienshiells@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/saml2-js_3.0.3_1644854851431_0.7789943529678953"},"_hasShrinkwrap":false}},"time":{"created":"2022-02-14T16:07:31.364Z","3.0.3":"2022-02-14T16:07:31.567Z","modified":"2022-04-05T05:44:49.648Z"},"maintainers":[{"name":"dshiells","email":"damienshiells@gmail.com"}],"description":"SAML 2.0 node helpers","homepage":"https://github.com/damienshiells/saml2#readme","keywords":["saml","node"],"repository":{"type":"git","url":"git://github.com/damienshiells/saml2.git"},"author":{"name":"dshiells"},"bugs":{"url":"https://github.com/damienshiells/saml2/issues"},"license":"Apache-2.0","readme":"# SAML2-js\n\n[![CircleCI](https://circleci.com/gh/Clever/saml2/tree/master.svg?style=svg)](https://circleci.com/gh/Clever/saml2/tree/master)\n\n`saml2-js` is a node module that abstracts away the complexities of the SAML protocol behind an easy to use interface.\n\n## Usage\n\nInstall with [npm](https://www.npmjs.com/).\n\n```bash\n  npm install saml2-js --save\n```\n\nInclude the SAML library.\n\n```javascript\n  var saml2 = require('saml2-js');\n```\n\n## Documentation\n\nThis library exports two constructors.\n\n- [`ServiceProvider`](#ServiceProvider) - Represents a service provider that relies on a trusted [`IdentityProvider`](#IdentityProvider) for authentication and authorization in the SAML flow.\n- [`IdentityProvider`](#IdentityProvider) - Represents an online service that authenticates users in the SAML flow.\n\n<a name=\"note_options\" />\n\n**Note:**  Some options can be set on the [SP](#ServiceProvider), [IdP](#IdentityProvider), and/or on a per-method basis. For the options that are set in multiple places, they are overridden in the following order: per-method basis *overrides* [IdP](#IdentityProvider) which *overrides* [SP](#ServiceProvider).\n\n<a name=\"ServiceProvider\" />\n\n### ServiceProvider(options)\nRepresents a service provider that relies on a trusted [`IdentityProvider`](#IdentityProvider) for authentication and authorization in the SAML flow.\n\n#### Options\nAn object that can contain the below options.  All options are strings, unless specified otherwise.  See [note](#note_options) for more information on options.\n\n- `entity_id` - **Required** - Unique identifier for the service provider, often the URL of the metadata file.\n- `private_key` - **Required** - (PEM format string) - Private key for the service provider.\n- `certificate` - **Required** - (PEM format string) - Certificate for the service provider.\n- `assert_endpoint` - **Required** - URL of service provider assert endpoint.\n- `alt_private_keys` - (Array of PEM format strings) - Additional private keys to use when attempting to decrypt responses. Useful for adding backward-compatibility for old certificates after a rollover.\n- `alt_certs` - (Array of PEM format strings) - Additional certificates to expose in the SAML metadata. Useful for staging new certificates for rollovers.\n- `audience` - (String or RegExp) — If set, at least one of the `<Audience>` values within the `<AudienceRestriction>` condition of a SAML authentication response must match. Defaults to `entity_id`.\n- `notbefore_skew` - (Number) – To account for clock skew between IdP and SP, accept responses with a NotBefore condition ahead of the current time (according to our clock) by this number of seconds. Defaults to 1. Set it to 0 for optimum security but no tolerance for clock skew.\n- `force_authn` - (Boolean) - If true, forces re-authentication of users even if the user has a SSO session with the [IdP](#IdentityProvider).  This can also be configured on the [IdP](#IdentityProvider) or on a per-method basis.\n- `auth_context` - Specifies `AuthnContextClassRef`.  This can also be configured on a per-method basis.\n- `nameid_format` - Format for Name ID.  This can also be configured on a per-method basis.\n- `sign_get_request` - (Boolean) - If true, signs the request.  This can also be configured on the [IdP](#IdentityProvider) or on a per-method basis.\n- `allow_unencrypted_assertion` - (Boolean) - If true, allows unencrypted assertions.  This can also be configured on the [IdP](#IdentityProvider) or on a per-method basis.\n\n#### Returns the following functions\n- [`create_login_request_url(IdP, options, cb)`](#create_login_request_url) - Get a URL to initiate a login.\n- [`redirect_assert(IdP, options, cb)`](#redirect_assert) - Gets a SAML response object if the login attempt is valid, used for redirect binding.\n- [`post_assert(IdP, options, cb)`](#post_assert) - Gets a SAML response object if the login attempt is valid, used for post binding.\n- [`create_logout_request_url(IdP, options, cb)`](#create_logout_request_url)- Creates a SAML Request URL to initiate a user logout.\n- [`create_logout_response_url(IdP, options, cb)`](#create_logout_response_url) - Creates a SAML Response URL to confirm a successful [IdP](#IdentityProvider) initiated logout.\n- [`create_metadata()`](#create_metadata) - Returns the XML metadata used during the initial SAML configuration.\n\n#### Example\n```javascript\n\n  var sp_options = {\n    entity_id: \"https://sp.example.com/metadata.xml\",\n    private_key: fs.readFileSync(\"key-file.pem\").toString(),\n    certificate: fs.readFileSync(\"cert-file.crt\").toString(),\n    assert_endpoint: \"https://sp.example.com/assert\",\n    force_authn: true,\n    auth_context: { comparison: \"exact\", class_refs: [\"urn:oasis:names:tc:SAML:1.0:am:password\"] },\n    nameid_format: \"urn:oasis:names:tc:SAML:2.0:nameid-format:transient\",\n    sign_get_request: false,\n    allow_unencrypted_assertion: true\n  }\n\n  // Call service provider constructor with options\n  var sp = new saml2.ServiceProvider(sp_options);\n\n  // Example use of service provider.\n  // Call metadata to get XML metatadata used in configuration.\n  var metadata = sp.create_metadata();\n\n```\n\n#### Service provider function definitions\n\n<a name=\"create_login_request_url\" />\n\n##### create_login_request_url(IdP, options, cb)\nGet a URL to initiate a login.\n\nTakes the following arguments:\n- `IdP` - [IdP](#IdentityProvider)\n- `options` - An object that can contain the below options.  All options are strings, unless specified otherwise.  See [note](#note_options) for more information on options.\n  - `relay_state` - SAML relay state.\n  - `auth_context` - Specifies `AuthnContextClassRef`.  This can also be configured on the [SP](#ServiceProvider).\n  - `nameid_format` - Format for Name ID.  This can also be configured on the [SP](#ServiceProvider).\n  - `force_authn`- (Boolean) - If true, forces re-authentication of users even if the user has a SSO session with the [IdP](#IdentityProvider).  This can also be configured on the [IdP](#IdentityProvider) or [SP](#ServiceProvider).\n  - `sign_get_request` - (Boolean) - If true, signs the request.  This can also be configured on the [IdP](#IdentityProvider) or [SP](#ServiceProvider).\n- `cb(error, login_url, request_id)` - Callback called with the login URL and ID of the request.\n\n\n<a name=\"redirect_assert\" />\n\n##### redirect_assert(IdP, options, cb)\nGets a SAML response object if the login attempt is valid, used for redirect binding.\n\nTakes the following arguments:\n- `IdP` - [IdP](#IdentityProvider)\n- `options` - An object that can contain the below options.  All options are strings, unless specified otherwise.  See [note](#note_options) for more information on options.\n  - `request_body` - (Object) - An object containing the parsed query string parameters.  This object should contain the value for either a `SAMLResponse` or `SAMLRequest`.\n  - `allow_unencrypted_assertion` - (Boolean) - If true, allows unencrypted assertions.  This can also be configured on the [IdP](#IdentityProvider) or [SP](#ServiceProvider).\n  - `require_session_index` - (Boolean) - If false, allow the assertion to be valid without a `SessionIndex` attribute on the `AuthnStatement` node.\n- `cb(error, response)` - Callback called with the [request response](#assert_response).\n\n<a name=\"assert_response\" />\nExample of the SAML assert response returned:\n\n  ```javascript\n  { response_header:\n     { id: '_abc-1',\n       destination: 'https://sp.example.com/assert',\n       in_response_to: '_abc-2' },\n    type: 'authn_response',\n    user:\n     { name_id: 'nameid',\n       session_index: '_abc-3',\n       attributes:\n        { 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname': [ 'Test' ] } } }\n  ```\n\n<a name=\"post_assert\" />\n\n##### post_assert(IdP, options, cb)\nGets a SAML response object if the login attempt is valid, used for post binding.\n\nTakes the following arguments:\n- `IdP` - [IdP](#IdentityProvider)\n- `options` - An object that can contain the below options.  All options are strings, unless specified otherwise.  See [note](#note_options) for more information on options.\n  - `request_body` - (Object) - An object containing the parsed query string parameters.  This object should contain the value for either a `SAMLResponse` or `SAMLRequest`.\n  - `allow_unencrypted_assertion` - (Boolean) - If true, allows unencrypted assertions.  This can also be configured on the [IdP](#IdentityProvider) or [SP](#ServiceProvider).\n  - `require_session_index` - (Boolean) - If false, allow the assertion to be valid without a `SessionIndex` attribute on the `AuthnStatement` node.\n  - `audience` - (String or RegExp) — If set, at least one of the `<Audience>` values within the `<AudienceRestriction>` condition of a SAML authentication response must match. Defaults to `entity_id`.\n  - `notbefore_skew` - (Number) – To account for clock skew between IdP and SP, accept responses with a NotBefore condition ahead of the current time (according to our clock) by this number of seconds. Defaults to 1. Set it to 0 for optimum security but no tolerance for clock skew.\n- `cb(error, response)` - Callback called with the [request response](#assert_response).\n\n\n<a name=\"create_logout_request_url\" />\n\n##### create_logout_request_url(IdP, options, cb)\nCreates a SAML Request URL to initiate a user logout.\n\nTakes the following arguments:\n- `IdP` - [IdP](#IdentityProvider).  Note: Can pass `sso_logout_url` instead of IdP.\n- `options` - An object that can contain the below options.  All options are strings, unless specified otherwise.  See [note](#note_options) for more information on options.\n  + `name_id` - Format for Name ID.  This can also be configured on a per-method basis.\n  + `session_index` - Session index to use for creating logout request.\n  + `allow_unencrypted_assertion` - (Boolean) - If true, allows unencrypted assertions.  This can also be configured on the [IdP](#IdentityProvider) or [SP](#ServiceProvider).\n  + `sign_get_request` - (Boolean) - If true, signs the request.  This can also be configured on the [IdP](#IdentityProvider) or [SP](#ServiceProvider).\n  + `relay_state` - SAML relay state.\n- `cb(error, request_url)` - Callback called with the logout request url.\n\n\n<a name=\"create_logout_response_url\" />\n\n##### create_logout_response_url(IdP, options, cb)\nCreates a SAML Response URL to confirm a successful [IdP](#IdentityProvider) initiated logout.\n\nTakes the following arguments:\n- `IdP` - [IdP](#IdentityProvider).  Note: Can pass `sso_logout_url` instead of IdP.\n- `options` - An object that can contain the below options.  All options are strings, unless specified otherwise.  See [note](#note_options) for more information on options.\n  + `in_response_to` - The ID of the request that this is in response to. Should be checked against any sent request IDs.\n  + `sign_get_request` - (Boolean) - If true, signs the request.  This can also be configured on the [IdP](#IdentityProvider) or [SP](#ServiceProvider).\n  + `relay_state` - SAML relay state.\n- `cb(error, response_url)` - Callback called with the logout response url.\n\n<a name=\"create_metadata\" />\n\n##### create_metadata()\nReturns the XML metadata used during the initial SAML configuration.\n\n<a name=\"IdentityProvider\" />\n\n### IdentityProvider(options)\nRepresents an online service that authenticates users in the SAML flow.\n\nReturns no functions, exists solely to be passed to an [SP](#ServiceProvider) function.\n\n#### Options\nAn object that can contain the below options.  All options are strings, unless specified otherwise.  See [note](#note_options) for more information on options.\n\n- `sso_login_url` - **Required** - Login url to use during a login request.\n- `sso_logout_url` - **Required** - Logout url to use during a logout request.\n- `certificates` - **Required** - (PEM format string or array of PEM format strings) - Certificate or certificates (array of certificate) for the identity provider.\n- `force_authn` - (Boolean) - If true, forces re-authentication of users even if the user has a SSO session with the [IdP](#IdentityProvider).  This can also be configured on the [SP](#ServiceProvider) or on a per-method basis.\n- `sign_get_request` - (Boolean) - If true, signs the request.  This can also be configured on the [[SP](#ServiceProvider) or on a per-method basis.\n- `allow_unencrypted_assertion` - (Boolean) - If true, allows unencrypted assertions.  This can also be configured on the [SP](#ServiceProvider) or on a per-method basis.\n\n#### Example\n```javascript\n\n  // Initialize options object\n  var idp_options = {\n    sso_login_url: \"https://idp.example.com/login\",\n    sso_logout_url: \"https://idp.example.com/logout\",\n    certificates: [fs.readFileSync(\"cert-file1.crt\").toString(), fs.readFileSync(\"cert-file2.crt\").toString()],\n    force_authn: true,\n    sign_get_request: false,\n    allow_unencrypted_assertion: false\n  };\n\n  // Call identity provider constructor with options\n  var idp = new saml2.IdentityProvider(idp_options);\n\n  // Example usage of identity provider.\n  // Pass identity provider into a service provider function with options and a callback.\n  sp.post_assert(idp, {}, callback);\n\n```\n\n\n## Example: Express implementation\n\nLibrary users will need to implement a set of URL endpoints, here is an example of [express](http://expressjs.com/) endpoints.\n\n```javascript\nvar saml2 = require('saml2-js');\nvar fs = require('fs');\nvar express = require('express');\nvar app = express();\nvar bodyParser = require('body-parser');\napp.use(bodyParser.urlencoded({\n  extended: true\n}));\n\n// Create service provider\nvar sp_options = {\n  entity_id: \"https://sp.example.com/metadata.xml\",\n  private_key: fs.readFileSync(\"key-file.pem\").toString(),\n  certificate: fs.readFileSync(\"cert-file.crt\").toString(),\n  assert_endpoint: \"https://sp.example.com/assert\"\n};\nvar sp = new saml2.ServiceProvider(sp_options);\n\n// Create identity provider\nvar idp_options = {\n  sso_login_url: \"https://idp.example.com/login\",\n  sso_logout_url: \"https://idp.example.com/logout\",\n  certificates: [fs.readFileSync(\"cert-file1.crt\").toString(), fs.readFileSync(\"cert-file2.crt\").toString()]\n};\nvar idp = new saml2.IdentityProvider(idp_options);\n\n// ------ Define express endpoints ------\n\n// Endpoint to retrieve metadata\napp.get(\"/metadata.xml\", function(req, res) {\n  res.type('application/xml');\n  res.send(sp.create_metadata());\n});\n\n// Starting point for login\napp.get(\"/login\", function(req, res) {\n  sp.create_login_request_url(idp, {}, function(err, login_url, request_id) {\n    if (err != null)\n      return res.send(500);\n    res.redirect(login_url);\n  });\n});\n\n// Assert endpoint for when login completes\napp.post(\"/assert\", function(req, res) {\n  var options = {request_body: req.body};\n  sp.post_assert(idp, options, function(err, saml_response) {\n    if (err != null)\n      return res.send(500);\n\n    // Save name_id and session_index for logout\n    // Note:  In practice these should be saved in the user session, not globally.\n    name_id = saml_response.user.name_id;\n    session_index = saml_response.user.session_index;\n\n    res.send(\"Hello #{saml_response.user.name_id}!\");\n  });\n});\n\n// Starting point for logout\napp.get(\"/logout\", function(req, res) {\n  var options = {\n    name_id: name_id,\n    session_index: session_index\n  };\n\n  sp.create_logout_request_url(idp, options, function(err, logout_url) {\n    if (err != null)\n      return res.send(500);\n    res.redirect(logout_url);\n  });\n});\n\napp.listen(3000);\n\n```\n","readmeFilename":"README.md"}