fix(pac4j): validate Pac4jSecurityConfig and stop composing OIDC URLs from baseUri #31
No reviewers
Labels
No labels
bug
documentation
duplicate
enhancement
good first issue
help wanted
invalid
question
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
iterative-works/support!31
Loading…
Reference in a new issue
No description provided.
Delete branch "PLATFORM-210-fix-pac4j-url-composition"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
iw-support 0.1.15's
Pac4jConfigFactorycomposed the OIDCredirect_uriasurlBase + baseUri.toString + callbackBase + "/callback". When callers passedbaseUri = BaseUri(urlBase)(the natural-looking usage matching howBaseUriisconstructed everywhere else),
urlBasewas duplicated:The same
baseUri.value.fold(\"/\")(_.toString)was used for the session-cookiePathattribute, producingPath=http://localhost:8090instead of a path.Both bugs went unnoticed because no spec exercised the URL or cookie
composition — the existing pac4j tests only covered the
AuthenticationServiceplumbing. Surfaced during live verification of platform PLATFORM-210 Phase 2 (BFF
server with Auth0 OIDC); the Auth0 login dance failed immediately at the first
redirect with "Callback URL mismatch."
Changes
API (breaking):
baseUri: BaseUriparameter fromPac4jConfigFactoryandPac4jHttpSecurity. Removing it surfaces misuse at compile time so callerscannot silently produce malformed URLs. Downstream callers need a
one-line update: drop the
baseUriargument.Pac4jSecurityConfig:New
cookiePath: Option[String]field (defaultSome(\"/\")) replaces themisuse of
baseUri.toStringfor the cookiePathattribute.New derived methods:
callbackUrl: String = s\"\$urlBase\$callbackBase/callback\"— composed once,used everywhere.
resolvedCookiePath: String = cookiePath.getOrElse(\"/\").mapOrFailvalidation on the ZIO Config descriptor rejects malformed valueswith clear
Config.Error.InvalidDataat startup:urlbasemust be an absolute origin (no path/query/fragment, no trailing/)callbackbasemust be empty or path-only (leading/, no trailing/, noscheme)
cookiepath(when set) must be a pathcallbackUrlmust parse as an absolute URI with a hostAnyone previously relying on a tolerated misconfiguration now fails loudly at
boot with an actionable error message instead of silently producing broken
URLs that Auth0 rejects.
Pac4jConfigFactory:cfg.callbackUrlfor theClientsregistry — no more string surgery.cfg.resolvedCookiePathfor the session-store path.securecookie flag to checkurlBase.startsWith(\"https://\"). Theprevious check was on
callbackBasewhich, after the contract change, is apath and never starts with a scheme — so the flag was always false.
Tests:
Pac4jSecurityConfigSpecwith 15 cases locking down validation rules andcomposition: rejects trailing-slash
urlbase, missing-slashcallbackbase,scheme in
callbackbase, bare/, invalidcookiepath; accepts emptycallbackbase; verifiescallbackUrl/resolvedCookiePathoutputs and thatthe composed URL parses cleanly.
mill http.testpasses (~50 cases across 9 specs).Docs:
HTTP_SERVER_GUIDE.mdPac4j section rewritten with the new contract,per-field validation rules, composition formula, and an env-var mapping
table. Marked the constructor change as a breaking change.
Migration for downstream consumers
If
callbackBasepreviously held a full URL or no leading slash, update it tomatch the new contract; validation will surface the exact problem.
Test plan
redirect_uriclean single prefixPath=/Verified locally on iterative-works platform PLATFORM-210 against Auth0
`fiftyforms.eu.auth0.com` —
/healthunchanged,/302 with clean`redirect_uri=http%3A%2F%2Flocalhost%3A8090%2Fauth%2Foidc%2Fcallback`, session
cookie
Path=/.🤖 Generated with Claude Code
Closing this without merging.
After investigation we found that iw-support's `BaseUri` has overloaded semantics
across consumers: `BlazeHttpServer.withBaseUri` and `ViteSupport` treat it as a
path-prefix where the app is mounted, while the Scala.js `fromLocation` layer and
`ConsulKeyValueStore` treat it as a URL. The original `Pac4jConfigFactory` formula
`urlBase + baseUri.toString + callbackBase + "/callback"` was internally consistent
under the path-prefix interpretation (and existing consumers wire it that way,
either leaving `BASEURI` unset → `BaseUri(None)` → `/`, or setting it to a mount
path like `/admin`).
The platform-side bug that motivated this PR was that PLATFORM-210's `AuthModule`
called `BaseUri(cfg.urlBase)` — passing the full origin URL where a path was
expected. The fix belongs on the platform side, not in iw-support: drop the
`BaseUri(cfg.urlBase)` line, read `BaseUri.config` like other consumers do (with
the path-prefix semantic), and leave `BASEURI` unset for root-mounted apps. That
gives a clean composed `redirect_uri` with no iw-support changes.
The broader `BaseUri` naming/semantic problem is real but out of scope for the
Pac4j-specific work that triggered this PR. Tracking it separately as an issue.
Pull request closed