feat(pac4j): session CSRF helpers + constant-time csrfCheck authorizer #39

Merged
mph merged 1 commit from feat/pac4j-csrf-support into main 2026-07-18 06:43:23 +00:00
Owner

Adds three pieces that downstream apps need whenever they use
Pac4jHttpSecurity.secure() with server-rendered HTML + HTMX / forms:

  • ConstantTimeCsrfAuthorizer: subclass of pac4j-core CsrfAuthorizer that
    overrides hashEquals with MessageDigest.isEqual over UTF-8 bytes.
    Closes a real weakness in pac4j-core 6.3.2: its hashEquals compares
    32-bit String.hashCode() values, which is collision-attackable
    (birthday ≈2^16, targeted ≈2^32) and not constant-time. Verified by a
    unit spec that finds a genuine collision for "abc" via random
    enumeration and asserts the subclass rejects it.

  • Pac4jCsrfSupport: bridges request handlers to the session-managed
    pac4jCsrfToken. Provides tokenFor(req) so a Scalatags layout can embed
    the token in / hx-headers, plus two install
    helpers that mutate a Pac4j Config:

    • installNonRotatingMatcher — swaps in a CsrfTokenGeneratorMatcher
      whose generator has setRotateTokens(false). Required for the HTMX
      pattern where the token is rendered once per full page and reused
      across many partial POSTs (default rotation kills the second POST).
    • installConstantTimeCsrfAuthorizer — registers the subclass above
      under the standard csrfCheck name.
  • docs/CSRF_GUIDE.md: end-to-end recipe covering what Pac4j does by
    default, the two rough edges these helpers smooth over (rotation vs
    HTMX; weak hashEquals in pac4j-core 6.3.2), the wiring order, meta-tag

    • hx-headers pattern, and anti-patterns. Cross-linked from
      HTTP_SERVER_GUIDE.md's Pac4jHttpSecurity section.

Verified against http.compile / http.test / http.checkFormat / http.fix
--check on Scala 3.3.7.

Extracted from the FiftyForms Cards BFF where this shape was validated
end-to-end via a runtime IT (Pac4jCsrfSpec — five scenarios) and a live
Playwright smoke on 2026-07-17.

🤖 Generated with Claude Code

Adds three pieces that downstream apps need whenever they use Pac4jHttpSecurity.secure() with server-rendered HTML + HTMX / forms: - ConstantTimeCsrfAuthorizer: subclass of pac4j-core CsrfAuthorizer that overrides hashEquals with MessageDigest.isEqual over UTF-8 bytes. Closes a real weakness in pac4j-core 6.3.2: its hashEquals compares 32-bit String.hashCode() values, which is collision-attackable (birthday ≈2^16, targeted ≈2^32) and not constant-time. Verified by a unit spec that finds a genuine collision for "abc" via random enumeration and asserts the subclass rejects it. - Pac4jCsrfSupport: bridges request handlers to the session-managed pac4jCsrfToken. Provides tokenFor(req) so a Scalatags layout can embed the token in <meta name="csrf-token"> / hx-headers, plus two install helpers that mutate a Pac4j Config: * installNonRotatingMatcher — swaps in a CsrfTokenGeneratorMatcher whose generator has setRotateTokens(false). Required for the HTMX pattern where the token is rendered once per full page and reused across many partial POSTs (default rotation kills the second POST). * installConstantTimeCsrfAuthorizer — registers the subclass above under the standard csrfCheck name. - docs/CSRF_GUIDE.md: end-to-end recipe covering what Pac4j does by default, the two rough edges these helpers smooth over (rotation vs HTMX; weak hashEquals in pac4j-core 6.3.2), the wiring order, meta-tag + hx-headers pattern, and anti-patterns. Cross-linked from HTTP_SERVER_GUIDE.md's Pac4jHttpSecurity section. Verified against http.compile / http.test / http.checkFormat / http.fix --check on Scala 3.3.7. Extracted from the FiftyForms Cards BFF where this shape was validated end-to-end via a runtime IT (Pac4jCsrfSpec — five scenarios) and a live Playwright smoke on 2026-07-17. 🤖 Generated with Claude Code
feat(pac4j): session CSRF helpers + constant-time csrfCheck authorizer
All checks were successful
CI / Compile (pull_request) Successful in 2m41s
CI / Check Formatting (pull_request) Successful in 51s
CI / Check Linting (pull_request) Successful in 2m36s
CI / Run Tests (pull_request) Successful in 2m58s
9ca9ec70d1
Adds three pieces that downstream apps need whenever they use
Pac4jHttpSecurity.secure() with server-rendered HTML + HTMX / forms:

- ConstantTimeCsrfAuthorizer: subclass of pac4j-core CsrfAuthorizer that
  overrides hashEquals with MessageDigest.isEqual over UTF-8 bytes.
  Closes a real weakness in pac4j-core 6.3.2: its hashEquals compares
  32-bit String.hashCode() values, which is collision-attackable
  (birthday ≈2^16, targeted ≈2^32) and not constant-time. Verified by a
  unit spec that finds a genuine collision for "abc" via random
  enumeration and asserts the subclass rejects it.

- Pac4jCsrfSupport: bridges request handlers to the session-managed
  pac4jCsrfToken. Provides tokenFor(req) so a Scalatags layout can embed
  the token in <meta name="csrf-token"> / hx-headers, plus two install
  helpers that mutate a Pac4j Config:
    * installNonRotatingMatcher — swaps in a CsrfTokenGeneratorMatcher
      whose generator has setRotateTokens(false). Required for the HTMX
      pattern where the token is rendered once per full page and reused
      across many partial POSTs (default rotation kills the second POST).
    * installConstantTimeCsrfAuthorizer — registers the subclass above
      under the standard csrfCheck name.

- docs/CSRF_GUIDE.md: end-to-end recipe covering what Pac4j does by
  default, the two rough edges these helpers smooth over (rotation vs
  HTMX; weak hashEquals in pac4j-core 6.3.2), the wiring order, meta-tag
  + hx-headers pattern, and anti-patterns. Cross-linked from
  HTTP_SERVER_GUIDE.md's Pac4jHttpSecurity section.

Verified against http.compile / http.test / http.checkFormat / http.fix
--check on Scala 3.3.7.

Extracted from the FiftyForms Cards BFF where this shape was validated
end-to-end via a runtime IT (Pac4jCsrfSpec — five scenarios) and a live
Playwright smoke on 2026-07-17.

🤖 Generated with Claude Code
mph merged commit 8018bc4163 into main 2026-07-18 06:43:23 +00:00
mph deleted branch feat/pac4j-csrf-support 2026-07-18 06:43:23 +00:00
mph referenced this pull request from a commit 2026-07-24 07:33:37 +00:00
mph referenced this pull request from a commit 2026-07-24 07:37:10 +00:00
Sign in to join this conversation.
No description provided.