Repository navigation
Conversation
tsujiguchitky
left a comment
There was a problem hiding this comment.
LGTM - enabling HttpOnly by default is the right call, and the change is consistent across code, defaults, CI, tests, and docs. Approving.
|
Rebased/merged |
|
Thanks for all the work on this! I have to apologize for coming back with something new. In my earlier review, I didn't find any blockers, but I noticed an issue that I think should be addressed before merging.
Could we have the MCP server read |
6e8f928 to
1700002
Compare
|
@tsujiguchitky Thanks — good catch, confirmed: with HttpOnly on and
I also rebased the branch onto current master (no functional change to the rest of the PR). Re-requesting review. |
tsujiguchitky
left a comment
There was a problem hiding this comment.
LGTM! Thanks for the quick fix — the MCP server now picks up the SSO token from the session cookie under the new HttpOnly default, and the tests cover both auth paths nicely.
maximthomas
left a comment
There was a problem hiding this comment.
praise: The default flip is small, and the one in-repo consumer it adapts is handled carefully.
- The flip is a single expression,
getAsBoolean(Constants.AM_COOKIE_HTTPONLY, true)inopenam-shared/.../CookieUtils.java:68-69, plus the shipped value inserverdefaults.properties. AuthInterceptor.extractSessionToken(openam-mcp-server/.../security/AuthInterceptor.java:152-173) prefers the body token, takes the last non-empty session cookie, and throws anIllegalStateExceptionnaming the cookie. A null token no longer reaches the token cache.
issue (blocking): Under the new default, the js-sdk login UI shipped at /extui never finishes a successful login.
openam-ui/openam-ui-js-sdk/src/lib/Login.tsx:47-49, openam-ui/openam-ui-js-sdk/src/lib/types.ts:43
isSuccessfulAuth() counts a response as success only when it has a string tokenId. RestAuthenticationHandler.java:339 now leaves tokenId out of the body whenever the cookie is HttpOnly and allowTokenInBody is off. A successful login therefore returns {successUrl, realm}, and handleAuthResponse falls through to console.error("Unknown response format"): no redirect, no navigate('/'). The bundle is unpacked into the server WAR at /extui (openam-server-only/pom.xml:111-118), so every new install is affected. The session already travels in the cookie, so the SDK does not need the token.
// Login.tsx
function isSuccessfulAuth(response: unknown): response is SuccessfulAuth {
return typeof response === 'object' && response !== null
&& 'successUrl' in response && typeof response.successUrl === 'string';
}
// types.ts:43
tokenId?: string;issue (blocking): Under the new default, REST and SOAP STS fail every validation that goes through REST authN.
openam-sts/openam-common-sts/src/main/java/org/forgerock/openam/sts/token/AMTokenParserImpl.java:51-56, openam-sts/openam-common-sts/src/main/java/org/forgerock/openam/sts/token/validator/AuthenticationHandlerImpl.java:61, openam-sts/openam-soap-sts/openam-soap-sts-server/src/main/java/org/forgerock/openam/sts/soap/bootstrap/SoapSTSAccessTokenProviderImpl.java:143
getSessionFromAuthNResponse reads the session id only from tokenId in the /json/authenticate body. If the field is missing it throws TokenValidationException(INTERNAL_ERROR, "REST authN response does not contain tokenId string entry…"). On a new install the body no longer carries it, so these all fail:
- REST STS username, OIDC and X.509 token validation;
- SOAP STS agent bootstrap.
They keep failing until an operator sets allowTokenInBody=true or httponly=false. The STS HTTP client's HttpURLConnectionWrapper.ConnectionResult holds only the body, so the cookie is lost before the parser runs. No CI step exercises the STS.
Suggested fix: give the STS the fallback the MCP server got. Carry the last non-empty session Set-Cookie value (cookie name from com.iplanet.am.cookie.name) in ConnectionResult, and use it in AMTokenParserImpl when the body has no string tokenId.
Pin: a unit test in which getSessionFromAuthNResponse gets a {successUrl, realm} body plus a session cookie and returns the cookie value.
issue (non-blocking): Under the new default, a user logged in by self-registration auto-login gets no session cookie.
openam-ui/openam-ui-ria/src/main/js/org/forgerock/openam/ui/user/anonymousProcess/SelfRegistrationView.js:49-52, openam-selfservice/src/main/java/org/forgerock/openam/selfservice/config/flows/AutoLoginStage.java:94, openam-ui/openam-ui-ria/src/main/js/org/forgerock/openam/ui/user/login/tokens/SessionToken.jsm:104-110
AutoLoginStage returns the new session only as additions.tokenId and sets no cookie. In HttpOnly mode SessionToken.set() keeps that value in page memory instead of writing the cookie. RESTLoginView.handleExistingSession then sends the user to the goto URL with window.location.href, and on that page, or on the next reload, the user is logged out. The registration response also puts the session id in front of JavaScript, which HttpOnly is meant to prevent. Not run: this needs a browser against a realm with self-registration and auto-login enabled. With that confirmed, it would be blocking.
Suggested fix: when CookieUtils.isCookieHttpOnly(), have the registration response set the session cookie the way /json/authenticate does, and leave tokenId out of the additions.
issue (non-blocking): The two HttpOnly readers this PR changes disagree on any value other than true or false.
openam-federation/openam-idpdiscovery/src/main/java/com/sun/identity/saml2/idpdiscovery/CookieUtils.java:66-67, openam-shared/src/main/java/com/sun/identity/shared/encode/CookieUtils.java:68-69
The IDP discovery reader treats everything except false as on. The shared reader uses Boolean.parseBoolean, so everything except true is off. The server WAR maps the IDP discovery servlets (openam-server-only web.xml:479-491), so both readers see the same value in one JVM. With -Dcom.sun.identity.cookie.httponly= (or yes, or 1), _saml_idp is HttpOnly and iPlanetDirectoryPro is not. The console and ssoadm accept only true/false, so only -D values or hand-edited files reach this.
// openam-shared CookieUtils.java:68 — same semantics as idpdiscovery: only "false" turns it off
static boolean cookieHttpOnly = !"false".equalsIgnoreCase(
StringUtils.trimToEmpty(SystemPropertiesManager.get(Constants.AM_COOKIE_HTTPONLY)));issue (non-blocking): The MCP server's cookie fallback returns the URL-encoded cookie value when cookie encoding is on.
openam-mcp-server/src/main/java/org/openidentityplatform/openam/mcp/server/security/AuthInterceptor.java:158-166
With com.iplanet.am.cookie.encode=true and com.iplanet.am.cookie.c66Encode=false, the session id contains =@#. The cookie then carries %3D%40%23, and SessionResource reads the token header without decoding it. Session validation fails, and the retry loop ends in IllegalStateException. With the default c66Encode=true the id survives encoding unchanged, so default installs are not affected. A raw session id never contains %, so decoding only values that contain it is safe.
String value = pair.substring(eq + 1).trim();
if (value.indexOf('%') >= 0) {
value = URLDecoder.decode(value, StandardCharsets.UTF_8);
}suggestion (non-blocking): extractSessionToken_prefersTokenIdInBody cannot fail against a cookie-first implementation.
openam-mcp-server/src/test/java/org/openidentityplatform/openam/mcp/server/security/AuthInterceptorTest.java:393-400
openAMConfig.tokenHeader() is not stubbed, so the mock returns null and no cookie ever matches. A version that reads the cookie first and falls back to the body still returns the body token, so the body precedence described in the PR is not pinned. Stub the name with lenient(): the correct code never reads it, so a strict stub would raise UnnecessaryStubbingException. With that stub, the cookie-first version fails.
// import static org.mockito.Mockito.lenient;
@Test
void extractSessionToken_prefersTokenIdInBody() {
lenient().when(openAMConfig.tokenHeader()).thenReturn("iPlanetDirectoryPro");
ResponseEntity<Map<String, String>> response = ResponseEntity.ok()
.headers(setCookies("iPlanetDirectoryPro=AQIC5wM2LY4Sfczn-cookie-token; Path=/"))
.body(Map.of("tokenId", "AQIC5wM2LY4Sfczn-body-token"));
assertThat(interceptor.extractSessionToken(response)).isEqualTo("AQIC5wM2LY4Sfczn-body-token");
}suggestion (non-blocking): No test pins the "last non-empty cookie wins" rule.
openam-mcp-server/src/test/java/org/openidentityplatform/openam/mcp/server/security/AuthInterceptorTest.java:402-414, openam-mcp-server/src/main/java/org/openidentityplatform/openam/mcp/server/security/AuthInterceptor.java:148-150
Every fixture has at most one non-empty iPlanetDirectoryPro cookie. A version that stops at the first non-empty match passes every test, although the javadoc says the last one wins, and so does the tail -n1 in build.yml.
@Test
void extractSessionToken_lastNonEmptyCookieWins() {
when(openAMConfig.tokenHeader()).thenReturn("iPlanetDirectoryPro");
ResponseEntity<Map<String, String>> response = ResponseEntity.ok()
.headers(setCookies(
"iPlanetDirectoryPro=AQIC5wM2LY4Sfczn-old-token; Path=/",
"iPlanetDirectoryPro=AQIC5wM2LY4Sfczn-new-token; Path=/; HttpOnly",
"iPlanetDirectoryPro=; Expires=Thu, 01-Jan-1970 00:00:10 GMT; Path=/"))
.body(Map.of("successUrl", "/openam/console"));
assertThat(interceptor.extractSessionToken(response)).isEqualTo("AQIC5wM2LY4Sfczn-new-token");
}Pin: this test fails against both a first-match version and a last-match-including-empty version.
suggestion (non-blocking): A failed IDP admin login no longer fails the step where it happens.
.github/workflows/build.yml:185-193
The whole curl -sf … | grep . | tail -n1 pipeline now runs inside bash -c without pipefail, so its status is that of tail, which is always 0. A 401 or an unmatched Set-Cookie leaves ADMIN_TOKEN empty. The user-create call at :199 swallows the error, and the job fails later at "Test demo user Auth", which points at the wrong step.
ADMIN_TOKEN=$(docker exec openam-idp bash -o pipefail -c \1700002 to
225d262
Compare
|
@maximthomas Thanks for the thorough round. All eight points are addressed in 225d262 (branch rebased onto current 1. js-sdk 2. REST/SOAP STS (blocking) — done as you suggested, with one change to where the cookie name comes from:
3. Self-registration auto-login — confirmed in a browser, and it was indeed blocking: on the previous code with HttpOnly on, the user stays on the registration form after "Save". With HttpOnly on, 4. HttpOnly value parsing — both readers now use the same rule: only 5. MCP URL-encoded cookie — values containing 6. 8. CI pipefail — the IDP admin login pipeline runs under The failed |
maximthomas
left a comment
There was a problem hiding this comment.
praise: The follow-up commit fixes every consumer of the new default at the place where it broke.
AMTokenParserImpl.getSessionFromAuthNResponsenow falls back to the last non-empty sessionSet-Cookie, whichHttpURLConnectionWrapperFactoryreads by index. The new@Named(AM_SESSION_COOKIE_NAME)argument is already bound in all three injectors (RestSTSInstanceModule,SoapSTSModule,SoapSTSInstanceModule).- Under HttpOnly,
AutoLoginStage.putSessionInSuccessAdditionssets the session cookie itself and keepstokenIdout of the body.xui-self-registration.spec.mjscovers this in both CI phases. - Both
CookieUtilsclasses now shareisHttpOnlyEnabled. Withbash -o pipefailin the IDP admin-token step, a broken admin login fails that step again.
suggestion (non-blocking): The STS Set-Cookie fallback depends on how a real HttpURLConnection returns headers, and only a mock tests it.
openam-sts/openam-common-sts/src/test/java/org/forgerock/openam/sts/HttpURLConnectionWrapperFactoryTest.java:35-63, openam-sts/openam-common-sts/src/main/java/org/forgerock/openam/sts/HttpURLConnectionWrapperFactory.java:128-141
The test scripts getHeaderFieldKey(i)/getHeaderField(i) on a mock. That leaves the two JDK facts in the comment untested:
- repeated
Set-Cookieheaders come back by index, in wire order; - an HttpOnly one is visible only while no JVM-wide
CookieHandleris installed. With one installed, the value comes back as"".
No CI step runs the REST or SOAP STS, so this test is the only guard on this path. If the code switched to getHeaderFields(), or a fixture or library installed a CookieHandler, AMTokenParserImpl would throw "contains neither a tokenId … nor a non-empty … cookie" and the suite would stay green. The code is correct today: nothing in OpenAM or in the server WAR's jars calls CookieHandler.setDefault.
// imports: com.sun.net.httpserver.HttpServer, java.net.InetAddress, java.net.InetSocketAddress
@Test
public void seesHttpOnlySetCookieOnARealConnectionInWireOrder() throws Exception {
HttpServer server = HttpServer.create(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0), 0);
server.createContext("/openam/json/authenticate", exchange -> {
exchange.getResponseHeaders().add("Set-Cookie", "iPlanetDirectoryPro=AQIC5wM2LY4Sfczn-old-token; Path=/");
exchange.getResponseHeaders().add("Set-Cookie", "iPlanetDirectoryPro=AQIC5wM2LY4Sfczn-new-token; Path=/; HttpOnly");
byte[] body = "{\"successUrl\":\"/openam/console\"}".getBytes(StandardCharsets.UTF_8);
exchange.sendResponseHeaders(HttpURLConnection.HTTP_OK, body.length);
exchange.getResponseBody().write(body);
exchange.close();
});
server.start();
try {
HttpURLConnectionWrapper.ConnectionResult result =
new HttpURLConnectionWrapperFactory(new DefaultHttpURLConnectionFactory())
.httpURLConnectionWrapper(new URL("http://127.0.0.1:" + server.getAddress().getPort()
+ "/openam/json/authenticate"))
.withoutAuditTransactionIdHeader()
.makeInvocation();
assertEquals(result.getSetCookieHeaders(), Arrays.asList(
"iPlanetDirectoryPro=AQIC5wM2LY4Sfczn-old-token; Path=/",
"iPlanetDirectoryPro=AQIC5wM2LY4Sfczn-new-token; Path=/; HttpOnly"));
} finally {
server.stop(0);
}
}Pin: this test fails if the reader switches to getHeaderFields() (wrong order) or if the test JVM has a JVM-wide CookieHandler (empty value). It runs on every JDK in the CI matrix.
note (non-blocking): The PR description is out of date for 225d262:
openam-shared/src/main/java/com/sun/identity/shared/encode/CookieUtils.java:69: the description saysgetAsBoolean(AM_COOKIE_HTTPONLY, true). The code usesisHttpOnlyEnabled, where onlyfalseturns HttpOnly off.openam-sts/openam-common-sts/src/main/java/org/forgerock/openam/sts/token/AMTokenParser.java,.../validator/disp/TokenAuthenticationRequestDispatcher.java,.../HttpURLConnectionWrapper.java: not described — they now passConnectionResult, and the session is read fromSet-Cookie.openam-selfservice/src/main/java/org/forgerock/openam/selfservice/config/flows/AutoLoginStage.java: not described — under HttpOnly it sets the session cookie and leaves outtokenId.openam-ui/openam-ui-js-sdk/src/lib/Login.tsx,types.ts: not described — success now depends onsuccessUrlalone.openam-ui/openam-ui-ria/src/main/js/org/forgerock/openam/ui/user/anonymousProcess/SelfRegistrationView.js: not described.
225d262 to
5957a6b
Compare
|
@maximthomas The real-connection test is in (5957a6b): Verifying the pin by mutation refined one fact:
The The branch was rebased onto current On the description note: the description was updated on 2026-09-28, right after the round-2 reply, and already covers the five items ( |
maximthomas
left a comment
There was a problem hiding this comment.
praise: The STS HttpOnly fallback is now pinned against a real HttpURLConnection, not only a mock.
HttpURLConnectionWrapperFactoryTest.seesHttpOnlySetCookieOnARealConnectionInWireOrder(openam-sts/openam-common-sts/src/test/java/org/forgerock/openam/sts/HttpURLConnectionWrapperFactoryTest.java:75-103) drives the wrapper through an in-JVMcom.sun.net.httpserver.HttpServerand asserts bothSet-Cookielines in wire order, theHttpOnlyone included, so agetHeaderFields()-based reader or a JVM-wideCookieHandlerin the test JVM turns it red.- It also asserts the response body, so the success road through
makeInvocation()is covered along with the headers. - All 11
build-mavenlegs (JDK 11 to 26 on Linux, macOS and Windows) are green at5957a6bc.
tsujiguchitky
left a comment
There was a problem hiding this comment.
LGTM! Thanks for the thorough follow-up — the STS, self-registration, and js-sdk paths now all work with HttpOnly by default, and the new tests pin the behavior nicely.
5957a6b to
406fa4b
Compare
|
Rebased onto current The only conflicts were in the two One consequence of combining with #1146: in idpdiscovery an HttpOnly cookie is written as a hand-built
|
406fa4b to
e3c9175
Compare
|
Rebased onto current Conflicts:
One change outside the conflicts: the header comment of I also checked the code that came in from
|
Switch the default of com.sun.identity.cookie.httponly from false to true so that OpenAM marks its SSO/session cookies HttpOnly out of the box. The XUI already supports this mode (relies on the auto-sent cookie instead of reading the token from document.cookie), so the previous "breaks XUI" rationale no longer applies. Core: - CookieUtils (openam-shared): default to true when the property is unset, via getAsBoolean(AM_COOKIE_HTTPONLY, true); update isCookieHttpOnly() javadoc. - serverdefaults.properties: ship com.sun.identity.cookie.httponly=true and rewrite the stale comment (document the allowTokenInBody opt-in / opt-out). IDP Discovery: - CookieUtils: default HttpOnly to true (null/empty -> on, explicit false -> off). - Configurator.jsp: default the "HTTP-Only Cookie" radio to True. CI / e2e: - build.yml: invert the Playwright phases — test the new HttpOnly=true default first (xui specs), then override to false via setenv.sh and run the full suite (oauth2/saml read tokenId from the response body, suppressed in HttpOnly mode). - saml-test.spec.mjs: fix the now-incorrect "HttpOnly breaks XUI" comment. - openam-commons.mjs: document that getAuthToken needs the token in the body. Tests: - RestAuthenticationHandlerTest: set the token-readable baseline (setCookieHttpOnly(false)) in @BeforeMethod so legacy assertions are independent of the production default and test order. Docs (asciidoc): update default to true and the serverinfo example in chap-securing, chap-deployments, chap-config-ref, chap-client-dev.
With HttpOnly enabled by default, /json/authenticate no longer echoes the tokenId in the response body, so the Docker/e2e steps that scraped it broke. - Extract the admin SSO token from the iPlanetDirectoryPro Set-Cookie header (curl -D - -o /dev/null + sed) instead of jq .tokenId; pick the last non-empty value so a clearing (empty) Set-Cookie cannot win. - Verify successful logins via "successUrl" in the response body (present on every completed authentication, in both HttpOnly and token-readable modes) instead of grepping tokenId — robust against cookie-clearing Set-Cookie. Applies to the IDP demo user, SP, and the multi-server test-openam1/2/3 checks.
With HttpOnly session cookies on by default, /json/authenticate no longer returns tokenId in the body, so the MCP server got a null token on a fresh OpenAM install. AuthInterceptor now takes tokenId from the body when present and otherwise the last non-empty Set-Cookie named like openam.tokenHeader (iPlanetDirectoryPro), failing with a clear error when neither is there. Covers both the username/password and the OAuth path; README notes that allowTokenInBody is not needed.
- js-sdk: treat a response with successUrl as a completed login; the session travels in the HttpOnly cookie, tokenId is optional. - STS: keep the Set-Cookie headers in ConnectionResult and let AMTokenParser fall back to the last non-empty session cookie (named by AM_SESSION_COOKIE_NAME, URL-decoded when encoded) when the authN body has no tokenId; fixes REST STS validation and SOAP STS agent bootstrap. - Self-registration auto-login: with HttpOnly on, set the session cookie server-side and keep tokenId out of the response unless allowTokenInBody is set; XUI only stores a tokenId it received. - Read com.sun.identity.cookie.httponly with one rule in the shared and IDP discovery CookieUtils: only "false" disables it. - MCP server: URL-decode an encoded session cookie; pin body precedence and last-non-empty-cookie-wins with tests. - CI: run the IDP admin login pipeline with pipefail. - e2e: self-registration with auto-login keeps the new user logged in across a reload, in both cookie modes.
e3c9175 to
50b9d25
Compare
Preserve Set-Cookie response headers in wire order and use the configured session cookie when authentication omits tokenId. Keep body precedence, ignore clearing cookies, and decode URL-encoded session values. Cover profile creation through a real local HTTP server, including custom cookie names, repeated headers, legacy responses, and authentication errors.
|
@maximthomas @tsujiguchitky The final review uncovered one more authentication-response consumer: automatic agent-profile creation in
The fix retains The new test exercises the real installer task and HTTP client against a loopback server. Six scenarios failed before the fix. All 48 module tests now pass on JDK 11 and JDK 27, including renamed cookies, body precedence, repeated/clearing cookies, encoded and raw values, and failure cases. A complete agent installation against a deployed server was not run in this round. The branch was checked against freshly fetched |
maximthomas
left a comment
There was a problem hiding this comment.
praise: 056cb21 adapts the last in-repo /json/authenticate reader, agent-profile creation in openam-installtools, with the same rule as the MCP and STS clients.
CreateProfileTask.getSSOToken(CreateProfileTask.java:220-244) uses a non-blank bodytokenIdfirst. Otherwise it takes the last non-empty Set-Cookie named by the serverinfo cookie name, and URL-decodes it only when the value has a%. When neither is present it throws anIllegalStateExceptionnaming the cookie, instead of the opaqueJSONObject["tokenId"] not found.RESTEndpoint.callreads Set-Cookie by index in wire order (RESTEndpoint.java:116-120).RESTResponse.getSetCookieHeaders(:426) keeps the headers out oftoString(), which the existing debug log prints.CreateProfileTaskTestdrives the real task and HTTP client against a loopback server, so the cookie path goes through a realHttpURLConnectionrather than a mock.
tsujiguchitky
left a comment
There was a problem hiding this comment.
Thanks for covering the installer as well!
LGTM. CreateProfileTask now takes the agent admin's session from the configured session cookie when tokenId is absent, using the same rules as MCP and STS (body first, last non-empty cookie, decode only when encoded).
RESTEndpoint keeps the Set-Cookie headers in wire order in a separate field, so toString() (used for the debug log and JSON parsing) still returns only the body and never writes the session cookie to the log.
The end-to-end tests against a local HTTP server cover HttpOnly, renamed-cookie and failure cases nicely.
Summary
Enable HttpOnly session cookies by default and adapt the in-repository authentication clients to receive the session through
Set-Cookiewhen/json/authenticateomitstokenIdfrom its JSON body.New installations and deployments without an explicit value get
com.sun.identity.cookie.httponly=true. Existing installations retain their persisted setting. The XUI already supports HttpOnly cookies through #1036.Changes
Cookie defaults and configuration
CookieUtilsenable HttpOnly unless the configured value isfalse(case-insensitive, surrounding whitespace ignored). Unset, empty, and unrecognized values leave it enabled; both readers have value-table tests.serverdefaults.propertiesshipshttponly=true, and the standalone IdP discovery configurator selects True by default.Authentication consumers
tokenId, otherwise read the last non-empty session cookie. The configuredopenam.tokenHeadersupplies the cookie name, and URL-encoded values are decoded. Missing sessions fail explicitly. The README documents the behavior andOPENAM_TOKEN_HEADERfor renamed cookies.ConnectionResultcarriesSet-Cookieheaders through the authentication dispatchers toAMTokenParserImpl, including SOAP STS agent bootstrap. The parser prefers the body token and otherwise reads the last non-empty cookie named by the existingAM_SESSION_COOKIE_NAMEbinding, decoding encoded values. Headers are read by index to preserve wire order on JDK 11/17; a real loopbackHttpURLConnectiontest covers repeated headers and HttpOnly visibility.openam-installtools):RESTEndpoint.RESTResponseretainsSet-Cookieheaders in wire order.CreateProfileTaskuses the cookie name obtained fromserverinfo, prefers a nonblank body token, and otherwise takes the last non-empty matching cookie, decoding encoded values. Automatic creation of a missing agent profile therefore works without enablingallowTokenInBody. Authentication failures, missing sessions, and malformed cookie encoding stop profile creation./extui): a stringsuccessUrlidentifies completed authentication;SuccessfulAuth.tokenIdis optional because the browser receives the session through the cookie.AutoLoginStagesets the session cookie on the registration response and omitsadditions.tokenIdunlessallowTokenInBodyis enabled. The XUI only stores atokenIdwhen one is returned.CI and browser coverage
serverinfo.cookieHttpOnly=true.tokenIdrun in this second phase.Set-Cookieinstead of the JSON body; the IDP administrator login pipeline usespipefail. Authentication smoke checks usesuccessUrl.tokenIdunder HttpOnly, and session survival after reload in both modes. Existing XUI specs cover login, logout, reload, and step-up.master.Compatibility and operator guidance
/json/authenticateresponses omittokenIdby default. Non-browser integrations should read the sessionSet-Cookie. Integrations that still require the JSON field can setorg.openidentityplatform.openam.httponly.allowTokenInBody=true, which exposes the token to scripts again, or disable HttpOnly withcom.sun.identity.cookie.httponly=false./oauth2/connect/checkSession) reads the session cookie from JavaScript and cannot observe the session while HttpOnly is enabled. This remains a documented limitation.Validation
Latest installer fix,
056cb216c6:CreateProfileTaskTestscenarios failed, including cookie-only authentication, renamed cookies, repeated cookies, URL encoding, and empty body-token fallback.openam-installtoolstests pass on JDK 11 and JDK 27, with no failures, errors, or skips. The tests exercise the realCreateProfileTask.execute()and HTTP client against a loopback HTTP server, asserting the session header sent in the profile-creation request and that failure cases send no such request.git diff --checkpasses. A complete agent installation against a deployed OpenAM server was not run in this round.Earlier validation:
CookieUtilsimplementations,RestAuthenticationHandler, the STS token parser and HTTP wrapper, self-registration, MCP authentication, and both js-sdk login cases passed on the preceding head./extuiagainst a server built from this branch. Self-registration passed in both cookie modes and failed against the earlier implementation with HttpOnly enabled.References