@node-saml/passport-saml
Advanced tools
Comparing version
{ | ||
"name": "@node-saml/passport-saml", | ||
"version": "4.0.1", | ||
"version": "4.0.2", | ||
"description": "SAML 2.0 authentication strategy for Passport", | ||
@@ -66,10 +66,10 @@ "keywords": [ | ||
"@types/mocha": "^10.0.0", | ||
"@types/node": "^14.18.33", | ||
"@types/node": "^14.18.34", | ||
"@types/sinon": "^10.0.13", | ||
"@typescript-eslint/eslint-plugin": "^5.41.0", | ||
"@typescript-eslint/parser": "^5.41.0", | ||
"@typescript-eslint/eslint-plugin": "^5.45.0", | ||
"@typescript-eslint/parser": "^5.46.1", | ||
"chai": "^4.3.6", | ||
"choma": "^1.2.1", | ||
"concurrently": "^7.5.0", | ||
"eslint": "^8.26.0", | ||
"eslint": "^8.29.0", | ||
"eslint-config-prettier": "^8.5.0", | ||
@@ -80,3 +80,3 @@ "eslint-plugin-prettier": "^4.2.1", | ||
"onchange": "^7.1.0", | ||
"prettier": "^2.7.1", | ||
"prettier": "^2.8.0", | ||
"prettier-plugin-packagejson": "^2.3.0", | ||
@@ -83,0 +83,0 @@ "release-it": "^15.5.0", |
116
README.md
@@ -18,3 +18,3 @@ # Passport-SAML | ||
```shell | ||
npm install passport-saml | ||
npm install @node-saml/passport-saml | ||
``` | ||
@@ -108,37 +108,16 @@ | ||
The options passed when the `MultiSamlStrategy` is initialized are also passed as default values to each provider. | ||
e.g. If you provide an `issuer` on `MultiSamlStrategy`, this will be also a default value for every provider. | ||
You can override these defaults by passing a new value through the `getSamlOptions` function. | ||
The options passed when the `MultiSamlStrategy` is initialized are also passed as default values to each provider. e.g. If you provide an `issuer` on `MultiSamlStrategy`, this will be also a default value for every provider. You can override these defaults by passing a new value through the `getSamlOptions` function. | ||
Using multiple providers supports `validateInResponseTo`, but all the `InResponse` values are stored on the same Cache. This means, if you're using the default `InMemoryCache`, that all providers have access to it and a provider might get its response validated against another's request. [Issue Report](!https://github.com/node-saml/passport-saml/issues/334). To amend this you should provide a different cache provider per SAML provider, through the `getSamlOptions` function. | ||
Using multiple providers supports `validateInResponseTo`, but all the `InResponse` values are stored on the same Cache. This means, if you're using the default `InMemoryCache`, that all providers have access to it and a provider might get its response validated against another's request. [Issue Report](https://github.com/node-saml/passport-saml/issues/334). To amend this you should provide a different cache provider per SAML provider, through the `getSamlOptions` function. | ||
> :warning: **There's a race condition [bug](https://github.com/node-saml/passport-saml/issues/425) in versions < 1.3.3 which makes it vulnerable to DOS attacks**: Please use > 1.3.3 if you want to use this issue | ||
Please note that in the above examples, `findProvider()`, `findByNameId()`, and `findByEmail()` are an examples of functions you need to implement yourself. These are just examples. You can implement this functionality any way you see fit. Please note that calling `getSamlOptions()` should result in `done()` being called with a proper SAML Configuration (see the TypeScript typings for more information) and the `done()` callbacks for the second and third arguments should be called with an object that represents the user. | ||
#### The profile object: | ||
### The profile object | ||
The profile object referenced above contains the following: | ||
Please see the [type specification](https://github.com/node-saml/node-saml/blob/master/src/types.ts#:~:text=export%20interface%20profile) in `node-saml` for information about this type. | ||
```typescript | ||
export interface Profile { | ||
issuer: string; | ||
sessionIndex?: string; | ||
nameID: string; | ||
nameIDFormat: string; | ||
nameQualifier?: string; | ||
spNameQualifier?: string; | ||
ID?: string; | ||
mail?: string; // InCommon Attribute urn:oid:0.9.2342.19200300.100.1.3 | ||
email?: string; // `mail` if not present in the assertion | ||
["urn:oid:0.9.2342.19200300.100.1.3"]?: string; | ||
getAssertionXml?(): string; // get the raw assertion XML | ||
getAssertion?(): Record<string, unknown>; // get the assertion XML parsed as a JavaScript object | ||
getSamlResponseXml?(): string; // get the raw SAML response XML | ||
[attributeName: string]: unknown; // arbitrary `AttributeValue`s | ||
} | ||
``` | ||
#### Config parameter details | ||
#### Config parameter details: | ||
##### **Core** | ||
**Core** | ||
- `callbackUrl`: full callbackUrl (overrides path/protocol if supplied) | ||
@@ -158,3 +137,3 @@ - `path`: path to callback; will be combined with protocol and server host information to construct callback url if `callbackUrl` is not specified (default: `/saml/consume`) | ||
**Additional SAML behaviors** | ||
##### **Additional SAML behaviors** | ||
@@ -180,3 +159,3 @@ - `additionalParams`: dictionary of additional query params to add to all requests; if an object with this key is passed to `authenticate`, the dictionary of additional query params will be appended to those present on the returned URL, overriding any specified by initialization options' additional parameters (`additionalParams`, `additionalAuthorizeParams`, and `additionalLogoutParams`) | ||
- `disableRequestAcsUrl`: if truthy, SAML AuthnRequest from the service provider will not include the optional AssertionConsumerServiceURL. Default is falsy so it is automatically included. | ||
- `scoping`: An optional configuration which implements the functionality [explained in the SAML spec paragraph "3.4.1.2 Element <Scoping>"](https://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf). The config object is structured as following: | ||
- `scoping`: An optional configuration which implements the functionality [explained in the SAML spec paragraph "3.4.1.2 Element \<Scoping\>"](https://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf). The config object is structured as following: | ||
@@ -202,3 +181,3 @@ ```javascript | ||
**InResponseTo Validation** | ||
##### **InResponseTo Validation** | ||
@@ -209,7 +188,7 @@ - `validateInResponseTo`: if truthy, then InResponseTo will be validated from incoming SAML responses | ||
**Issuer Validation** | ||
##### **Issuer Validation** | ||
- `idpIssuer`: if provided, then the IdP issuer will be validated for incoming Logout Requests/Responses. For ADFS this looks like `https://acme_tools.windows.net/deadbeef` | ||
**Passport** | ||
##### **Passport** | ||
@@ -221,3 +200,3 @@ - `passReqToCallback`: if truthy, `req` will be passed as the first argument to the verify callback (default: `false`) | ||
**Logout** | ||
##### **Logout** | ||
@@ -280,8 +259,4 @@ - `logoutUrl`: base address to call with logout requests (default: `entryPoint`) | ||
As a convenience, the strategy object exposes a `generateServiceProviderMetadata` method which will generate a service provider metadata document suitable for supplying to an identity provider. This method will only work on strategies which are configured with a `callbackUrl` (since the relative path for the callback is not sufficient information to generate a complete metadata document). | ||
For details about this method, please see the [documentation](https://github.com/node-saml/node-saml#generateserviceprovidermetadata-decryptioncert-signingcert-) at `node-saml`. | ||
The `decryptionCert` argument should be a public certificate matching the `decryptionPvk` and is required if the strategy is configured with a `decryptionPvk`. | ||
The `signingCert` argument should be a public certificate matching the `privateKey` and is required if the strategy is configured with a `privateKey`. An array of certificates can be provided to support certificate rotation. When supplying an array of certificates, the first entry in the array should match the current `privateKey`. Additional entries in the array can be used to publish upcoming certificates to IdPs before changing the `privateKey`. | ||
The `generateServiceProviderMetadata` method is also available on the `MultiSamlStrategy`, but needs an extra request and a callback argument (`generateServiceProviderMetadata( req, decryptionCert, signingCert, next )`), which are passed to the `getSamlOptions` to retrieve the correct configuration. | ||
@@ -311,22 +286,22 @@ | ||
```text | ||
-----BEGIN PRIVATE KEY----- | ||
<private key contents here delimited at 64 characters per row> | ||
-----END PRIVATE KEY----- | ||
```text | ||
-----BEGIN PRIVATE KEY----- | ||
<private key contents here delimited at 64 characters per row> | ||
-----END PRIVATE KEY----- | ||
``` | ||
``` | ||
```text | ||
-----BEGIN RSA PRIVATE KEY----- | ||
<private key contents here delimited at 64 characters per row> | ||
-----END RSA PRIVATE KEY----- | ||
```text | ||
-----BEGIN RSA PRIVATE KEY----- | ||
<private key contents here delimited at 64 characters per row> | ||
-----END RSA PRIVATE KEY----- | ||
``` | ||
``` | ||
(both versions work) | ||
See example from tests of the first version of [well formatted private key](test/static/acme_tools_com.key). | ||
(both versions work) | ||
See example from tests of the first version of [well formatted private key](test/static/acme_tools_com.key). | ||
2. Alternativelly a single line private key without start/end lines where all rows are joined into single line: | ||
1. Alternativelly a single line private key without start/end lines where all rows are joined into single line: | ||
See example from tests of [singleline private key](test/static/singleline_acme_tools_com.key). | ||
See example from tests of [singleline private key](test/static/singleline_acme_tools_com.key). | ||
@@ -384,29 +359,19 @@ Add it to strategy options like this: | ||
If the `NotBefore` or the `NotOnOrAfter` attributes are returned in the SAML response, Passport-SAML will validate them | ||
against the current time +/- a configurable clock skew value. The default for the skew is 0s. This is to account for | ||
differences between the clock time on the client (Node server with Passport-SAML) and the server (Identity provider). | ||
If the `NotBefore` or the `NotOnOrAfter` attributes are returned in the SAML response, Passport-SAML will validate them against the current time +/- a configurable clock skew value. The default for the skew is 0s. This is to account for differences between the clock time on the client (Node server with Passport-SAML) and the server (Identity provider). | ||
`NotBefore` and `NotOnOrAfter` can be part of either the `SubjectConfirmation` element, or within in the `Assertion/Conditions` element | ||
in the SAML response. | ||
`NotBefore` and `NotOnOrAfter` can be part of either the `SubjectConfirmation` element, or within in the `Assertion/Conditions` element in the SAML response. | ||
## Subject confirmation validation | ||
When configured (turn `validateInResponseTo` to `true` in the Passport-SAML config), the `InResponseTo` attribute will be validated. | ||
Validation will succeed if Passport-SAML previously generated a SAML request with an id that matches the value of `InResponseTo`. | ||
When configured (turn `validateInResponseTo` to `true` in the Passport-SAML config), the `InResponseTo` attribute will be validated. Validation will succeed if Passport-SAML previously generated a SAML request with an id that matches the value of `InResponseTo`. | ||
Also note that `InResponseTo` is validated as an attribute of the top level `Response` element in the SAML response, as well | ||
as part of the `SubjectConfirmation` element. | ||
Also note that `InResponseTo` is validated as an attribute of the top level `Response` element in the SAML response, as well as part of the `SubjectConfirmation` element. | ||
Previous request id's generated for SAML requests will eventually expire. This is controlled with the `requestIdExpirationPeriodMs` option | ||
passed into the Passport-SAML config. The default is 28,800,000 ms (8 hours). Once expired, a subsequent SAML response | ||
received with an `InResponseTo` equal to the expired id will not validate and an error will be returned. | ||
Previous request id's generated for SAML requests will eventually expire. This is controlled with the `requestIdExpirationPeriodMs` option passed into the Passport-SAML config. The default is 28,800,000 ms (8 hours). Once expired, a subsequent SAML response received with an `InResponseTo` equal to the expired id will not validate and an error will be returned. | ||
## Cache Provider | ||
When `InResponseTo` validation is turned on, Passport-SAML will store generated request ids used in SAML requests to the IdP. The implementation | ||
of how things are stored, checked to see if they exist, and eventually removed is from the Cache Provider used by Passport-SAML. | ||
When `InResponseTo` validation is turned on, Passport-SAML will store generated request ids used in SAML requests to the IdP. The implementation of how things are stored, checked to see if they exist, and eventually removed is from the Cache Provider used by Passport-SAML. | ||
The default implementation is a simple in-memory cache provider. For multiple server/process scenarios, this will not be sufficient as | ||
the server/process that generated the request id and stored in memory could be different than the server/process handling the | ||
SAML response. The `InResponseTo` could fail in this case erroneously. | ||
The default implementation is a simple in-memory cache provider. For multiple server/process scenarios, this will not be sufficient as the server/process that generated the request id and stored in memory could be different than the server/process handling the SAML response. The `InResponseTo` could fail in this case erroneously. | ||
@@ -449,3 +414,3 @@ To support this scenario you can provide an implementation for a cache provider by providing an object with following functions: | ||
Gerard Braad has provided an example app at https://github.com/gbraad/passport-saml-example/ | ||
Gerard Braad has provided an example app at <https://github.com/gbraad/passport-saml-example/> | ||
@@ -466,4 +431,3 @@ ## Node Support Policy | ||
The project was started by @bergie in 2012 based on Michael Bosworth's [express-saml](https://github.com/bozzltron/express-saml) library. From 2014 - 2016, @ploer served as primary maintainer. | ||
@markstos served the primary maintainer from 2017 till 2020 when he created the node-saml organization. With a goal to create a team of maintainers, invitations were sent to major contributors and fork authors to work together to maintain all the improvements in one place. | ||
The project was started by @bergie in 2012 based on Michael Bosworth's [express-saml](https://github.com/bozzltron/express-saml) library. From 2014 - 2016, @ploer served as primary maintainer. @markstos served the primary maintainer from 2017 till 2020 when he created the node-saml organization. With a goal to create a team of maintainers, invitations were sent to major contributors and fork authors to work together to maintain all the improvements in one place. | ||
@@ -473,1 +437,5 @@ Since 2020, @cjbath emerged as the primary maintainer, with major contributions from @gugu and @zoellner. Major updates from the team included rewriting the project in TypeScript and splitting off a `node-saml` module which can be used without Passport. Almost 100 other developers have contributed improvements to the project. | ||
The project continues to be maintained by volunteers. Contributions small and large are welcome. | ||
## Copyright Notices | ||
“[OASIS](http://www.oasis-open.org/)”, “SAML”, and “Security Assertion Markup Language” are trademarks of OASIS, the open standards consortium where the SAML specification is owned and developed. SAML is a copyrighted © work of OASIS Open. All rights reserved. |
70945
-0.95%429
-6.94%