Skip to content

Commit

Permalink
Support multiple and dynamic signing certificates
Browse files Browse the repository at this point in the history
In our organisation we roll the signing certificate for our ADFS servers every year.  During the roll over period the server provides two certificates which may be valid, so when a SAML response is provided it is valid if it is signed with either of those signatures.

This change has two methods that can be used when `passport-saml` is used by a long running service that will persist over the certificate roll over period.  The first change is to allow the `cert` configuration key to be an array, this allows for the old and new certificates to be checked during the roll over period.  The second change is to allow the `cert` configuration key to be a function that returns the valid certificate or certificates, this allows the service to poll the ADFS server for what the valid certificates are at this moment and update the signing certificates used by `passport-saml` as they change.
  • Loading branch information
richjharris committed Oct 23, 2017
1 parent da829fc commit d3a9bae
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 2 deletions.
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,18 @@ If you have a certificate in the binary DER encoding, you can convert it to the
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 and array:

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

The `cert` configuration key can also be a function that returns 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() { return polledCertificates; }
```

## Usage with Active Directory Federation Services

Here is a configuration that has been proven to work with ADFS:
Expand Down
15 changes: 15 additions & 0 deletions lib/passport-saml/saml.js
Original file line number Diff line number Diff line change
Expand Up @@ -476,6 +476,21 @@ SAML.prototype.validateSignature = function (fullXml, currentNode, cert) {
if (signatures.length != 1)
return false;
var signature = signatures[0];
var certsToCheck = cert;
if (typeof(cert) === 'function') {
certsToCheck = cert();
}
if (!Array.isArray(certsToCheck)) {
certsToCheck = [certsToCheck];
}
return certsToCheck.some(function (certToCheck) {
return self.validateSignatureForCert(signature, certToCheck, fullXml, currentNode);
});
};

// This function checks that the |signature| is signed with a given |cert|.
SAML.prototype.validateSignatureForCert = function (signature, cert, fullXml, currentNode) {
var self = this;
var sig = new xmlCrypto.SignedXml();
sig.keyInfoProvider = {
getKeyInfo: function (key) {
Expand Down
65 changes: 63 additions & 2 deletions test/tests.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit d3a9bae

Please sign in to comment.