Skip to content

Fix dual-domain cookie invalidation on logout#91

Merged
KrisSimon merged 7 commits intomainfrom
feature/edgecase-impreovements
Feb 19, 2026
Merged

Fix dual-domain cookie invalidation on logout#91
KrisSimon merged 7 commits intomainfrom
feature/edgecase-impreovements

Conversation

@KrisSimon
Copy link
Copy Markdown
Contributor

Summary

  • Dual-domain cookie invalidation: When a tenant has an interceptor domain (e.g. .ops.example.com) and an OAuth login page on a different host (e.g. login.ops.example.com), the browser holds two separate SSO cookies. Logout now invalidates both via ExtraCookiesMiddleware, which appends extra Set-Cookie headers after Vapor's SessionsMiddleware dictionary round-trip.
  • Helm cookieDomain mapping: The per-domain cookieDomain from values.domains[] is now passed to the application via a domain-cookies ConfigMap (COOKIE_DOMAINS env var), so OAuth login cookies are set on the correct broad domain.
  • WebKit logout resilience: /logout/finalize no longer requires a valid JWT — WebKit may not send SameSite=Strict cookies on meta-refresh navigations. The endpoint falls back to the tenant from RequestClientMiddleware.
  • Wildcard cookie domain sanitization: *.example.com in Helm values is automatically sanitized to .example.com.

Test plan

  • swift build compiles without errors
  • ./tooling.sh lint — 0 violations
  • swift test --filter LoginControllerLogoutTests — 6/6 tests pass
  • ./tooling.sh e2e — 837 passed, 28 skipped, 0 failures (all browsers including WebKit)

In OAuth mode, setCookieDomain ignored the tenant's interceptor cookie
domain and fell back to the request host (e.g. login.ops.gcb-cloud.de).
This created a cookie on a different domain than the interceptor login
(e.g. .ops.gcb-cloud.de), resulting in two separate browser cookies.

Now both modes prefer tenant.config.interceptor.cookieOrDomain when
configured, so only one cookie domain is used consistently.
The Helm values.yaml has a cookieDomain per domain entry (e.g.
login.ops.gcb-cloud.de -> .ops.gcb-cloud.de) but it was never consumed.

Now the Helm chart serializes the mapping as a JSON env var
(COOKIE_DOMAINS) in the environment-config ConfigMap.
CookieDomainMapping reads it at startup and resolves cookie domains
for OAuth login and logout flows, so that cookies are set on the
correct broad domain (e.g. .ops.gcb-cloud.de) instead of the
specific login host (login.ops.gcb-cloud.de).
The e2e Helm values had cookieDomain: "*.bnbc.example" which is not a
valid Set-Cookie Domain attribute. Browsers reject wildcards and the
cookie is silently dropped, breaking the silent login flow.

Fix the e2e config to use ".bnbc.example" and add defensive
sanitization in CookieDomainMapping that converts "*.x" to ".x".
- Remove trailing whitespace in TokenController.swift
- Extract session storage configuration into configureSessionStorage()
  and configureInMemoryStorage() to fix function body length warning
  in configure.swift
WebKit/Safari may not send SameSite=Strict cookies on meta-refresh
navigations, causing the /logout/finalize endpoint to fail when the
uitsmijter-sso cookie is absent. The doLogout method now uses try?
for JWT verification and falls back to the tenant resolved by
RequestClientMiddleware from the location query parameter.

Also removes leftover debug dump() calls from TokenController and
a misleading debug log from configure.swift.
@KrisSimon KrisSimon merged commit d54fafc into main Feb 19, 2026
17 checks passed
@KrisSimon KrisSimon deleted the feature/edgecase-impreovements branch February 19, 2026 08:28
@KrisSimon KrisSimon mentioned this pull request Mar 5, 2026
3 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant