Files
accounted/lib/domains/legacy-redirect.ts
T
Jakob Wennberg 335d908614 fix(domains,skatteverket): #1087 follow-ups: auth-path redirect exclusions, SKV callback hardening (#1094)
- Exclude auth/ and reset-password from the legacy-host redirect (#1092):
  email links sent before the cutover carry a PKCE code or recovery
  session whose cookies live on app.gnubok.se; forwarding them to the
  new domain breaks password resets and signup confirmations clicked
  after the flip. login/MFA stay redirected on purpose: a usable login
  page on the legacy host would establish sessions there and loop.
  Exclusion pattern extracted to lib/domains/legacy-redirect.ts with a
  unit test pinning the behavior.
- Clean up ephemeral oauth state rows (incl. oauth_user_id) when the
  SKV token exchange fails (#1090): identity data must not outlive the
  flow; best-effort so cleanup failure never masks the user-facing error.
- Assert the stored user is still a member of the company before the
  service-role storeTokens write (#1091): membership can be revoked
  between /authorize and the callback, and RLS no longer backstops the
  write. Checked before the exchange so the one-shot code is not burned.

Fixes #1090, fixes #1091, fixes #1092.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-21 13:48:01 +02:00

26 lines
1.2 KiB
TypeScript

/**
* Path exclusions for the legacy-host (app.gnubok.se) page redirect in
* next.config.ts.
*
* Machine surfaces (api/, .well-known/), assets (_next/) and the
* PKCE-cookie-bound auth flows (auth/, reset-password) must keep answering
* on the legacy host after the app.accounted.se cutover; everything else
* forwards to the new domain. auth/ and reset-password stay because email
* links sent before the cutover carry a PKCE code or recovery session
* whose cookies live on the legacy host (#1092); the login and MFA pages
* are deliberately NOT excluded, since a usable login page on the legacy
* host would establish sessions there and bounce users in a redirect loop.
*/
export const LEGACY_HOST_REDIRECT_EXCLUSIONS =
'(?!api/|\\.well-known/|_next/|auth/|reset-password)'
/**
* Mirror of how the path-to-regexp source `/:path((?!...).*)` decides
* whether a legacy-host request is forwarded. Used by tests to pin the
* exclusion behavior without booting Next's router.
*/
export function isRedirectedFromLegacyHost(pathname: string): boolean {
const relative = pathname.replace(/^\//, '')
return new RegExp(`^${LEGACY_HOST_REDIRECT_EXCLUSIONS}.*$`).test(relative)
}