Skip to main content

Upgrading to 5.0 from 4.x

5.0.0 moves the crypto backend to litesaml/lightsaml 6.0, which upgrades robrichards/xmlseclibs from 3.x to 4.x and adds phpseclib/phpseclib. xmlseclibs 4 is safe-by-default: it refuses RSA-1.5 key transport when decrypting and binds the signature and key-transport algorithms it will accept. As a result litesaml/saml now emits encrypted assertions with RSA-OAEP instead of RSA-1.5, and rejects inbound assertions encrypted with RSA-1.5.

The public API is unchanged — no method signatures move. If you don't use assertion encryption, upgrading is a Composer bump and nothing else.

Why​

litesaml/saml delegates all XML cryptography to lightsaml, which in turn delegates to robrichards/xmlseclibs. xmlseclibs 4.0 is a security release: it drops the weak defaults that made XML encryption and signatures historically fragile — RSA-1.5 key transport (the Bleichenbacher padding-oracle class), unbound signature algorithms (algorithm substitution and key confusion), and pre-authentication denial of service through XPath-filter transforms and DOCTYPE entity expansion.

Adopting it means lightsaml 6.0, and lightsaml 6.0 flips the EncryptedAssertion writer default from RSA-1.5 to RSA-OAEP. litesaml/saml 5.0 is the release that carries both through — a new major because the on-the-wire format of encrypted assertions changes and some previously accepted inbound messages are now refused.

1. Update the dependency​

composer require "litesaml/saml:^5.0"

litesaml/saml 5.0 requires litesaml/lightsaml ^6.0, which pulls in robrichards/xmlseclibs ^4.0 and phpseclib/phpseclib ^3.0 transitively. If your project requires any of these directly, widen the constraint.

Nothing else is needed if you don't encrypt or decrypt assertions.

2. Encrypted assertions now use RSA-OAEP​

There is nothing to change in your code — the algorithm switch is internal:

4.x5.0
Key transportRSA-1.5 (http://www.w3.org/2001/04/xmlenc#rsa-1_5)RSA-OAEP (http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p)
Block cipherAES-128-CBCAES-128-CBC (unchanged)

What you do need to check is the peer on the other end:

  • You are the IdP — sendAuthnResponse() with encrypted: true attributes: the receiving SP must be able to decrypt RSA-OAEP. Every current SAML implementation can; only very old stacks that hard-code RSA-1.5 will fail, and those need a config change on their side.
  • You are the SP — handleAuthnResponse(): if a partner IdP still encrypts with RSA-1.5, handleAuthnResponse() now throws (see the next section). Ask them to switch to RSA-OAEP — a one-line change on every major IdP (ADFS, Keycloak, Microsoft Entra ID, SimpleSAMLphp, Shibboleth).

3. RSA-1.5 encrypted assertions are rejected on decrypt​

xmlseclibs 4 refuses RSA-1.5 key transport during decryption by default — it is the algorithm behind the Bleichenbacher padding-oracle attacks. litesaml/saml exposes no opt-in.

If handleAuthnResponse() receives an assertion whose EncryptedKey uses xmlenc#rsa-1_5, it now throws:

Litesaml\Exceptions\SamlException: Failed to decrypt assertion: ...

In 4.x the same message decrypted. Handle it like any other SamlException from handle*():

use Litesaml\Exceptions\SamlException;

try {
$authnResponse = $spWrapper->handleAuthnResponse($request);
} catch (SamlException $e) {
// includes "Failed to decrypt assertion: ..." when the IdP used RSA-1.5
}

In 4.x a decryption failure surfaced as a raw RobRichards\XMLSecLibs exception; 5.0 wraps it in SamlException so a single catch covers the whole handle*() call.

4. Stricter signature validation​

xmlseclibs 4 also hardens signature verification, which litesaml/saml runs whenever you pass a Validate context. These checks are transparent for well-formed SAML from a compliant peer, but a non-compliant sender whose messages "worked" in 4.x may now fail Validate:

  • documents containing a DOCTYPE are rejected
  • XPath-filter transforms inside the signature are rejected
  • the SignatureMethod is bound to the key type, so an algorithm-substitution attempt (for example downgrading RSA-SHA256 to an HMAC verified with the public certificate) no longer validates

If a partner's messages start failing Validate after the upgrade, their signing setup was relying on one of these behaviours; the fix is on their side.

5. What did not change​

  • The encrypted-attribute API: new Attribute('ssn', ['...'], encrypted: true) inside a ContextList, exactly as in 4.x.
  • The block cipher (AES-128-CBC), certificate configuration, and metadata — generateMetadata() output is byte-for-byte the same.
  • Message signing: still RSA-SHA256 with a SHA-256 digest.
  • Every code path that does not touch encryption or signature verification.

See Encrypt assertion and Decrypt assertion for the updated reference.