There are a few typical reasons for supplying the SP with multiple keypairs, or "credentials", to use for authentication and encryption:
- separating signing/TLS and encryption keys
- key "rollover"
- federation or partner-dictated requirements to use particular certificates
These scenarios are discussed in more detail below, with examples explaining how to configure the SP in each case. In each scenario, the common factor is the use of a "Chaining"
<CredentialResolver> to "wrap" two or more individual resolvers (usually of type "File") and enable each credential to be loaded and used. The varying part pertains to how credentials are labeled so that the selection process works as intended in each case.
Note also that the use of encryption in this context is specific to XML Encryption, and for the present, limited to use of SAML 2.0.
Separate Signing and Encryption Keys
This is the simplest (but also not all that common) case, and is handled by labeling the individual resolvers in the chain with a
use property, typically of "signing" or "encryption".
For this use case, no additional labeling or configuration should be necessary to get the right key selected.
Typically with rolling over keys or certificates you have two separate concerns: migrating your signing/authentication keys and your encryption keys. On the authentication side, the solution is to publish the new key/certificate in your metadata and wait for that to propagate before switching your SP from the old credential to the new one. In that scenario, you need not ever configure both within the SP itself (i.e., it's different from this topic's goal).
On the other hand, with encryption you have the opposite problem. Once you publish a new key in your metadata, your peers may start using it but not all of them will switch at the same time. So in this case, you MUST configure both the old and new credentials into the SP so that either key can be available for decryption.
It's likely the case that both of these scenarios apply; often, a single credential is used for both signing and encryption and the migration is from one credential for both to another for both.
Therefore, combining these issues, the simplest approach is:
- Add the second key to your SP configuration explicitly as an encryption key.
- Publish the new key in your metadata and wait for propagation.
- Remove the old key and the usage constraint from your SP configuration.
As an example, if you start here:
Then the configuration after step 1 might be:
And after step 3:
Multiple Certificate Scenarios
The most complex (and ill-advised) case is if you're trying to selectively apply different keys or certificates when interacting with different relying parties. The primary advice on this is "don't". Unfortunately, this isn't always possible, as some federations insist on imposing PKI-based constraints on their members. To accomodate this, the SP includes a mechanism for attaching "names" to credentials and then referencing the credentials in a
While this is seemingly straightforward (once you see an example), attaching names to credentials has the side effect of influencing the credential selection process in ways that can be difficult to understand or diagnose. This is because attaching names will act as a filter when selecting decryption keys, and can introduce various errors if the names aren't chosen carefully.
In versions of the XMLTooling library prior to 1.3.2, a certain amount of automatic processing took place that tended to simplify the use of this feature, but it also was discovered to cause other errors and had to be scaled back for the time being. As a result, there will typically be more thought required when naming credentials, and this material accounts for this change. A future version of the library may improve the situation, and this documentation will be updated at that point.
Assuming a scenario in which you want to use one credential by default, but a second credential when dealing with a particular relying party, you will typically do the following:
- Configure both credentials together in a chain.
- Attach a
<Name>element to each credential.
- Add one or more
<RelyingParty>elements in the appropriate spot with a matching
Now, a few cautions and warnings about how to avoid problems (and note again that none of this matters unless you have to name your credentials to begin with):
Once you name one credential, you generally will need to attach names to all of them. Prior to the library change mentioned above, you could avoid this, but skipping that now will usually result in the "nameless" credential being used by default if it appears ahead of the named one in the chain. In the example above, both credentials are named, even though only the second one is referenced up above within a
<RelyingParty> element. This prevents the first credential from "satisfying" a lookup for a key to use with the named IdP because it has no name to filter against.
The names you use are essentially arbitrary when it comes to signing and referencing from a
<RelyingParty> element, but once you've attached a name to a credential, you will typically find that decryption of encrypted XML starts breaking if the name(s) used don't bear a relationship to what's in the certificate. This is because the information in the certificate found inside the encrypted data is used to help identify the decryption key to use and if the names don't overlap, it will fail.
This problem was a side effect of the library change mentioned above, because originally the names were extracted silently from the certificate you provide locally, and they would match the names extracted from the certificate in the message. For now, at least, you need to supply these names yourself, which is just a matter of naming the credential using the "CN" from the certificate subject or using a subjectAltName.
As a result, to avoid problems, you should name credentials using the "CN" of the certificate subject or use a subjectAltName. If the two credentials happen to share identical certificate name(s), then you should include both a name from the certificate and a name that is locally chosen. The local name is then used to reference the credential in a
<RelyingParty> element, while including the certificate-derived name ensures that decryption proceeds properly.