# Logout notifications

M7 supports front-channel and back-channel logout for applications that have
participated in a root SSO login session. Both discovery documents advertise
these capabilities, verified on 2026-09-20 at 02:58:25 UTC. A notification tells
your application to end the matching local session; your receiver is responsible
for carrying out that action.

## What triggers a notification

| Action | Front channel | Back channel |
| --- | --- | --- |
| Confirmed SSO end-session logout, including an individual remembered-account × | Yes, for registered participating apps | Yes, for registered participating apps |
| Explicit logout × in the account chooser | Yes | Yes |
| Revoke a root session through account session management | No; the target browser may be absent | Yes |
| Ordinary account selection, switching, re-login or session replacement | No | No |

Notifications follow confirmed revocation of the selected root and its token
family. They do not run merely because the logout page is opened. Expiry,
password changes and other implicit invalidations are outside these notification
triggers. **Log Out These** concerns the matching remembered sessions in that
browser/context; it is not an account-wide, all-devices operation.

Applications join the notification set at successful OpenID Connect
authorization-code pickup at `/token`. Only pickups made after this feature was
installed are tracked. Sign in again before testing an older session. Device
grants, client credentials and independent token families are not added to this
browser-root set.

ID tokens carry a stable `sid` identifying the original root login; refresh
rotation preserves it. Store it with the validated issuer and your application's
local session. The local account-management record ID, ID-token `jti`, and
root `sid` are different identifiers. Several applications can share one root.

## Register receiving URLs

Use [Dynamic Client Registration](https://m7.org/docs/api/sso.user.m7.org/registration.md) or
[application management](https://m7.org/docs/api/api.user.m7.org/oauth-clients#logout-notification-settings).

| Field | Meaning |
| --- | --- |
| `frontchannel_logout_uri` | HTTPS browser receiver. Scheme, host and port must match a registered sign-in redirect URI. |
| `backchannel_logout_uri` | HTTPS server receiver. A different host or port is permitted. |
| `frontchannel_logout_session_required` | Standard registration boolean, default false; declares that the receiver requires `iss` and `sid`. |
| `backchannel_logout_session_required` | Standard registration boolean, default false; declares that the receiver requires `sid`. |

Both URLs allow static query parameters, must be at most 2,048 characters,
and cannot contain credentials or fragments. Configure only receivers you operate.
Current registration is used at delivery time; removing a URL disables that channel.
A true session-required flag requires its corresponding URL.

**M7 always sends `sid` on both channels, and `iss` on the front channel.**
False or omitted session-required flags do not suppress these values or disable
delivery. User.M7 therefore presents the two URL fields without session-ID
checkboxes. Its Client → Logout tab appears when editing an existing application
and has a separate **Update Logout Settings** action. Post-logout redirect URIs
remain under General: they control the final browser destination, not receivers.
Saving configuration alone does not send a notification or end a session.

## Front-channel receiver

M7 loads each registered URL in a hidden iframe with `iss` and `sid` query
parameters. For example:

```text
GET https://app.example.com/logout/front?iss=https%3A%2F%2Fsso.user.m7.org&sid=ROOT_SESSION_ID
```

The receiver should check the exact trusted issuer and associate the `sid`
with its own session before clearing that session. It must be usable within
an iframe from the provider origin. Browser cookie and framing policies can
prevent access to local state; front-channel logout is not a reliable way to
terminate sessions on another device.

M7 waits for frame completion or a 2.5-second limit, then continues to the
validated return destination. A Continue link supports manual navigation.
Frame completion is not proof that the application cleared its cookies.

## Back-channel receiver

M7 sends an HTTPS `POST` with `Content-Type: application/x-www-form-urlencoded`
and one form field, `logout_token`. The request does not depend on browser
cookies or a current browser login.

The token is a signed JWT with protected-header `typ: logout+jwt`. It contains:

| Claim | Value |
| --- | --- |
| `iss` | Canonical SSO issuer, `https://sso.user.m7.org` |
| `aud` | Receiving application's public OAuth client ID |
| `sub` | Subject associated with the participating root |
| `sid` | Original root session identifier |
| `iat`, `exp` | Issue time and expiry, with a 120-second lifetime |
| `jti` | Unique notification identifier |
| `events` | An object containing `http://schemas.openid.net/event/backchannel-logout` with an empty object value |

There is no `nonce`. The current registered ID-token signing algorithm also
applies to Logout Tokens. Required ID-token response encryption applies too:
decrypt the compact JWE, then validate the inner signature and claims. See
[response encryption](https://m7.org/docs/api/sso.user.m7.org/response-encryption.md). This artifact is never an access
or refresh credential and must not be accepted for sign-in or API authorization.

A receiving application must validate the signature using trusted issuer keys
or the configured HMAC secret, supported algorithm, issuer, audience, token
type, time claims, logout event and session association. Reject malformed or
inappropriate tokens and handle duplicates safely. Do not trust claims from
an unverified decoded token. On accepted processing, return HTTP 200; use
HTTP 400 for an invalid Logout Token. An already-ended matching session can
be acknowledged without requiring the user to return first.

Delivery uses public HTTPS destinations, TLS verification and no redirects.
Requests have a one-second connection timeout and three-second overall timeout,
with bounded concurrency. Notification failure does not restore a revoked root.
Explicit browser logout makes a best-effort attempt without a persistent retry
queue. Account session revocation separately records pending work for service
reconciliation; applications must tolerate a repeated notification. HTTP success
proves receiver acceptance, not application-side invalidation.

## Current M7 Web/PHP SDK boundary

The updated source installed in User.M7 and Drop exposes:

```text
GET  /m7_sso_session/frontchannel-logout
POST /m7_sso_session/backchannel-logout
```

The front receiver clears that browser's SDK cookies. It does not yet match
incoming `sid` against a stored local session. The back receiver validates the
notification and returns `ok`; **it does not invalidate application sessions**.
Application-side enforcement and further SDK tuning are separate work.

The current Web/PHP verifier supports RS256/RS512 through OpenSSL and Ed25519
when the optional `ext-m7crypto` runtime is available. With no
`M7_ID_TOKEN_SIGNED_RESPONSE_ALG` setting it verifies an incoming supported
algorithm. An explicit setting additionally pins that algorithm. Unsupported
algorithms or missing native support produce `algorithm_unsupported`; a
supported algorithm that differs from an explicit pin produces
`algorithm_mismatch`. Signature and claim validation always remain required.
Do not infer receiver support from the wider token SDK's algorithm list.

Receiver failures return a bounded reason and correlation ID. The sender can
record the recognized reason and ID alongside the HTTP status; use them to
correlate receiver logs without recording tokens or arbitrary response bodies.
These installed-source capabilities do not imply that previously published
immutable SDK archives include the receivers or their latest fixes.

## Integration check

1. Deploy a compatible receiver and save its URL on the correct client.
2. Complete a fresh OpenID sign-in to that application to record participation.
3. Explicitly log out one remembered account and check that only its matching
   application session is ended by your receiver.
4. Test the browser's grouped logout and the chooser × separately. Account
   switching should not generate notifications.
5. Test [own-session revocation](https://m7.org/docs/api/api.user.m7.org/sessions)
   from another session: expect back-channel delivery, with no front-channel frame.
6. Check invalid-token rejection, duplicate receipt and unavailable-receiver
   handling. A 200 from the current SDK back receiver tests receipt only.

Protocol references: [OpenID Connect Front-Channel Logout](https://openid.net/specs/openid-connect-frontchannel-1_0.html)
and [OpenID Connect Back-Channel Logout](https://openid.net/specs/openid-connect-backchannel-1_0.html).
