Troubleshooting Ignition Perspective Logout Redirect Issues
The system.perspective.logout function in Inductive Automation's Ignition Perspective module is the standard mechanism for terminating a user session. A common field problem, tracked internally as FEATURE-12767 / FEATURE-14002, is that when a logout action is chained with a navigation action, the second navigation's browser redirect "wins" the race against the logout handshake, so the SAML/IdP session cookie is never cleared and the next launch of the project silently signs the previous user back in. This reference explains the underlying redirect flow, why the race exists, the workarounds available in current 8.1.x code, and how to verify a proper logout.
1. Problem Description
Symptom observed on Perspective Sessions (project session bound to a browser tab):
- User clicks a button wired to
onClick→ Logout + Navigate. - Browser URL changes to the configured target, but the Ignition gateway session, the IdP session, or both remain active.
- Subsequent access to the project URL bypasses the credential prompt and drops the user directly into the running project.
- If the navigation action is removed and only the Logout action remains, the credential prompt reappears on next launch — confirming the navigation step is what suppresses the IdP challenge.
2. Root Cause: Redirect Race Condition
The Perspective Logout component action (or the equivalent system.perspective.logout() script function) is implemented as a client-side window.location redirect to a gateway-managed logout route. The route is responsible for:
- Invalidating the Perspective session token on the gateway.
- Checking the project-level IdP configuration for a Single Logout (SLO) callback.
- If an IdP logout callback is configured, redirecting the browser to the IdP's logout endpoint (e.g. the SAML SLO URL, the OIDC end_session_endpoint, or the Azure AD logout URL).
- On completion, returning the browser to the originating project/page URL.
A subsequent Navigate action or system.perspective.navigate(url="...") also issues a window.location assignment. Because both events fire from the same onClick handler, the JavaScript event loop schedules two competing location assignments. The browser honors whichever location change resolves last, which in practice is the user's target URL — bypassing steps 2 and 3 entirely. The gateway never sees a chance to revoke the IdP token, so the cookie set by the IdP (e.g. __Host-azure-auth-session, JSESSIONID, Okta session cookie) is still valid when the user next visits the project.
For reference, the documented contract for the logout call is:
system.perspective.logout() // Triggers a logout event; requires IdP set in Project properties
Source: system.perspective.logout — Ignition 8.1 User Manual.
3. Affected Versions and Configurations
| Ignition Version | Affected Behavior | Notes |
|---|---|---|
| 8.0.x ≤ 8.0.17 | Logout race present; SLO callback not supported | IdP must be re-entered manually on next session |
| 8.1.0 – 8.1.27 | Logout race present; SAML SLO tracked under internal ticket 12767 | Ignition IdP always has internal logout callback, but third-party IdP SLO is not yet honored |
| 8.1.28+ | SLO configuration UI shipped (post-14002 work) | Verify behavior against the release notes for your exact 8.1.x build |
| Perspective Workstation, Browser, Mobile | All affected | Race is browser-engine independent (Chromium, WebKit, WebView) |
4. Solution A — Recommended Workaround (Pre-SLO)
Until the SLO enhancement tracked under FEATURE-12767 ships in a stable build you are running, the cleanest workaround is to remove the navigation step from the button entirely and rely on the gateway's built-in post-logout redirect behavior. Configure the destination directly on the IdP or the project's login settings.
4.1 Configure the post-logout destination
- Open the Perspective project in the Designer.
- Navigate to Project → Properties → Perspective → Identity Provider.
- If using the bundled Ignition IdP, the logout callback is wired automatically; you only need to set the default landing page on the IdP itself.
- If using an external IdP (Azure AD, Okta, ADFS, Keycloak, Auth0, etc.), configure the IdP's post-logout redirect URI to point to the desired landing URL — not to the project URL.
4.2 Simplify the button to a single action
Replace the two-step onClick handler with a single Logout action, or call system.perspective.logout() from a single Script action. Do not chain a Navigate after it.
// Button onClick → Script
system.perspective.logout()
// Do NOT call system.perspective.navigate() after this line.
The gateway will then perform the full handshake and return the browser to a URL where the credential prompt is required. See the Login and Logout Actions video on Inductive University for the canonical binding pattern.
5. Solution B — Explicit SLO (SAML / OIDC)
For deployments using SAML 2.0 or OIDC, the long-term fix is the Single Logout callback tracked in FEATURE-12767. When shipped, it adds a configurable SLO URL to the Perspective project IdP settings so that Ignition can notify the IdP when the user has logged out. Configuration steps once available in your build:
- In the Designer, open Project → Properties → Perspective → Identity Provider → SAML (or OIDC, depending on your auth profile).
- Set the Single Logout Service URL (SAML) or End Session Endpoint (OIDC) provided by the IdP.
- Whitelist the Ignition gateway callback in the IdP's allowed redirect URIs (typical pattern:
https://<gateway>:<webport>/auth/logout/callback). - Save and commit the project. The logout flow will now clear the IdP session, not just the local Perspective session.
For background on the recommended identity-security posture in Ignition, review the Changing Your Perspective on Security webinar, which covers SLO, token lifetimes, and gateway hardening.
6. Solution C — Azure AD / MSAL Edge Case
Projects federated through Azure AD via the Microsoft Authentication Library (MSAL) can exhibit a related failure where no logout request is observed in Fiddler or browser dev tools. The reference issue and the diagnostic procedure (open Fiddler, click login, enter credentials, then clear traces and click logout) is documented in AzureAD/microsoft-authentication-library-for-js #127. Apply the same principle to a Perspective deployment:
- Open the browser's DevTools → Network tab with "Preserve log" enabled.
- Click the logout button.
- Confirm that a request to
/auth/logoutis issued before any request to your target URL. - If the navigation request fires first, the navigation is winning the race and steps 1–2 of the gateway logout handshake are skipped.
7. Verification
After applying Solution A or B, validate the logout end-to-end:
- Sign in to the Perspective project from a private/incognito window.
- Open Diagnostics → Sessions in the Gateway Web Interface and note the active session count.
- Click the logout button.
- Confirm in DevTools that
/auth/logoutreturns 302/200, and that any IdP logout endpoint is contacted. - Refresh Diagnostics → Sessions; the session row for the test user must be removed within a few seconds.
- Close the browser, reopen, and navigate to the project URL. The credential prompt must appear — if the previous user is silently re-authenticated, the race is still present.
session.props.auth.user expression function in a Perspective binding should resolve to an unauthenticated (empty) value immediately after the logout redirect completes. A quick way to test this is to bind a label to {session.props.auth.user} on a launch page — the label must clear.8. Troubleshooting Matrix
| Observed Symptom | Likely Cause | Corrective Action |
|---|---|---|
| User silently re-authenticated on next visit | Navigate action overriding logout redirect | Remove Navigate; let gateway drive redirect |
| Login prompt appears but IdP SSO still active | IdP session cookie not cleared (no SLO) | Wait for FEATURE-12767; configure SLO URL when available |
| No /auth/logout request in network trace | JS error before logout, or navigation preempts it | Wrap handler in try/catch; check console for errors |
| IdP returns error on callback | Callback URL not whitelisted on IdP | Add https://<gw>/auth/logout/callback to IdP allowed redirects |
| Mobile session (Perspective App) does not honor logout | Cached WebView credentials | Clear app cache, force-stop, re-launch |
User logs out but designer session.props.auth.user still shows identity |
Stale session in another tab | Close all Perspective tabs; only one tab should drive logout |
9. Best Practices for Logout UI Design
- Use a single Logout component action; never chain a Navigate.
- If the project must land on a specific URL after logout, configure that URL on the IdP (SLO post-logout redirect), not on the button.
- Place the logout button in a shell view that lives outside the authenticated route tree, so the user does not need a navigation event to leave restricted content.
- For kiosk / Workstation deployments, consider a periodic session-expire binding that calls
system.perspective.logout()whendateDiff(now, session.props.auth.lastActivity) > configuredTimeout. - For compliance-sensitive environments, enable gateway audit logging on the
auth/logoutroute and export to a SIEM.
10. Security Considerations
A logout that does not terminate the IdP session is, in audit terms, a soft logout. The browser cookie persists, the IdP SSO assertion remains valid, and the next browser launch on the same machine is treated as a continuing session. For environments subject to FDA 21 CFR Part 11, IEC 62443, or similar regulations, this is a finding-class issue. Treat it as such by:
- Documenting the SLO configuration in the system's security context.
- Validating SLO behavior in the FAT/SAT scripts, not just the SAT.
- Disabling browser "remember me" / persistent session cookies at the IdP where policy permits.
The Changing Your Perspective on Security webinar covers the full posture checklist; cross-reference it for your specific threat model.
11. FAQ
Why does my logout button leave the previous user signed in?
The Navigate action chained after Logout in the same onClick handler is a browser window.location race; the navigation request is dispatched before the gateway logout handshake completes, so neither the Perspective session nor the IdP session is invalidated. Use only the Logout action, or call system.perspective.logout() alone, and configure the post-logout landing URL on the IdP instead.
Does the built-in Ignition Identity Provider support Single Logout?
The Ignition IdP is preconfigured with a logout callback under the hood, so projects using the bundled IdP perform a clean logout through the gateway route. The SLO URL that allows Ignition to notify a third-party IdP (Azure AD, Okta, ADFS, etc.) is tracked under FEATURE-12767 and is exposed in newer 8.1.x releases; configure it under Project → Properties → Perspective → Identity Provider.
How do I confirm the logout actually ran in the browser?
Open DevTools → Network with "Preserve log" enabled, click logout, and verify a 200/302 response from /auth/logout followed by a redirect to the IdP's logout endpoint (when configured). Also confirm in the Gateway Web Interface under Diagnostics → Sessions that the user row disappears within a few seconds.
What is the right script to call from a button for logout?
Use a single Script action with system.perspective.logout() and no other navigation or system.perspective.navigate() call. The function requires an Identity Provider to be configured in the Perspective Project properties; otherwise it returns an error and no redirect is issued.
Is the mobile Perspective app affected by the same redirect race?
Yes. The WebView in the mobile Perspective app receives the same window.location assignments as a desktop browser, so a chained Navigate+Logout will exhibit identical behavior. Apply the same single-action fix, and clear the app cache during commissioning to remove any cached SSO cookies that may have been stored before the fix was deployed.