{"analyzedAt":"2022-07-02T03:35:24.186Z","collected":{"metadata":{"name":"hana-saml-wsse","scope":"unscoped","version":"0.3.8","description":"SAML ECP client with assertion delegation support.","keywords":["shibboleth","idp","hana","hdb","saml","ecp","ws-security","ssos","delegation"],"date":"2016-09-26T17:19:51.843Z","author":{"name":"kelas"},"publisher":{"username":"kelas","email":"me@kel.as"},"maintainers":[{"username":"kelas","email":"me@kel.as"}],"repository":{"type":"git","url":"git@git.umoja.un.org:hana/hana-saml-wsse.git"},"links":{"npm":"https://www.npmjs.com/package/hana-saml-wsse"},"license":"MIT","dependencies":{"underscore":"*","moment":"*","node-uuid":"*","xml-crypto":"*","mustache":"*","xmldom":"*","xmlfmt":"*","xpath":"*","xml-encryption":"*"},"releases":[{"from":"2022-06-02T00:00:00.000Z","to":"2022-07-02T00:00:00.000Z","count":1},{"from":"2022-04-03T00:00:00.000Z","to":"2022-07-02T00:00:00.000Z","count":1},{"from":"2022-01-03T00:00:00.000Z","to":"2022-07-02T00:00:00.000Z","count":1},{"from":"2021-07-02T00:00:00.000Z","to":"2022-07-02T00:00:00.000Z","count":1},{"from":"2020-07-02T00:00:00.000Z","to":"2022-07-02T00:00:00.000Z","count":1}],"hasTestScript":true,"readme":"## SAML delegation\n\nSome advanced SAML use cases involve a single logical transaction that spans one or more intermediate\nclients or servers. A common example includes a SAML-enabled web site acting on behalf of a logged-in\nuser while accessing additional SAML-enabled services, which are not directly accessible \nby the user agent, e.g. a database. Generalizing this example, a number of intermediaries might be \ntraversed before the final point of access. Popular ways of making this happen are\n__SAML impersonation__, __SAML assertion forwarding__ and __SAML IdP proxy__.\n\nAll of them suck:\n\n* SAML impersonation forces principal to disclose credentials to an SP.\n* SAML forwarding makes IdP lose track of who and when is using forwarded assertions.\n* IdP proxy requires a second IdP in exotic configuration.\n\nWhen a SAML assertion is used as a security token to authenticate/authorize people and software \nagainst a mission-critical service, it is important that the identities and order of intermediaries,\nif any, are expressed within the token in some fashion.\n\n__SAML assertion delegation__ moves beyond the forwarding scenario by adding information to the \nassertion that explicitly identifies the chain of parties through which a transaction flows.\nDelegation assures that all requests in the chain are routed back through the identity provider at \neach hop to cryptographically guarantee that each party has been authenticated and appropriate \npolicy enforced. This finegrained and real-time enforcement capability is a key advantage over \npure SAML forwarding and impersonation, at a price of additional back-channel operation for \neach delegation hop. \n\n[__Shibboleth Identity Provider__]() implements SAML 2.0 profile for assertion delegation (Liberty/IDWSF).\n\n__hana-saml-wsse__ is the corresponding client. It also implements an __ECP__ client, which is handy \nfor testing your delegation configuration, but can be very useful in its own right, e.g.\nif you are implementing impersonation or fowarding model.\n\nThe package name is historical; the client has been originally implemented for a specific use case \nthat involved a SAP HANA database backend. Making Shibboleth delegation work with SAP HANA requires\nadditional IdP configuration, which is not covered here. \n\n## Compatibility\n\nThis implementation is known to work with Shibboleth IdP 3.2. There is some indication that ECP \nand ID-WSF profiles are supported by some other open source and commercial IdP\nsystems, but none of them were tested.\n\n## X.509 authentication\n\nAs it should be clear from the example below, ID-WSF requires that your IdP is configured to support\n__X.509 client certificate authentication__. The same applies to all TLS middleware you might have \nin front of your IdP, e.g. nginx, httpd, netscaler, etc. This is at least as complicated as it\nsounds, so good luck. Good starting points are:\n\n* [Tomcat SSLValve](https://tomcat.apache.org/tomcat-8.0-doc/api/org/apache/catalina/valves/SSLValve.html)\n* [X.509 Client-Side Certificate Auth with Nginx](http://nategood.com/client-side-certificate-authentication-in-ngi)\n\n> Things get easier if you want to use this library in ECP mode. Although ECP *does* support X.509 auth,\n> it is optional (you can use basic HTTP auth method).\n\n## Security\n\n- The client signs all outgoing AuthRequests.\n- The client expects incoming assertions to be both encrypted and signed.\n- `inResponseTo` validation is supported and enabled by default.\n- `NotBeforeOrAfter` is not validated, but is returned in `assertionInfo` object.\n- `wsa` profile does not work over plain HTTP, and never will.\n- `ecp` mode _should_ work over plain HTTP, but this is a very bad idea. \n\n## Install\n\n```\n$ npm install hana-saml-wsse\n```\n\n## IdP configuration\n\nThe following configuration snippet assumes the following scenario:\n\n- A Service Provider idendified as `webserver-sp` is allowed to obtain a \ndelegatable assertion using ECP at any time. Assertion is valid for 10 hours.\n- By itself, a delegatable assertion in not usable by any other SP other than \n`webserver-sp` as its `Audience` restriction is limited to `webserver-sp`.\n- However, for as long as delegatable assertion remains valid, `webserver-sp` can \nrequest additional, \"delegated\" assertions which will be valid for `database-sp`,\neach valid for 60 seconds. These delegated assertions are no further delegatable, \ni.e. `database-sp` is the final point of access.\n\n___\n\n> Note that, while requesting a delegated assertion, `webserver-sp` does not need\n> to present actual credentials of the user (generally, username and password), and it \n> is not expected to have them - instead, it presents a delegatable assertion as the \n> means of confirming that it has the authority to impersonate that user on `database-sp`\n> or elsewhere. The communication takes place over authenticated TLS channel, i.e. \n> IdP uses TLS to ensure it is actually talking to the SP to which the delegatable\n> assertion was originally issued. __In essence, this is the whole idea of how \n> assertion delegation works__.\n___\n\n```xml\n<!-- conf/relying-party.xml -->\n\n<!-- \n     \"delegation-predicate\" is a reference to a bean that implements\n     com.google.common.base.Predicate<ProfileRequestContext<?,?>> interface.\n     It can be used to implement additional custom logic to selectively allow\n     or disallow delegation. In the most basic case, you want to implement a predicate that\n     always returns true.\n-->\n\n<bean parent=\"RelyingPartyByName\" c:relyingPartyIds=\"#{{ 'webserver-sp' }}\">\n  <property name=\"profileConfigurations\">\n    <list>\n      <!-- serve long-lived delegatable assertions via ECP -->\n      <bean id=\"SAML2.ECP\"\n        class=\"net.shibboleth.idp.saml.saml2.profile.config.ECPProfileConfiguration\"\n        p:inboundInterceptorFlows=\"security-policy/saml2-ecp\"\n        p:allowDelegation-ref=\"delegation-predicate\"\n        p:assertionLifetime=\"PT600M\"\n      />\n      <!-- serve short-lived delegated assertions via ID-WSF -->\n      <bean id=\"Liberty.SSOS\"\n        class=\"net.shibboleth.idp.saml.idwsf.profile.config.SSOSProfileConfiguration\"\n        p:inboundInterceptorFlows=\"security-policy/saml2-idwsf-ssos\"\n        p:maximumTokenDelegationChainLength=\"1\"\n        p:allowDelegation=\"false\"\n        p:delegationPredicate-ref=\"delegation-predicate\"\n        p:additionalAudiencesForAssertion=\"#{{ 'database-sp' }}\"\n        p:assertionLifetime=\"PT1M\"\n      />\n     </list>\n  </property>\n</bean>\n```\n\n## SP configuration\n\nSP metadata must inform IdP that SP is ready and willing to consume delegatable assertions,\nas shown below. The `Location` attribute of `AssertionConsumerService` must match `consumerURL` parameter\nof `hana-saml-wsse` client configuration, but this is a formality as SP is not expected\nto actually respond on that URL. \n\n```xml\n...\n<!-- SSOS -->\n<AssertionConsumerService\n  Binding=\"urn:oasis:names:tc:SAML:2.0:bindings:PAOS\"\n  Location=\"https://my.org/Liberty/SSOS\"/>\n\n<AttributeConsumingService>\n  <RequestedAttribute\n    NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:uri\"\n    Name=\"urn:liberty:ssos:2006-08\"\n    FriendlyName=\"assertionDelegation\"\n    isRequired=\"false\" />\n</AttributeConsumingService>\n...\n```\n\n## Usage\n\nThe example below matches the IdP configuration above and:\n\n1. Binds to your Identity Provider's ECP endpoint using TLS transport.\n2. Authenticates using either user/password or X.509 certificate of the user.\n3. Retrieves, verifies and decrypts a delegatable assertion.\n4. Creates an ID-WSF AuthRequest using delegatable assertion as a security token.\n5. Binds to the ID-WSF endpoint using TLS transport.\n6. Authenticates using X.509 certificate of the SP.\n7. Retrieves, verifies and decrypts a delegate assertion.\n8. Tests it by using it as a security token to connect to a SAP HANA backend.\n9. Optionally repeats steps 4-7 every `deleg_test_repeat_ms` milliseconds.\n___\n\n```javascript\n// test.js\nvar\n  hdb = require('hdb'),\n  precise = require('precise'),\n  moment = require('moment'),\n  xmlfmt = require('xmlfmt'),\n  WSS = require('hana-saml-wsse')\n;\n \nvar\n  deleg_test_repeat_ms = 3000,\n  idpHost = 'idphost',\n  idpPort = 443,\n  http_ua = 'hana-wss-client/1.0',\n  hdb_conf = {\n    host: 'hanahost',\n    port: 30015\n  }\n;\n \nvar conf = {\n  user         : 'tj_holowaychuk',\n  pass         : null, // leave blank for TLS CCA (@see user_key/user_cert) \n\n  idpHost      : idpHost,\n  idpPort      : idpPort,\n\n  idpId        : 'idp-id',\n  spId         : 'webserver-sp',\n\n  url: { \n    ecp        : '/idp/profile/SAML2/SOAP/ECP',\n    wsa        : '/idp/profile/IDWSF/SSOS'\n  },\n\n  consumerURL  : 'https://my.org/Liberty/SSOS',\n\n  idp_cert     : './idp.pem',\n\n  // used both for signing and X.509 auth (WSA only)\n  sp_key       : './sp_private_key.pem',\n  sp_cert      : './sp_public_key.pem',\n\n  // optional TLS CCA authentication (ECP only) \n  user_key     : './user.key',\n  user_cert    : './user.crt',\n\n  sig_alg      : 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256',\n\n  tls_opt: {\n    hostname   : idpHost,\n    port       : idpPort,\n    method     : 'POST',\n    headers    : {\n      'Content-Type'      : 'text/xml',\n      'Transfer-Encoding' : 'chunked',\n      'User-Agent'        : http_ua\n    },\n    // die on bad IdP cert \n    rejectUnauthorized: true\n  },\n\n  log: console.log\n};\n\nvar client = new WSS.client(conf);\n\nfunction hdbtest(assertion, cb) {\n  var hdbclient = hdb.createClient(hdb_conf);\n  hdbclient.connect({ assertion: assertion }, (err) => {\n    if (err) {\n      console.error('[hdb] error:', err);\n    } else {\n      console.log('[hdb] i am', hdbclient.get('user'));\n    }\n    hdbclient.end();\n    cb && cb(err);\n  });\n}\n\nclient.get('ecp', (err, delegatableAssertion, assertionInfo) => {\n  if (err)\n    return conf.log('[ecp] error:', err);\n\n  conf.log('[ecp] rcvd delegatable assertion, expires',\n    moment(assertionInfo.notOnOrAfter).fromNow());\n\n  //conf.log(xmlfmt(delegatableAssertion))\n\n  var delegator = () => {\n    var timer = precise().start();\n    client.get('wsa', (err, assertion, assertionInfo) => {\n      if (err)\n        return conf.log('[wsa] error:', err);\n\n      //conf.log(xmlfmt(assertion));\n      //conf.log(assertion);\n\n      conf.log('[wsa] rcvd delegated assertion in',\n        (timer.stop().diff()/1000000000).toFixed(2) + 's,',\n        'expires', moment(assertionInfo.notOnOrAfter).fromNow());\n\n      hdbtest(assertion, () => {\n        if(!deleg_test_repeat_ms)\n          process.exit(0);\n        });\n      }, delegatableAssertion);\n  };\n\n  if (deleg_test_repeat_ms)\n    setInterval(delegator, deleg_test_repeat_ms);\n  else\n    delegator();\n}); \n\n//:~\n```\n\nYou should get something like:\n\n```\n$ node test.js\n\n[ecp] using tls cca with user key\n[ecp] rcvd delegatable assertion, expires in 10 hours\n[wsa] using tls cca with SP key\n[wsa] rcvd delegated assertion in 0.22s, expires in a minute\n[hdb] i am tj_holowaychuk\n[wsa] using tls cca with SP key\n[wsa] rcvd delegated assertion in 0.14s, expires in a minute\n[hdb] i am tj_holowaychuk\n[wsa] using tls cca with SP key\n[wsa] rcvd delegated assertion in 0.16s, expires in a minute\n[hdb] i am tj_holowaychuk\n[wsa] using tls cca with SP key\n[wsa] rcvd delegated assertion in 0.11s, expires in a minute\n[hdb] i am tj_holowaychuk\n[wsa] using tls cca with SP key\n[wsa] rcvd delegated assertion in 0.14s, expires in a minute\n^C\n\n```\n\n## Recommended reading\n\nSAML specs are fun:\n\n* [Overview of SAML assertion delegation scenarios](http://docs.oasis-open.org/security/saml/Post2.0/sstc-saml-delegation-cs-01.pdf)\n* [SAML V2.0 Enhanced Client or Proxy (ECP)](https://wiki.oasis-open.org/security/SAML2EnhancedClientProfile)\n* [WS-Security SAML Token](http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.0.pdf)\n* [SAML Metadata Specification](https://docs.oasis-open.org/security/saml/v2.0/saml-metadata-2.0-os.pdf)\n* [IDWSF-SAML Specification](http://www.projectliberty.org/resource_center/specifications/liberty_alliance_id_wsf_2_0_specifications/)\n* [Understanding WS-Security](https://msdn.microsoft.com/en-us/library/ms977327.aspx)\n* [WSA SOAP binding](https://www.w3.org/TR/2006/REC-ws-addr-soap-20060509/)\n* [urn:oasis:names:tc:SAML:2.0:cm:holder-of-key](http://hdknr.github.io/docs/identity/SamlHokProfile.html)\n\n## License\n\nMIT. Use at your own risk. As with all things SAML, always be sure you know what you are doing."},"npm":{"downloads":[{"from":"2022-07-01T00:00:00.000Z","to":"2022-07-02T00:00:00.000Z","count":0},{"from":"2022-06-25T00:00:00.000Z","to":"2022-07-02T00:00:00.000Z","count":10},{"from":"2022-06-02T00:00:00.000Z","to":"2022-07-02T00:00:00.000Z","count":135},{"from":"2022-04-03T00:00:00.000Z","to":"2022-07-02T00:00:00.000Z","count":833},{"from":"2022-01-03T00:00:00.000Z","to":"2022-07-02T00:00:00.000Z","count":1130},{"from":"2021-07-02T00:00:00.000Z","to":"2022-07-02T00:00:00.000Z","count":2690}],"starsCount":0},"source":{"files":{"readmeSize":12348,"testsSize":0,"hasNpmIgnore":true}}},"evaluation":{"quality":{"carefulness":0.39499999999999996,"tests":0,"health":0.1,"branding":0},"popularity":{"communityInterest":0,"downloadsCount":277.6666666666667,"downloadsAcceleration":-0.9904870624048707,"dependentsCount":0},"maintenance":{"releasesFrequency":0.7591609589041095,"commitsFrequency":0,"openIssues":0,"issuesDistribution":0}},"score":{"final":0.19783183980485386,"detail":{"quality":0.26037653871129274,"popularity":0.009498044040925307,"maintenance":0.33255589364897764}}}