Files
orion/docs/proposals/store-login-platform-detection.md
Samir Boulahtit cfce6c0ca4
Some checks failed
CI / ruff (push) Successful in 10s
CI / validate (push) Has been cancelled
CI / dependency-scanning (push) Has been cancelled
CI / docs (push) Has been cancelled
CI / deploy (push) Has been cancelled
CI / pytest (push) Has been cancelled
fix: loyalty module end-to-end — merchant route, store menus, sidebar, API error handling
- Add merchant loyalty overview route and template (was 404)
- Fix store loyalty route paths to match menu URLs (/{store_code}/loyalty/...)
- Add loyalty rewards card to storefront account dashboard
- Fix merchant overview to resolve merchant via get_merchant_for_current_user_page
- Fix store login to use store's primary platform for JWT token (interim fix)
- Fix apiClient to attach status/errorCode to thrown errors (fixes error.status
  checks in 12+ JS files — loyalty settings, terminal, email templates, etc.)
- Hide "Add Product" sidebar button when catalog module is not enabled
- Add proposal doc for proper platform detection in store login flow

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 13:52:11 +01:00

3.3 KiB

Store Login: JWT Token Gets Wrong Platform

Status: Open — needs design review on fallback strategy Date: 2026-02-24

Problem

When a user logs in to a store via /platforms/loyalty/store/FASHIONHUB/login, the JWT token should encode platform_id=3 (loyalty). Instead, it gets platform_id=2 (main). This causes the store sidebar menu to show the wrong modules — e.g., analytics (from "main") appears while loyalty (from "loyalty") is missing.

Root Cause Chain

  1. User visits http://localhost:8000/platforms/loyalty/store/FASHIONHUB/login
  2. PlatformContextMiddleware detects loyalty and rewrites path to /store/FASHIONHUB/logincorrect
  3. Login page renders with loyalty platform context — correct
  4. JavaScript login.js POSTs to apiClient.post('/store/auth/login', ...) which resolves to /api/v1/store/auth/loginno platform prefix
  5. PlatformContextMiddleware sees /api/v1/store/auth/login, doesn't match /platforms/*, defaults to "main" platform
  6. Store auth endpoint calls get_current_platform(request) → gets "main" (id=2) instead of "loyalty" (id=3)
  7. Token encodes platform_id=2, all subsequent menu/API calls use the wrong platform

The Referer-based platform extraction in the middleware (middleware/platform_context.py lines 359-374) only handles /api/v1/storefront/ paths, not /api/v1/store/ paths.

Why is_primary Is Wrong

A store can be subscribed to multiple platforms. The platform should be determined by the login URL context (which platform the user navigated from), not by a database default. Using is_primary would always pick the same platform regardless of how the user accessed the store.

Key Constraint

  • Production: One domain per platform (e.g., omsflow.lu for OMS, loyaltyflow.lu for loyalty). Store subdomains: fashionhub.omsflow.lu. Premium domains: fashionhub.lu.
  • Development: Path-based: /platforms/{code}/store/{store_code}/login
  • A store can be on multiple platforms and should show different menus depending on which platform URL the user logged in from.

Current Workaround

app/modules/tenancy/routes/api/store_auth.py currently uses is_primary to resolve the platform from the store's store_platforms table. This works for single-platform stores but breaks for multi-platform stores.

Files Involved

File Role
middleware/platform_context.py Platform detection from URL/domain — doesn't cover /api/v1/store/ paths
middleware/store_context.py Store detection from URL/domain
app/modules/tenancy/routes/api/store_auth.py Store login endpoint — creates JWT with platform_id
app/modules/tenancy/static/store/js/login.js Frontend login — POSTs to /api/v1/store/auth/login
static/shared/js/api-client.js API client — base URL is /api/v1 (no platform prefix)
models/schema/auth.py UserLogin schema — currently has store_code but not platform_code
app/modules/core/routes/api/store_menu.py Menu API — reads token_platform_id from JWT

Open Questions

  • What should the fallback strategy be when platform can't be determined from the login context?
  • Should the solution also handle storefront customer login (which has the same issue)?
  • Should the Referer-based detection in platform_context.py be extended to cover /api/v1/store/ paths as a complementary fix?