8000 Apply browser security headers on SP-initiated SAML endpoints by edewit · Pull Request #54159 · keycloak/keycloak · GitHub
[go: up one dir, main page]

Skip to content

Apply browser security headers on SP-initiated SAML endpoints - #54159

Merged
rmartinc merged 6 commits into
keycloak:mainfrom
edewit:fix-54122-saml-security-headers
Oct 30, 2026
Merged

rmartinc merged 6 commits into
keycloak:mainfrom
edewit:fix-54122-saml-security-headers

Conversation

@edewit
@edewit edewit commented Oct 20, 2026 •
Copy link
Copy Markdown
Contributor

Return Response synchronously from /protocol/saml GET/POST (including
artifact resolution) so KeycloakSecurityHeadersFilter can apply realm
browser security headers. Previously @suspended AsyncResponse closed the
session before the filter ran, omitting CSP and X-Frame-Options.

Closes #54122

Copilot AI balanced review requested due to automatic review settings October 20, 2026 10:35
@edewit
edewit requested a review from a team as a code owner October 20, 2026 10:35
Return Response synchronously from /protocol/saml GET/POST (including
artifact resolution) so KeycloakSecurityHeadersFilter can apply realm
browser security headers. Previously @suspended AsyncResponse closed the
session before the filter ran, omitting CSP and X-Frame-Options.

Closes keycloak#54122

Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com>
@edewit
edewit force-pushed the fix-54122-saml-security-headers branch from f5df67f to 87c60c0 Compare October 20, 2026 10:37
Copilot AI left a comment
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Artifact resolution loses HTTP-worker isolation and lacks security-header regression coverage.

2 open issues
What changed in this PR

Addresses #54122 by returning SAML responses synchronously so Keycloak’s security-header filter can apply realm browser protections.

Changes:

  • Converts GET/POST and artifact resolution to synchronous response handling.
  • Adds security-header tests and Redirect-binding test support.
File Description
tests/​base/​src/​test/​java/​org/​keycloak/​tests/​saml/​SamlSloSessionHijackTest.java Adapts to the generalized request type.
tests/​base/​src/​test/​java/​org/​keycloak/​tests/​saml/​SamlSecurityHeadersTest.java Tests POST and Redirect security headers.
tests/​base/​src/​test/​java/​org/​keycloak/​tests/​saml/​SamlClient.java Adds Redirect-binding request support.
services/​src/​main/​java/​org/​keycloak/​protocol/​saml/​SamlService.java Replaces asynchronous SAML response handling.

Review effort: Balanced

Copilot AI balanced review requested due to automatic review settings October 20, 2026 10:40
Copilot AI left a comment
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The rewritten artifact-resolution lifecycle lacks regression coverage verifying security headers.

3 open issues

Review effort: Balanced

@lhanusov lhanusov left a comment
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@edewit thanks for this fix, I've added one comment to address, also, can you please check those created by Copilot? thanks 👍

Restore async artifact SOAP I/O so a slow SP does not block shared HTTP
workers, while still applying realm browser security headers before
AsyncResponse resume for SP-initiated SAML endpoints.

Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com>
Copilot AI balanced review requested due to automatic review settings October 21, 2026 14:24
Copilot AI left a comment
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Header handling bypasses logout-specific CSP options and leaves rollback-generated artifact error pages unprotected.

4 open issues
1 resolved since last review

Review effort: Balanced

@edewit
edewit requested a review from lhanusov October 21, 2026 14:58
Route async SAML header application through SecurityHeadersProvider so
allowFrameSrc from FrontChannelLogoutHandler is not overwritten by raw
realm defaults.

Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com>
Copilot AI balanced review requested due to automatic review settings October 21, 2026 15:20
Copilot AI left a comment
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

The security-sensitive HTML error-response path still needs GET and POST regression coverage.

3 open issues
1 previously missed issue

In code that hasn't changed since last review

Medium severity Add GET and POST tests for security headers on SAML parameter errors

services/​src/​main/​java/​org/​keycloak/​protocol/​saml/​SamlService.java:803

Add GET and POST regression tests that omit all SAML parameters and assert status 400 plus the realm's configured security headers on the HTML error page. Both new tests send valid AuthnRequests, leaving this separately decorated early-error path untested even though error pages are explicitly part of #54122.

1 resolved since last review

Review effort: Balanced

@lhanusov
Copy link
Copy Markdown
Contributor

