In a SAML 2.0 <samlp:Response>, what does a <saml:EncryptedAssertion> protect that the TLS connection to the service provider does not?
answer
- the relay is a browser, not a wire
- protects the document, not the hop
- encrypted to the service provider's key
- one-off symmetric key, wrapped for transport
- confidentiality only, never origin
basics
~20 sA saml:EncryptedAssertion holds the assertion as ciphertext the identity provider encrypted to the service provider's public encryption key, so the browser relaying the document, its history, its logs and any intermediary see no plaintext subject or attributes.
solid answer
~50 sIn the Web Browser SSO profile the document does not travel on one wire: the identity provider hands it to the user's browser, which posts it on to the service provider. TLS protects each of those two hops, but the browser is an *endpoint* of both, so the user agent, its page history, an extension and anything logging the form body can read a plain `<saml:Assertion>`. Replacing it with a `<saml:EncryptedAssertion>` moves the protection from the hop to the document: the identity provider generates a one-off content-encryption key, encrypts the assertion element under it, and wraps that key to the service provider's public encryption key inside `<xenc:EncryptedKey>`. Only the holder of the matching private key recovers the subject and attributes. It is confidentiality only — the service provider must still verify the identity provider's signature, which encryption neither replaces nor implies.
code
xml · 19 lines<samlp:Response ID="_2a19f3" Version="2.0" IssueInstant="2026-09-19T10:14:02Z">
<saml:Issuer>https://idp.research-federation.example/idp</saml:Issuer>
<saml:EncryptedAssertion>
<xenc:EncryptedData Type="http://www.w3.org/2001/04/xmlenc#Element">
<xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes128-cbc"/>
<ds:KeyInfo>
<xenc:EncryptedKey>
<xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p"/>
<xenc:CipherData>
<xenc:CipherValue>d3JhcHBlZGNvbnRlbnRrZXk=</xenc:CipherValue>
</xenc:CipherData>
</xenc:EncryptedKey>
</ds:KeyInfo>
<xenc:CipherData>
<xenc:CipherValue>YXNzZXJ0aW9uY2lwaGVydGV4dA==</xenc:CipherValue>
</xenc:CipherData>
</xenc:EncryptedData>
</saml:EncryptedAssertion>
</samlp:Response>go deeper
Recall that an encrypted assertion protects the document itself, not the connection, because the user's browser relays it and can read anything left in the clear.
Explain the hybrid shape: a one-off symmetric content key encrypts the assertion, and that key is wrapped to the service provider's public key in xenc:EncryptedKey.
Show where the decision belongs: what sits in the AttributeStatement, which parties relay the document, and that encryption never substitutes for verifying the signature.
Frame it as a data-exposure boundary across organisations — which attributes you are willing to let a partner's browser population carry, and what that commits both sides to operationally.
## What the element replaces A SAML 2.0 `<samlp:Response>` normally carries one or more `<saml:Assertion>` children in clear XML: the `<saml:Subject>` naming the user, the `<saml:Conditions>` bounding validity, and an `<saml:AttributeStatement>` carrying whatever the identity provider is willing to say about them. At a national health research data-access portal those attributes are the sensitive part — a researcher's cohort entitlements, project identifiers, the consent classes they may open. A `<saml:EncryptedAssertion>` occupies exactly the position an `<saml:Assertion>` would, but its content is a single `<xenc:EncryptedData>` block. None of the assertion's structure survives in the clear. The same construction exists at finer grain: `<saml:EncryptedID>` replaces a `<saml:NameID>` and leaves the rest of the assertion readable, which is what a deployment reaches for when the identifier is the only sensitive field. ## Why the transport does not already cover it The instinct — "it is HTTPS, so it is confidential" — is right about the wire and wrong about the path. In the Web Browser SSO profile the document is relayed **by the user's own browser**: 1. The identity provider returns an HTML page whose form field `SAMLResponse` holds the base64 of the `<samlp:Response>`. 2. The browser submits that form to the service provider's assertion consumer endpoint. There are two TLS connections and the browser terminates both. Base64 is an encoding, not a protection; anyone who can read that form field reads the XML. The realistic exposures are unglamorous: a shared or kiosk machine, a browser extension with page access, an error page that echoes the posted body, a diagnostic capture taken by the very team debugging the integration, a proxy that logs form parameters. Encrypting the assertion is what makes the document safe to pass through a party you do not control. | Layer | Covers | Leaves exposed | |---|---|---| | TLS on each hop | Bytes between two endpoints | Both endpoints, including the relaying browser | | Base64 of `SAMLResponse` | Nothing — it is transfer encoding | The whole XML to anyone who decodes it | | `<saml:EncryptedAssertion>` | Subject and attributes, end to end between identity provider and service provider | The `<samlp:Response>` envelope, `<saml:Issuer>`, `RelayState`, message identifiers and timestamps | That last row matters: encrypting the assertion does not hide *that* a federated login happened, nor who issued it. ## The two-layer key shape Public-key operations cover only a small block, so XML Encryption uses the standard hybrid shape and SAML inherits it: - a fresh symmetric **content-encryption key** is generated for this one assertion; - the assertion element is bulk-encrypted under it, the algorithm named in `<xenc:EncryptionMethod>` — for example `http://www.w3.org/2001/04/xmlenc#aes128-cbc`; - that symmetric key is itself encrypted to the service provider's **public** encryption key and carried alongside in `<xenc:EncryptedKey>`, with its own `<xenc:EncryptionMethod>` naming a key-transport algorithm such as `http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p`; - both ciphertexts sit in `<xenc:CipherValue>` elements. The service provider decrypts `<xenc:EncryptedKey>` with its private key, recovers the content-encryption key, and decrypts the assertion back into an XML element it can then parse. ## What it does not do The direction of each key is where candidates slip. The assertion is **signed with the identity provider's private key** and **encrypted to the service provider's public key** — two different keys held by two different parties, doing two different jobs. Encryption gives confidentiality and says nothing about origin: a recipient that decrypts successfully has learned only that somebody encrypted to its key, which anybody holding the public key can do. Authenticity comes solely from the `<ds:Signature>`, and a service provider that treats a successful decryption as proof of issuance has removed its own authentication step. Encryption is also optional in the protocol. A great many production federations run with signed, unencrypted assertions and accept that the browser sees the attributes, because the attributes are a username and an email address. The decision is about what sits in the `<saml:AttributeStatement>`, not about conformance. Finally, encrypting the assertion does not stop the document being replayed or the receiver being made to act on an element it never verified. Those are properties of what the signature covers and of how the receiver selects what it consumes — separate questions, and the ones where SAML deployments actually get hurt.
- If the assertion as a whole is left in the clear, what can <saml:EncryptedID> still protect?Only the identifier. `<saml:EncryptedID>` stands where a `<saml:NameID>` would and holds the same `<xenc:EncryptedData>` construction, so the subject's identifier is unreadable while the `<saml:Conditions>` and the `<saml:AttributeStatement>` remain plain XML. It is the choice when the identifier is the sensitive value and the rest is not.
- Why is a one-off symmetric key wrapped in <xenc:EncryptedKey> rather than encrypting the assertion directly under the public key?A key-transport algorithm such as `rsa-oaep-mgf1p` can cover only a block far smaller than an assertion, and public-key operations are slow. So a fresh content-encryption key does the bulk work in `<xenc:EncryptedData>`, and only that short key is encrypted to the recipient's public key. Each assertion gets its own content key.
- A service provider decrypts an assertion successfully. What has that proved about who sent it?Nothing. Anyone holding the service provider's published encryption key can produce a well-formed `<saml:EncryptedAssertion>` it will decrypt cleanly. Origin comes only from verifying the `<ds:Signature>` against the identity provider's key, which is a separate step the receiver must still perform on the decrypted element.
TLS is a locked van between two depots; the courier still carries the papers inside and reads them at every stop. An encrypted assertion is a sealed envelope handed to that courier — the van is still locked, but the courier is no longer a reader.
saying these in an interview costs you the question
- Says TLS already makes the assertion confidential end to end.
- Treats successful decryption as proof of who issued the assertion.
- Claims the assertion is encrypted with the identity provider's private key.
- Thinks base64 of SAMLResponse is itself a form of protection.
- Assumes every SAML deployment encrypts assertions by default.