|
| 1 | +--- |
| 2 | +outline: [2, 4] |
| 3 | +--- |
| 4 | +# abap2UI5 — Logoff guide for Launchpad, ICF handler, and BSP |
| 5 | + |
| 6 | +> **TL;DR** The `SYSTEM_LOGOUT` client event behaves differently depending on **how the app was started**, because SAP exposes three independent session layers (FLP shell, ICF/SSO, BSP context) and no single browser-side action terminates all three. This guide explains each layer, what `SYSTEM_LOGOUT` does in each startup context, and which options you have to customize the behavior. |
| 7 | +
|
| 8 | +See sample `Z2UI5_CL_DEMO_APP_361` for a working example that triggers the `system_logout` client event. |
| 9 | + |
| 10 | +--- |
| 11 | + |
| 12 | +## 1. The three startup contexts |
| 13 | + |
| 14 | +abap2UI5 can be launched in three ways. The JavaScript that runs on the client is the **same** in all three — the difference is which session layers exist around it. |
| 15 | + |
| 16 | +| Context | Typical URL | Server runtime | FLP shell loaded? | |
| 17 | +|---|---|---|---| |
| 18 | +| **Fiori Launchpad tile** | `…/sap/bc/ui2/flp#Z2UI5-display` | ICF + UI2 services | ✅ yes | |
| 19 | +| **ICF HTTP handler** (e.g. `Z2UI5_CL_HTTP_HANDLER`, `Z2UI5_CL_LP_HANDLER`) | `…/sap/bc/<your-service>` | Plain ICF | ❌ no | |
| 20 | +| **BSP application** (`Z2UI5`, `Z2UI5_V2`) | `…/sap/bc/bsp/sap/z2ui5/index.html` | BSP runtime, **stateful** by default | ❌ no | |
| 21 | + |
| 22 | +--- |
| 23 | + |
| 24 | +## 2. The three SAP session layers |
| 25 | + |
| 26 | +Different cookies, different lifetimes, different ways to terminate. |
| 27 | + |
| 28 | +| Layer | What it represents | Cookie / identifier | Lifetime / scope | |
| 29 | +|---|---|---|---| |
| 30 | +| **A. FLP shell session** | The Fiori Launchpad UI runtime in the browser | In-memory `sap.ushell.Container` state, plus underlying ICF session | Tab-bound, only exists if FLP was loaded | |
| 31 | +| **B. ICF / SSO logon** | AS ABAP authenticated session | `MYSAPSSO2`, `SAP_SESSIONID_<sid>_<client>` | Path-scoped to `/sap/`, killed by `/sap/public/bc/icf/logoff` | |
| 32 | +| **C. BSP stateful context** | BSP runtime app state on the application server (visible in `SM04` as Plugin HTTP) | `sap-contextid` scoped to `/sap/bc/bsp/sap/<app>/` | Per-app, killed by `?sap-sessioncmd=logoff` on a URL inside that BSP app | |
| 33 | + |
| 34 | +**Crucial:** these are independent. Killing one does **not** kill the others. And in any **SSO / IdP** setup (SAML, Kerberos, X.509, custom OIDC) the next request to a protected SAP URL silently re-authenticates regardless — see §6. |
| 35 | + |
| 36 | +--- |
| 37 | + |
| 38 | +## 3. What `SYSTEM_LOGOUT` actually does |
| 39 | + |
| 40 | +The button on the demo `Z2UI5_CL_DEMO_APP_361` triggers the client event `cs_event-system_logout`. The JS handler is identical across all three runtimes; pseudocode: |
| 41 | + |
| 42 | +``` |
| 43 | +SYSTEM_LOGOUT(args): |
| 44 | + logoutUrl = args[1] || '/sap/public/bc/icf/logoff' |
| 45 | +
|
| 46 | + try: |
| 47 | + if z2ui5.oLaunchpad?.Container?.logout: # only inside FLP shell |
| 48 | + z2ui5.oLaunchpad.Container.logout() # terminates layer A |
| 49 | + else: |
| 50 | + redirectToLogoff() # fallback path |
| 51 | + catch: redirectToLogoff() |
| 52 | +
|
| 53 | +
|
| 54 | +redirectToLogoff(): |
| 55 | + # NEW (since the BSP fix): also handle layer C when running inside BSP |
| 56 | + if window.location.pathname.startsWith('/sap/bc/bsp/'): |
| 57 | + # Hit the BSP path with sap-sessioncmd=logoff via a hidden iframe. |
| 58 | + # BSP runtime calls server->session->terminate( ). |
| 59 | + <fire iframe to "<bsp-path>?sap-sessioncmd=logoff"> |
| 60 | + <on iframe load, OR after 1.5s safety timeout:> |
| 61 | + window.location.href = logoutUrl # then go drop layer B |
| 62 | + else: |
| 63 | + window.location.href = logoutUrl # ICF/handler stays as before |
| 64 | +``` |
| 65 | + |
| 66 | +### What this terminates per startup context |
| 67 | + |
| 68 | +| Context | A – FLP shell | B – ICF/SSO | C – BSP context | |
| 69 | +|---|---|---|---| |
| 70 | +| Fiori Launchpad tile | ✅ via `Container.logout()` | depends on FLP shell wiring | n/a | |
| 71 | +| ICF HTTP handler | n/a | ✅ via `/sap/public/bc/icf/logoff` | n/a | |
| 72 | +| BSP application | n/a | ✅ via `/sap/public/bc/icf/logoff` | ✅ via `?sap-sessioncmd=logoff` *(new)* | |
| 73 | + |
| 74 | +**This is the whole feature** — there is no client-side mechanism that can terminate a layer that wasn't loaded into the page. A BSP page cannot log out the FLP shell, because no FLP shell is mounted on it. The same constraint holds in reverse. |
| 75 | + |
| 76 | +--- |
| 77 | + |
| 78 | +## 4. Why the BSP fix was needed |
| 79 | + |
| 80 | +`/sap/public/bc/icf/logoff` invalidates layer B only. The BSP runtime keeps its **layer C** stateful context alive on the server (you'd see it in `SM04` as a Plugin HTTP session) and the cookie `sap-contextid` stays scoped to `/sap/bc/bsp/sap/<app>/`. Returning to the BSP URL (or any cached state) re-attaches to that context. |
| 81 | + |
| 82 | +The canonical SAP-standard mechanism for terminating a BSP context is `?sap-sessioncmd=logoff` on a request inside the BSP namespace. SAP itself uses exactly this pattern in `CL_BSP_LOGIN_APPLICATION`, `CL_BSP_LOGOFF_APPL_TAG`, the CRM IC framework, and several `*.wapa.leave.htm` BSP pages — typically delivered via a hidden 1×1 element so the redirect happens silently. |
| 83 | + |
| 84 | +The patched JS does the same: a hidden iframe → `?sap-sessioncmd=logoff` → on load, redirect to `logoutUrl`. The non-BSP branch is unchanged. |
| 85 | + |
| 86 | +--- |
| 87 | + |
| 88 | +## 5. Where this lives in the code |
| 89 | + |
| 90 | +When you customize, edit only one of these — pick the one that matches your runtime. |
| 91 | + |
| 92 | +| Object | Type / Package | Role | |
| 93 | +|---|---|---| |
| 94 | +| `Z2UI5_CL_APP_VIEW1_JS` | CLAS / `$ZLK_00_01_03` | Generates the JS for the **ICF handler** runtime | |
| 95 | +| `Z2UI5` (`controller/View1.controller.js`) | WAPA / `$ZLK_01_02` | JS served from MIME repository for **BSP V1** | |
| 96 | +| `Z2UI5_V2` (`cc/Actions.js`) | WAPA / `$ZLK_02` | JS served from MIME repository for **BSP V2** | |
| 97 | +| `Z2UI5_CL_DEMO_APP_361` | CLAS / `$ZLK_06_02` | Demo that fires the `system_logout` client event | |
| 98 | +| `Z2UI5_IF_CLIENT` | INTF | Defines the `cs_event-system_logout` constant | |
| 99 | + |
| 100 | +> **Important:** the JS is duplicated in three places. If you change the logoff behavior, change it in all three so the runtime you're not testing today doesn't drift. |
| 101 | +
|
| 102 | +--- |
| 103 | + |
| 104 | +## 6. Your customization options |
| 105 | + |
| 106 | +There are exactly four levers. Pick based on what you want, not all of them at once. |
| 107 | + |
| 108 | +### Lever 1 — Override the post-logoff URL per call |
| 109 | + |
| 110 | +Pass any same-origin URL as `args[1]` of the `system_logout` event. The JS uses it instead of `/sap/public/bc/icf/logoff`. |
| 111 | + |
| 112 | +```abap |
| 113 | +client->_event_client( |
| 114 | + val = client->cs_event-system_logout |
| 115 | + t_arg = VALUE #( ( `/sap/public/bsp/sap/system/logoff.htm` ) ) ). |
| 116 | +``` |
| 117 | + |
| 118 | +Use this when you want, e.g., the SAP standard BSP logoff confirmation page rather than wherever your customized ICF logoff redirects. |
| 119 | + |
| 120 | +> Constraint: same origin only. The JS rejects cross-origin redirects. |
| 121 | +
|
| 122 | +### Lever 2 — Customize what `/sap/public/bc/icf/logoff` does (SICF) |
| 123 | + |
| 124 | +Default behavior of this endpoint is system-level customizing. Common patterns: |
| 125 | + |
| 126 | +| What you want | SICF setup | |
| 127 | +|---|---| |
| 128 | +| Show SAP's standard "you have logged off" page | leave default (ships out of the box) | |
| 129 | +| Redirect to the FLP login | Service → Error Pages → Logoff Page → Redirect to URL = `…/sap/bc/ui2/flp` | |
| 130 | +| Redirect to a custom company logoff page | Same path, set Redirect to URL = your page | |
| 131 | +| Land on a fresh login dialog (force re-prompt) | Combine with disabling SSO for that path | |
| 132 | + |
| 133 | +This is a **Basis / system-administrator** task. abap2UI5 cannot influence it from the app. If your symptom is "I logged out and came back into the launchpad," this lever is almost certainly the cause. |
| 134 | + |
| 135 | +### Lever 3 — Run inside the FLP shell when you want shell logout |
| 136 | + |
| 137 | +If your goal is to always go through `Container.logout()` (the cleanest user experience), run the app **as an FLP tile**, not via a BSP URL. From a BSP URL there is no shell to log out from — that's not a bug, that's by design of how FLP works. |
| 138 | + |
| 139 | +### Lever 4 — Replace the JS entirely |
| 140 | + |
| 141 | +If none of the above fits, edit the `_evSystemLogout` / `SYSTEM_LOGOUT` handler in the file matching your runtime (table in §5) and add whatever sequence you need: extra `fetch()` calls, custom IdP single-logout, post-logoff messages, etc. Keep the default branch intact so the existing demos keep working. |
| 142 | + |
| 143 | +--- |
| 144 | + |
| 145 | +## 7. The SSO truth |
| 146 | + |
| 147 | +In any SAP landscape with single sign-on, "logoff" from a single SAP app is inherently **soft**: |
| 148 | + |
| 149 | +- Killing layers A + B + C in the browser deletes the SAP-side session |
| 150 | +- The IdP session (Active Directory, SAML provider, OIDC, certificate-based auth) is **untouched** |
| 151 | +- The next request to any protected SAP URL re-authenticates silently |
| 152 | +- The user experience is "I clicked logoff, I came right back in" |
| 153 | + |
| 154 | +This is not abap2UI5 behavior, it's SAP NetWeaver behavior. Real "log out everywhere" requires either: |
| 155 | + |
| 156 | +1. **IdP-initiated single logout (SLO)** — your IdP's logout endpoint, not SAP's |
| 157 | +2. **Closing the browser tab/window** so the IdP session cookies are lost |
| 158 | +3. **A server-side logout-everywhere flow** that you build per landscape |
| 159 | + |
| 160 | +If users complain "logoff doesn't really log me off," explain this constraint. The fix is at the IdP, not in the app. |
| 161 | + |
| 162 | +--- |
| 163 | + |
| 164 | +## 8. Decision tree |
| 165 | + |
| 166 | +``` |
| 167 | +User clicks Logout |
| 168 | +│ |
| 169 | +├─ App is in FLP shell? ───YES──▶ Container.logout() [layer A killed] |
| 170 | +│ FLP-managed redirect afterward |
| 171 | +│ (typically to a logoff page) |
| 172 | +│ |
| 173 | +└─ NO (ICF handler or BSP) |
| 174 | + │ |
| 175 | + ├─ App is on /sap/bc/bsp/…? ───YES──▶ hidden iframe to ?sap-sessioncmd=logoff |
| 176 | + │ [layer C killed] |
| 177 | + │ THEN ↓ |
| 178 | + │ |
| 179 | + └─ window.location.href = logoutUrl (default /sap/public/bc/icf/logoff) |
| 180 | + [layer B killed by ICF logoff service] |
| 181 | + afterward: SICF redirect target |
| 182 | + (your system administrator decides) |
| 183 | +``` |
| 184 | + |
| 185 | +--- |
| 186 | + |
| 187 | +## 9. Common scenarios and what to expect |
| 188 | + |
| 189 | +| Scenario | A | B | C | Where you land | |
| 190 | +|---|---|---|---|---| |
| 191 | +| Started from FLP, click Logout | ✅ | depends on FLP wiring | n/a | FLP "you have signed out" page | |
| 192 | +| Started from ICF handler URL, click Logout | n/a | ✅ | n/a | Whatever `/sap/public/bc/icf/logoff` redirects to | |
| 193 | +| Started from BSP URL, click Logout *(after fix)* | n/a | ✅ | ✅ | Whatever `/sap/public/bc/icf/logoff` redirects to — could be FLP if your SICF says so | |
| 194 | +| Started from BSP URL, click Logout *(before fix)* | n/a | ✅ | ❌ context lingered in `SM04` | Same as above, but BSP context lived on | |
| 195 | +| Any of the above, on an SSO-enabled system | as above | as above | as above | If the redirect target is itself protected, SSO re-authenticates — looks like "didn't log out" | |
| 196 | + |
| 197 | +--- |
| 198 | + |
| 199 | +## 10. Recommended config matrix |
| 200 | + |
| 201 | +| You want… | Lever 1 (`args[1]`) | Lever 2 (SICF) | Lever 3 (start in FLP) | Lever 4 (edit JS) | |
| 202 | +|---|---|---|---|---| |
| 203 | +| Standard "you have logged off" page after logout | — | leave default | — | — | |
| 204 | +| Redirect to your company logoff page | optionally `args[1]` to that page | OR set in SICF | — | — | |
| 205 | +| Always go through FLP shell logout | — | — | ✅ run as FLP tile | — | |
| 206 | +| Hard logout including the IdP | — | combine with IdP SLO | — | possibly extra calls | |
| 207 | +| Replace mechanism entirely (e.g. mobile app) | — | — | — | ✅ | |
| 208 | + |
| 209 | +--- |
| 210 | + |
| 211 | +## 11. Glossary |
| 212 | + |
| 213 | +- **FLP / Fiori Launchpad** — the SAP shell UI that hosts Fiori tiles; provides `sap.ushell.Container`. |
| 214 | +- **ICF** — Internet Communication Framework, the AS ABAP HTTP server (transactions `SICF`, `SMICM`). |
| 215 | +- **BSP** — Business Server Pages, an older SAP web technology that runs **stateful** by default and has its own session layer on top of ICF. |
| 216 | +- **SSO / IdP** — Single Sign-On / Identity Provider; the external auth system (AD, SAML, OIDC, etc.). Logging out of SAP locally does **not** log you out of the IdP. |
| 217 | +- **`sap-contextid`** — the BSP runtime's stateful-session cookie, scoped to `/sap/bc/bsp/sap/<app>/`. |
| 218 | +- **`sap-sessioncmd=logoff`** — URL parameter that instructs the BSP runtime to call `server->session->terminate( )`. |
0 commit comments