@edewit Hi Erik, the artifact worker pool and logout CSP handling look good now. There’s still one gap: if the artifact transaction fails to commit, AsyncResponseTransaction.rollback() replaces the response with a fresh 500 error page, losing the security headers applied here.

Could we apply the headers after the final response is selected and add a regression test for that rollback path? The current tests only send SAMLRequest, so they don’t cover artifact resolution.

Thank you.

@lhanusov lhanusov left a comment
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please, check my comment

…e final response

Rollback-generated artifact error pages were missing realm browser security
headers because they replaced an already-decorated success response. Apply
headers on commit/rollback after the final response is chosen, and cover the
artifact resolution rollback path in SamlSecurityHeadersTest.

Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com>
Copilot AI balanced review requested due to automatic review settings October 30, 2026 07:44
@edewit
edewit commented Oct 30, 2026
Copy link
Copy Markdown
Contributor Author

@lhanusov Thanks — addressed in 387b52b.

AsyncResponseTransaction now applies browser security headers to the response that is actually resumed after commit/rollback selects it, so a rollback-generated 500 still gets the realm headers. Added testBrowserSecurityHeadersOnArtifactResolutionRollback covering the artifact path through that transaction.

Copilot AI left a comment
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

No active review issues remain for the SAML security-header changes.

No open issues 🎉

3 resolved since last review

Review effort: Balanced

Mutating Response.getHeaders() is not propagated by Quarkus REST on
AsyncResponse resume. Rebuild the Response via Response.fromResponse
so realm security headers are present on the wire.

Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com>
Copilot AI balanced review requested due to automatic review settings October 30, 2026 08:05
Copilot AI left a comment
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Generated security headers append to existing CSP values, causing browsers to enforce intersecting policies that may block resources or frames permitted by the realm policy.

1 open issue

Review effort: Balanced

…onses

Resolve SamlClient conflict by keeping both unsigned-response helpers from
main and artifact-request helpers from this branch. Clear copied header
values before applying realm browser security headers so CSP is replaced
rather than duplicated.

Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com>
Copilot AI balanced review requested due to automatic review settings October 30, 2026 10:46
Copilot AI left a comment
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

No active review issues were identified for the SAML security-header changes.

No open issues 🎉

1 resolved since last review

Review effort: Balanced

@lhanusov lhanusov left a comment
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM @edewit thank you for the fix

@rmartinc rmartinc left a comment
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @edewit and @lhanusov!

@rmartinc
rmartinc merged commit 42a3b96 into keycloak:main Oct 30, 2026
97 checks passed
ruchikajha95 pushed a commit to ruchikajha95/keycloak that referenced this pull request Nov 3, 2026
…ak#54159)

* Apply browser security headers on SP-initiated SAML endpoints

Return Response synchronously from /protocol/saml GET/POST (including
artifact resolution) so KeycloakSecurityHeadersFilter can apply realm
browser security headers. Previously @suspended AsyncResponse closed the
session before the filter ran, omitting CSP and X-Frame-Options.

Closes keycloak#54122

Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com>

* Keep SAML artifact resolution on saml-artifact-pool

Restore async artifact SOAP I/O so a slow SP does not block shared HTTP
workers, while still applying realm browser security headers before
AsyncResponse resume for SP-initiated SAML endpoints.

Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com>

* Preserve front-channel logout CSP when applying SAML security headers

Route async SAML header application through SecurityHeadersProvider so
allowFrameSrc from FrontChannelLogoutHandler is not overwritten by raw
realm defaults.

Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com>

* Apply SAML security headers after AsyncResponseTransaction selects the final response

Rollback-generated artifact error pages were missing realm browser security
headers because they replaced an already-decorated success response. Apply
headers on commit/rollback after the final response is chosen, and cover the
artifact resolution rollback path in SamlSecurityHeadersTest.

Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com>

* Rebuild SAML responses when applying browser security headers

Mutating Response.getHeaders() is not propagated by Quarkus REST on
AsyncResponse resume. Rebuild the Response via Response.fromResponse
so realm security headers are present on the wire.

Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com>

---------

Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com>
mposolda pushed a commit that referenced this pull request Nov 12, 2026
#55043)

Closes #54122


Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com>
(cherry picked from commit 42a3b96)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

SAML endpoint /realms/{realm}/protocol/saml responses are served without browser security headers (clickjacking, no CSP)

4 participants

0