Skip to content

Commit

Permalink
Merge branch 'master' into session-url-params
Browse files Browse the repository at this point in the history
* master: (51 commits)
  start to use the debug module.
  v0.34.0: release
  internal: provide unique failure messages for invalid signatures. Fixes node-saml#146
  package.json: bump version to 0.33.0
  docs: mention that disableRequestAuthnContext helps with AD FS
  New Feature: allow customizing the name of the strategy.
  bump version to v0.32.1
  README: link to where our Changes are documented.
  Audience validation
  README: fix typo `s/ADSF/ADFS/`
  jshint: fix jshint violation.
  v0.31.0 release
  README: update link description for ADFS docs.
  Upd: Mention ADFS 2016 with NameIDFormatError. (node-saml#242)
  Support multiple and dynamic signing certificates (node-saml#218)
  v0.30.0
  Ignore .tern-port files
  Use crypto.randomBytes for ID generation (node-saml#235)
  BugFix: Fail gracefully when SAML Response is invalid. Fixes node-saml#238
  docs: Improve docs for privateKey format. Ref node-saml#230
  ...

# Conflicts:
#	README.md
#	test/samlTests.js
  • Loading branch information
cjbarth committed Sep 10, 2018
2 parents aa29f86 + f8140aa commit 735509f
Show file tree
Hide file tree
Showing 10 changed files with 706 additions and 330 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
node_modules/
.tern-port
6 changes: 0 additions & 6 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,14 +1,8 @@
language: node_js
node_js:
- "0.10"
- "0.12"
- "iojs"
- "4.0"
- "stable"

before_install:
- npm install -g npm

script:
- npm test
- ./node_modules/.bin/jshint lib
110 changes: 73 additions & 37 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
Passport-SAML
=============
[![Build Status](https://travis-ci.org/bergie/passport-saml.svg?branch=master)](https://travis-ci.org/bergie/passport-saml) [![GitHub version](https://badge.fury.io/gh/bergie%2Fpassport-saml.svg)](https://badge.fury.io/gh/bergie%2Fpassport-saml) [![npm version](https://badge.fury.io/js/passport-saml.svg)](http://badge.fury.io/js/passport-saml) [![dependencies](https://david-dm.org/bergie/passport-saml.svg)](https://david-dm.org/bergie/passport-saml.svg) [![devDependencies](https://david-dm.org/bergie/passport-saml/dev-status.svg)](https://david-dm.org/bergie/passport-saml/dev-status.svg) [![peerDependencies](https://david-dm.org/bergie/passport-saml/peer-status.svg)](https://david-dm.org/bergie/passport-saml/peer-status.svg)

[![NPM](https://nodei.co/npm/passport-saml.png?downloads=true&downloadRank=true&stars=true)](https://nodei.co/npm/passport-saml/)

This is a [SAML 2.0](http://en.wikipedia.org/wiki/SAML_2.0) authentication provider for [Passport](http://passportjs.org/), the Node.js authentication library.

Expand Down Expand Up @@ -40,39 +43,46 @@ passport.use(new SamlStrategy(
);
```

Config parameter details:
* Core
* `callbackUrl`: full callbackUrl (overrides path/protocol if supplied)
* `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`)
* `protocol`: protocol for callback; will be combined with path and server host information to construct callback url if `callbackUrl` is not specified (default: `http://`)
* `host`: host for callback; will be combined with path and protocol to construct callback url if `callbackUrl` is not specified (default: `localhost`)
* `entryPoint`: identity provider entrypoint
* `issuer`: issuer string to supply to identity provider
* `cert`: see 'security and signatures'
* `privateCert`: see 'security and signatures'
* `decryptionPvk`: optional private key that will be used to attempt to decrypt any encrypted assertions that are received
* `signatureAlgorithm`: optionally set the signature algorithm for signing requests, valid values are 'sha1' (default) or 'sha256'
* Additional SAML behaviors
* `additionalParams`: dictionary of additional query params to add to all requests; this can also be part of the options that are passed to `authenticate` for params to be added on a per-call basis
* `additionalAuthorizeParams`: dictionary of additional query params to add to 'authorize' requests
* `identifierFormat`: if truthy, name identifier format to request from identity provider (default: `urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress`)
* `acceptedClockSkewMs`: Time in milliseconds of skew that is acceptable between client and server when checking `OnBefore` and `NotOnOrAfter` assertion condition validity timestamps. Setting to `-1` will disable checking these conditions entirely. Default is `0`.
* `attributeConsumingServiceIndex`: optional `AttributeConsumingServiceIndex` attribute to add to AuthnRequest to instruct the IDP which attribute set to attach to the response ([link](http://blog.aniljohn.com/2014/01/data-minimization-front-channel-saml-attribute-requests.html))
* `disableRequestedAuthnContext`: if truthy, do not request a specific auth context
* `authnContext`: if truthy, name identifier format to request auth context (default: `urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport`)
* `forceAuthn`: if set to true, the initial SAML request from the service provider specifies that the IdP should force re-authentication of the user, even if they possess a valid session.
* `skipRequestCompression`: if set to true, the SAML request from the service provider won't be compressed.
* `authnRequestBinding`: if set to `HTTP-POST`, will request authentication from IDP via HTTP POST binding, otherwise defaults to HTTP Redirect
* InResponseTo Validation
* `validateInResponseTo`: if truthy, then InResponseTo will be validated from incoming SAML responses
* `requestIdExpirationPeriodMs`: Defines the expiration time when a Request ID generated for a SAML request will not be valid if seen in a SAML response in the `InResponseTo` field. Default is 8 hours.
* `cacheProvider`: Defines the implementation for a cache provider used to store request Ids generated in SAML requests as part of `InResponseTo` validation. Default is a built-in in-memory cache provider. For details see the 'Cache Provider' section.
* Passport
* `passReqToCallback`: if truthy, `req` will be passed as the first argument to the verify callback (default: `false`)
* Logout
* `logoutUrl`: base address to call with logout requests (default: `entryPoint`)
* `additionalLogoutParams`: dictionary of additional query params to add to 'logout' requests
* `logoutCallbackUrl`: The value with which to populate the `Location` attribute in the `SingleLogoutService` elements in the generated service provider metadata.
#### Config parameter details:

* **Core**
* `callbackUrl`: full callbackUrl (overrides path/protocol if supplied)
* `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`)
* `protocol`: protocol for callback; will be combined with path and server host information to construct callback url if `callbackUrl` is not specified (default: `http://`)
* `host`: host for callback; will be combined with path and protocol to construct callback url if `callbackUrl` is not specified (default: `localhost`)
* `entryPoint`: identity provider entrypoint
* `issuer`: issuer string to supply to identity provider
* `audience`: expected saml response Audience (if not provided, Audience won't be verified)
* `cert`: see [Security and signatures](#security-and-signatures)
* `privateCert`: see [Security and signatures](#security-and-signatures)
* `decryptionPvk`: optional private key that will be used to attempt to decrypt any encrypted assertions that are received
* `signatureAlgorithm`: optionally set the signature algorithm for signing requests, valid values are 'sha1' (default), 'sha256', or 'sha512'
* **Additional SAML behaviors**
* `additionalParams`: dictionary of additional query params to add to all requests; this can also be part of the options that are passed to `authenticate` for params to be added on a per-call basis
* `additionalAuthorizeParams`: dictionary of additional query params to add to 'authorize' requests
* `identifierFormat`: if truthy, name identifier format to request from identity provider (default: `urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress`)
* `acceptedClockSkewMs`: Time in milliseconds of skew that is acceptable between client and server when checking `OnBefore` and `NotOnOrAfter` assertion condition validity timestamps. Setting to `-1` will disable checking these conditions entirely. Default is `0`.
* `attributeConsumingServiceIndex`: optional `AttributeConsumingServiceIndex` attribute to add to AuthnRequest to instruct the IDP which attribute set to attach to the response ([link](http://blog.aniljohn.com/2014/01/data-minimization-front-channel-saml-attribute-requests.html))
* `disableRequestedAuthnContext`: if truthy, do not request a specific authentication context. This is [known to help when authenticating against Active Directory](https://github.com/bergie/passport-saml/issues/226) (AD FS) servers.
* `authnContext`: if truthy, name identifier format to request auth context (default: `urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport`)
* `forceAuthn`: if set to true, the initial SAML request from the service provider specifies that the IdP should force re-authentication of the user, even if they possess a valid session.
* `providerName`: optional human-readable name of the requester for use by the presenter's user agent or the identity provider
* `skipRequestCompression`: if set to true, the SAML request from the service provider won't be compressed.
* `authnRequestBinding`: if set to `HTTP-POST`, will request authentication from IDP via HTTP POST binding, otherwise defaults to HTTP Redirect
* **InResponseTo Validation**
* `validateInResponseTo`: if truthy, then InResponseTo will be validated from incoming SAML responses
* `requestIdExpirationPeriodMs`: Defines the expiration time when a Request ID generated for a SAML request will not be valid if seen in a SAML response in the `InResponseTo` field. Default is 8 hours.
* `cacheProvider`: Defines the implementation for a cache provider used to store request Ids generated in SAML requests as part of `InResponseTo` validation. Default is a built-in in-memory cache provider. For details see the 'Cache Provider' section.
* **Passport**
* `passReqToCallback`: if truthy, `req` will be passed as the first argument to the verify callback (default: `false`)
* `name`: Optionally, provide a custom name. (default: `saml`). Useful If you want to instantiate the strategy multiple times with different configurations,
allowing users to authenticate against multiple different SAML targets from the same site. You'll need to use a unique set of URLs
for each target, and use this custom name when calling `passport.authenticate()` as well.
* **Logout**
* `logoutUrl`: base address to call with logout requests (default: `entryPoint`)
* `additionalLogoutParams`: dictionary of additional query params to add to 'logout' requests
* `logoutCallbackUrl`: The value with which to populate the `Location` attribute in the `SingleLogoutService` elements in the generated service provider metadata.


### Provide the authentication callback

Expand Down Expand Up @@ -104,25 +114,47 @@ app.get('/login',

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).

The `decryptionCert` argument should be a certificate matching the `decryptionPvk` and is required if the strategy is configured with a `decryptionPvk`.
The `decryptionCert` argument should be a public certificate matching the `decryptionPvk` and is required if the strategy is configured with a `decryptionPvk`.


## Security and signatures

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

Authentication requests sent by Passport-SAML can be signed using RSA-SHA1. To sign them you need to provide a private key in the PEM format via the `privateCert` configuration key. For example:
Authentication requests sent by Passport-SAML can be signed using RSA-SHA1. To sign them you need to provide a private key in the PEM format via the `privateCert` configuration key. The certificate
should start with `-----BEGIN PRIVATE KEY-----` on its own line and end with `-----END PRIVATE KEY-----` on its own line.

For example:

```javascript
privateCert: fs.readFileSync('./cert.pem', 'utf-8')
```

It is a good idea to validate the incoming SAML Responses. For this, you can provide the Identity Provider's certificate using the `cert` confguration key:

It is a good idea to validate the signatures of the incoming SAML Responses. For this, you can provide the Identity Provider's public PEM-encoded X.509 signing certificate using the `cert` confguration key. The "BEGIN CERTIFICATE" and "END CERTIFICATE" lines should be stripped out and the certificate should be provided on a single line.

```javascript
cert: 'MIICizCCAfQCCQCY8tKaMc0BMjANBgkqh ... W=='
```

If you have a certificate in the binary DER encoding, you can convert it to the necessary PEM encoding like this:

```bash
openssl x509 -inform der -in my_certificate.cer -out my_certificate.pem
````

If the Identity Provider has multiple signing certificates that are valid (such as during the rolling from an old key to a new key and responses signed with either key are valid) then the `cert` configuration key can be an array:

```javascript
cert: [ 'MIICizCCAfQCCQCY8tKaMc0BMjANBgkqh ... W==', 'MIIEOTCCAyGgAwIBAgIJAKZgJdKdCdL6M ... g=' ]
```

The `cert` configuration key can also be a function that receives a callback as argument calls back a possible error and a certificate or array of certificates. This allows the Identity Provider to be polled for valid certificates and the new certificate can be used if it is changed:

```javascript
cert: function(callback) { callback(null,polledCertificates); }
```

## Usage with Active Directory Federation Services

Here is a configuration that has been proven to work with ADFS:
Expand All @@ -140,7 +172,7 @@ Here is a configuration that has been proven to work with ADFS:

Please note that ADFS needs to have a trust established to your service in order for this to work.

For more detailed instructions, see [this document from Tim Brody](docs/adfs/README.md).
For more detailed instructions, see [ADFS documentation](docs/adfs/README.md).

## SAML Response Validation - NotBefore and NotOnOrAfter

Expand Down Expand Up @@ -199,6 +231,10 @@ function callback(err, result)
Provide an instance of an object which has these functions passed to the `cacheProvider` config option when using Passport-SAML.
## ChangeLog
See [Releases](https://github.com/bergie/passport-saml/releases) to find the changes that go into each release.
## FAQ
### What if I have multiple SAML providers that my users may be connecting to?
Expand Down
Binary file added docs/adfs/NameIDFormatError.jpg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
16 changes: 16 additions & 0 deletions docs/adfs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,3 +109,19 @@ module.exports = passport;

var server = http.createServer(app);
```
# Troubleshooting

## ADFS 2016

If you are setting up an ADFS 2016 server, you might run into the following issue with the previous settings:

```
An error occurred during an attempt to read the federation metadata. Verify that the specified URL or host name is a valid federation metadata endpoint.
Verify your proxy server setting. For more information about how to verify you proxy sever setting, see the AD FS Troubleshooting Guide http://go.microsoft.com/fwlink/?LinkId=182180).
Error message: EntityDescriptor 'acme_tools_com'. ID0014: The value 'NamelDFormat' must be an absolute URI.
```

![NamelDFormat Error Popup](./NameIDFormatError.jpg)

If you remove the `identifierFormat`, it works as expected.

0 comments on commit 735509f

Please sign in to comment.