Logout and notifications

RP-initiated logout (end_session)

GET /oauth2?op=end_session
  id_token_hint                  (the user's most recent id_token)
  post_logout_redirect_uri       (registered in the portal; state passthrough supported)

With both parameters the U session ends and the browser returns to your page. Without them the standard U sign-out page runs.

Back-channel logout (recommended)

When the user signs out anywhere - your app, another app, or their U account - we POST a signed Logout Token to your registered back-channel endpoint:

POST your-endpoint (application/x-www-form-urlencoded)
logout_token=<JWT>

The token is RS256 with the same keys as id_tokens (verify against the JWKS) and carries iss, sub, aud (your client_id), iat, exp (120s), jti (unique - reject replays), and events. Respond 2xx quickly; we retry at 1m, 5m, 30m, 2h, 6h, then stop.

Verifying a Logout Token (PHP)

$parts = explode(".", $_POST["logout_token"]);
$claims = json_decode(base64_decode(strtr($parts[1], "-_", "+/")), true);
if (($claims["iss"] ?? "") !== "https://accounts.u.cash") exit("no");
if (($claims["aud"] ?? "") !== MY_CLIENT_ID) exit("no");
if (($claims["exp"] ?? 0) < time()) exit("no");
if (!isset($claims["events"]["http://schemas.openid.net/event/backchannel-logout"])) exit("no");
// 1. fetch /.well-known/jwks.json, pick the kid from the token header
// 2. openssl_verify(parts[0].".".parts[1], sig, pem_from_jwk, "sha256")
// 3. reject a jti you have seen before
http_response_code(200); // then clear the user's local session

Discovery advertises backchannel_logout_supported: true and backchannel_logout_session_supported: false (a logout applies to the subject, not to a per-app session).