What does a SAML `<LogoutResponse>` whose second-level `<StatusCode>` is `PartialLogout` tell the initiator?
answer
- success is not the same as complete
- top level says Success, nested code qualifies
- at least one participant never confirmed
- unconfirmed is not the same as live
- second-level status code, never the top one
basics
~20 sThe exchange itself worked, the outcome did not: the session authority ended what it could, and at least one session participant never confirmed. The top-level code stays Success, so a caller reading only that level reports a clean logout it did not get.
solid answer
~40 sSAML status is two levels deep. The top-level `<StatusCode>` says whether the message was processed — `urn:oasis:names:tc:SAML:2.0:status:Success` here — and a nested second-level code qualifies the outcome. `urn:oasis:names:tc:SAML:2.0:status:PartialLogout` is that qualifier: the session authority terminated its own session and every participant it could, and at least one participant did not confirm. A session authority is required to return it when propagation was incomplete. For the initiator the practical meaning is: do not tell the user they are signed out everywhere. End your own session, record which participants are unaccounted for, and surface an honest message — some applications may still be open, closing the browser is the reliable step. Treating it as a failure and retrying blindly is as wrong as treating it as clean.
code
xml · 17 lines<samlp:LogoutResponse
xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
ID="_c04ab712" Version="2.0"
IssueInstant="2026-09-19T10:04:19Z"
InResponseTo="_8f2c1a63"
Destination="https://review.example.com/sp/slo">
<saml:Issuer>https://idp.example.org</saml:Issuer>
<samlp:Status>
<samlp:StatusCode
Value="urn:oasis:names:tc:SAML:2.0:status:Success">
<samlp:StatusCode
Value="urn:oasis:names:tc:SAML:2.0:status:PartialLogout"/>
</samlp:StatusCode>
<samlp:StatusMessage>2 of 5 participants did not confirm</samlp:StatusMessage>
</samlp:Status>
</samlp:LogoutResponse>go deeper
Recall that a logout can come back successful and still be incomplete, and that a nested status code is how the exchange says so.
Explain the two levels of status: the top level reports processing, the nested code reports the outcome, and the code appears only at the second level.
Show what you do with it — the user-facing wording you choose, what you record about the unaccounted participants, and why you do not retry.
The question to own is what an incomplete logout means contractually, and whether the estate needs shorter participant sessions rather than a better logout story.
## Two levels of status, and only one of them is about the outcome Every SAML response message carries a `<samlp:Status>` element containing a `<samlp:StatusCode>` with a `Value` attribute holding a URI. The top level answers a narrow question: could the responder process this message at all? It takes one of a small set of values — `urn:oasis:names:tc:SAML:2.0:status:Success`, `urn:oasis:names:tc:SAML:2.0:status:Requester` when the fault lay with the sender, `urn:oasis:names:tc:SAML:2.0:status:Responder` when the responder itself failed, `urn:oasis:names:tc:SAML:2.0:status:VersionMismatch`. The interesting detail is that a `<samlp:StatusCode>` may *nest* another one. The inner code is the second level, and it qualifies the outcome. `urn:oasis:names:tc:SAML:2.0:status:PartialLogout` only ever appears there, under a top-level `Success`. ## What the code actually asserts A session authority that receives a `<LogoutRequest>` walks its list of session participants. When it cannot get every one of them to confirm, it must say so, and the second-level code is how. Read precisely, it asserts: - the authority processed the request and ended its own session; - it attempted propagation to the participants it knows about; - **at least one participant did not confirm** that it ended the session. Note what it does *not* assert. It does not say those participants are still logged in. A participant may have ended the session perfectly and then failed to get its `<LogoutResponse>` back — a browser that never returned from a front-channel hop is the classic case. Unconfirmed and still-live are different states, and the code reports the first. ## How the initiator should read each status | status on the `<LogoutResponse>` | meaning | what the initiator does | |---|---|---| | top-level `Success`, no nested code | every participant confirmed | end the local session and report a completed logout | | top-level `Success` with nested `PartialLogout` | propagation was incomplete | end the local session, qualify the message to the user, record the gap | | top-level `Requester` | the request itself was at fault | fix the message; the federated session is untouched | | top-level `Responder` | the responder could not process it | treat the exchange as failed; nothing was propagated | The two rows that get confused are the second and the fourth. A `Responder` status means nothing happened. A nested `PartialLogout` means most of it happened. Retrying makes some sense in the first case and little in the second, where a retry re-runs a propagation that already largely succeeded. ## What to put in front of the user This is where a partial logout does real damage, because the honest answer is uncomfortable. A user who is shown *You have been signed out of all applications* after a partial logout has been told something false by a system that knew it was false. Reasonable handling: 1. End the local application session unconditionally — that part is yours and it always works. 2. If the response carried a nested `PartialLogout`, say that sign-out could not be confirmed for every connected application, and that closing the browser is the reliable step. 3. Record which participants were unaccounted for, with the principal identifier and the session index, so an operator can answer the question later. 4. Do not loop. The profile places no retry obligation on anyone, and a client-side retry loop mostly generates traffic. ## Why it exists at all A protocol that could only say *success* or *failure* would force the authority into a lie either way: reporting failure after ending four sessions out of five, or reporting success after ending four out of five. The second-level code exists because the designers accepted that this exchange is best-effort and decided the honest outcome deserved a name on the wire. That is also why the code is worth asking about in an interview: a candidate who knows it exists usually also knows *why* logout half-works, and a candidate who has only read the happy path does not. In the e-discovery setting, this is the difference between an engagement-closure report that says *access ended* and one that says *access ended at the review tool and the document store; the transcript viewer did not confirm*. The second is the one counsel can act on.
- What should a service provider show the user after a partial logout?That its own session has ended, and that sign-out could not be confirmed for every connected application, with closing the browser offered as the reliable step. An unqualified *signed out everywhere* is a claim the response explicitly refused to make. The detail of which participants were unaccounted for belongs in the operator's record, not in the user's message.
- How does a nested `PartialLogout` differ from a top-level `Responder` status?`urn:oasis:names:tc:SAML:2.0:status:Responder` reports that the responder could not process the message at all, so nothing was propagated and the federated session is intact. A nested `PartialLogout` sits under `Success`: the exchange ran and the outcome was incomplete. One invites a retry, the other mostly does not.
- Does an unconfirmed participant mean that session is definitely still live?No. It means no confirmation arrived. The participant may have ended the session and then lost the response — a user who closed the tab during a front-channel chain produces exactly that. The authority cannot distinguish the two, which is why the code is worded around confirmation rather than around the session's state.
saying these in an interview costs you the question
- Reads a nested PartialLogout as an outright failure worth retrying in a loop.
- Shows the user signed out of everything after a partial logout.
- Thinks PartialLogout appears as the top-level status code value.
- Assumes the session authority retries the participants that never answered.
- Believes an unconfirmed participant is proof that session is still live.