Support HttpOnly session cookie in XUI#1036
Conversation
Allow the XUI to work correctly when the OpenAM session cookie (iPlanetDirectoryPro) is issued with the HttpOnly flag, where the token cannot be read from JavaScript via document.cookie. Server - ServerInfoResource: expose the new "cookieHttpOnly" flag in /json/serverinfo/* so the XUI can detect the mode at runtime. XUI - SessionToken: detect HttpOnly mode via Configuration.globalData.cookieHttpOnly. When enabled, keep the token in memory for the page lifetime instead of reading/writing the cookie, return an HTTP_ONLY_SESSION_TOKEN sentinel from get(), and add isHttpOnly()/isResolvable() helpers. set()/remove() become no-ops on the cookie since it is managed server-side. - SessionService: omit the tokenId query param for getSessionInfo/logout when the token is not client-readable, so the server resolves the session from the automatically-sent HttpOnly cookie; suppress expected 400/401 for the no-token case. - AuthNService: only send sessionUpgradeSSOTokenId when the token is resolvable. - SiteConfigurationService: tolerate a missing/invalid session in checkForDifferences() and continue rendering instead of stalling. Tests / CI - e2e/xui/xui-httponly.spec.mjs: mode-agnostic Playwright spec that asserts the cookie HttpOnly attribute, JS visibility, login/idFromSession detection and logout match the server mode. - build.yml: run the UI smoke tests in both modes — default (HttpOnly disabled) and after restarting the IDP with -Dcom.sun.identity.cookie.httponly=true (HttpOnly enabled). Docs - dev-guide: document the new cookieHttpOnly field in the serverinfo example.
The HttpOnly spec waited for "#loginButton", which does not exist in this XUI build, so the login click hung until the global test timeout. - Match the submit button by type, like the working SAML spec, and keep the id as a fallback: "#loginButton, input[type=submit], button[type=submit]". - Click the first visible match to avoid a strict-mode violation when several elements match.
route when waiting for the session to end.
Stabilize the XUI HttpOnly Playwright spec so it passes against the real
XUI build with the session cookie both with and without the HttpOnly flag.
- Login: match the submit button by type with the id as a fallback
("#loginButton, input[type=submit], button[type=submit]") and click the
first visible match, since "#loginButton" is absent in this build.
- Logout: XUI redirects to "#loggedOut/" (not "#login/"), so accept either
route when waiting for the session to end.
- Logout assertion: verify the session is invalidated server-side via
idFromSession instead of checking the browser cookie. In HttpOnly mode JS
cannot clear the cookie and the REST logout may not emit a Set-Cookie, so a
stale-but-dead cookie can linger; server-side invalidation holds in both modes.
|
I suggest this commit 3913a59 can be reverted for now. |
Reverts the workaround from 3913a59 that disabled the XUI entirely when the session cookie is HttpOnly. The XUI now supports HttpOnly session cookies, so it must stay enabled in that mode.
Add an e2e check that an admin remains authenticated in the console after a full browser page reload (the reload drops any in-memory token, so the session must be re-detected from the auto-sent cookie). Extract shared loginViaXui()/idFromSession() helpers and update the PR description.
|
Nice work on the HttpOnly support - login/reload/logout look solid. One thing I wanted to check with you: The way I read it, the step-up redirect is a fresh page load, so If that's right, would it make sense to fall back to the session cookie as the upgrade target in the REST authenticate flow when |
…arget When the session cookie is configured as HttpOnly, the XUI cannot read the tokenId from JavaScript and therefore cannot send the sessionUpgradeSSOTokenId query parameter on an agent-driven session upgrade (step-up), which is performed via a fresh page load with an empty in-memory token. Server-side that parameter was the only source for the session to upgrade, so the request fell through to a brand-new login: the existing session was orphaned, its properties/sessionHandle were lost, and composite-advice step-up could loop. RestAuthenticationHandler now resolves the upgrade target from the auto-sent HttpOnly session cookie when sessionUpgradeSSOTokenId is absent. The fallback is limited to the HttpOnly deployment mode (CookieUtils.isCookieHttpOnly()), so the behaviour of all other token-readable deployments is unchanged. Also clean up leftover merge-conflict markers in the file's license header. Changes: - RestAuthenticationHandler: add resolveSessionUpgradeTarget() and apply it in the authenticate flow before resolving the auth index. - RestAuthenticationHandlerTest: cover the cookie fallback in HttpOnly mode and the unchanged behaviour when a token is supplied / HttpOnly is off. - e2e/xui/xui-httponly.spec.mjs: add a step-up scenario asserting the existing session is recognised as the upgrade target (no fresh authId/callbacks) in HttpOnly mode; consolidated from the separate session-upgrade spec.
Summary
Make the OpenAM XUI (login / admin console,
openam-ui-ria) work correctly whenthe session cookie (e.g.
iPlanetDirectoryPro) is issued with theHttpOnlyflag.
With
HttpOnly=truethe browser does not expose the cookie to JavaScript(
document.cookie), so the XUI could no longer read the session token. Becausethe XUI relied on reading the token client‑side (
SessionToken.get()) for sessiondetection, upgrade, realm‑change checks and logout, it treated authenticated users
as logged out. This PR removes that hard dependency: the token is kept in memory
for the page lifetime, and where a token is not client‑readable the server resolves
the session from the automatically‑sent
HttpOnlycookie instead.The change is backwards compatible — when
HttpOnlyis disabled the behaviour isunchanged.
Motivation
HttpOnlysession cookies are a baseline security hardening measure (mitigatestoken theft via XSS). Previously enabling
com.sun.identity.cookie.httponly=truebroke the XUI, forcing operators to choose between the XUI and this protection.
Changes
Server
ServerInfoResource— expose a newcookieHttpOnlyflag in/json/serverinfo/*so the XUI can detect the mode at runtime.XUI (
openam-ui-ria)SessionToken.jsmHttpOnlymode viaConfiguration.globalData.cookieHttpOnly.HttpOnlymode keep the token in memory for the page lifetime instead ofreading/writing the cookie;
get()returns the in‑memory token or anHTTP_ONLY_SESSION_TOKENsentinel so callers know a session may exist.set()/remove()become no‑ops on the cookie (it is managed server‑side).isHttpOnly()andisResolvable(token).SessionService.jsm— forgetSessionInfo/logout, omit thetokenIdquery parameter when the token is not client‑readable so the server resolves the
session from the request cookie; suppress the expected
400/401for theno‑token case.
AuthNService.js— only sendsessionUpgradeSSOTokenIdwhen the token isresolvable.
SiteConfigurationService.js— tolerate a missing/invalid session incheckForDifferences()and continue rendering instead of stalling.Tests / CI
e2e/xui/xui-httponly.spec.mjs— mode‑agnostic Playwright spec. It readsthe server mode from
/json/serverinfo/*and asserts that the cookieHttpOnlyattribute,
document.cookievisibility, login +idFromSessiondetection, andserver‑side logout invalidation all match that mode.
.github/workflows/build.yml— run the UI smoke tests in both modes:the existing default run (HttpOnly disabled) and a second run after restarting
the IDP container with
-Dcom.sun.identity.cookie.httponly=true(HttpOnly enabled).
Docs
dev-guide/chap-client-dev.adoc— document the newcookieHttpOnlyfieldin the
serverinfoexample.How to enable
Set the system property and restart OpenAM (it is read once at startup):
Or via Configuration → Servers and Sites → Server → Advanced:
com.sun.identity.cookie.httponly = true(restart required).Verify:
Testing
Automated (Playwright), runs in both modes:
The spec verifies, for the active mode:
serverinfo.cookieHttpOnlymatches the expected mode.HttpOnlyattribute.document.cookievisibility is the inverse ofHttpOnly.idFromSession(no client‑side cookie read).Manual:
HttpOnly, log in to the XUI.iPlanetDirectoryProshows theHttpOnlyflag;
document.cookiedoes not contain the token.Backwards compatibility
serverinfofield is additive.Affected modules
openam-core-restopenam-ui/openam-ui-riaopenam-documentatione2e, CI (.github/workflows/build.yml)