fix(api): autorise l'origine WebView Capacitor dans CORS_ORIGIN #82

Merged
kyuno merged 1 commit from fix/cors-origin-capacitor-app into main 2026-09-07 08:39:56 +02:00
Owner

Bug

L'app Android n'arrivait pas à se logger ni à s'inscrire : /auth/login
et /auth/signup semblaient répondre 204 côté logs serveur, avec
« erreur inattendue » affichée côté client — alors que le site web
fonctionnait normalement.

Cause

CORS_ORIGIN n'est jamais défini explicitement en prod
(docker-compose.yml ne le passe pas au service app), donc il
retombait sur son default de code, http://localhost:5173 (le serveur
Vite de dev). Ça ne matche évidemment jamais l'origine réelle de
l'appli packagée, https://localhost (voir capacitor.config.ts —
c'est l'origine fixe par défaut de la WebView Android de Capacitor).
Le site web, lui, n'a jamais ce problème : il est servi depuis la même
origine que l'API en prod, donc aucun preflight CORS n'entre en jeu
sur /auth/*.

Le symptôme est trompeur à cause du fonctionnement du package cors :
un preflight OPTIONS reçoit toujours 204, même pour une origine
qui va être rejetée — la seule différence (invisible sans inspecter les
headers) est l'absence de Access-Control-Allow-Origin, qui fait
ensuite bloquer le vrai POST côté client sans qu'il n'atteigne jamais
le serveur. Vu depuis les logs serveur, la route a bien l'air
« appelée » (le preflight matche le même chemin) alors que
/auth/login lui-même n'est jamais réellement reçu.

Fix

CORS_ORIGIN devient une liste séparée par des virgules (le type
ExpressServerCoreOptions.corsOrigin acceptait déjà string | string[])
et son default inclut désormais https://localhost. L'origine de
l'appli packagée est fixe et non secrète (contrairement au domaine du
site en prod, qui n'a de toute façon pas besoin d'être dans cette
liste puisqu'il est same-origin) — la coder en dur dans le default
couvre tout déploiement sans configuration supplémentaire à faire côté
Portainer/.env.

Vérification

Script ad hoc démarrant le vrai createServer() et envoyant un
preflight OPTIONS /auth/login avec différentes origines :

  • https://localhost (app) et http://localhost:5173 (Vite dev)
    reçoivent maintenant Access-Control-Allow-Origin.
  • Une origine arbitraire non listée continue de ne rien recevoir (pas
    de bypass en wildcard).

pnpm --filter api exec tsc --noEmit et pnpm exec biome check sur
les fichiers touchés — tous les deux propres.

🤖 Generated with Claude Code

## Bug L'app Android n'arrivait pas à se logger ni à s'inscrire : `/auth/login` et `/auth/signup` semblaient répondre 204 côté logs serveur, avec « erreur inattendue » affichée côté client — alors que le site web fonctionnait normalement. ## Cause `CORS_ORIGIN` n'est jamais défini explicitement en prod (`docker-compose.yml` ne le passe pas au service `app`), donc il retombait sur son default de code, `http://localhost:5173` (le serveur Vite de dev). Ça ne matche évidemment jamais l'origine réelle de l'appli packagée, `https://localhost` (voir `capacitor.config.ts` — c'est l'origine fixe par défaut de la WebView Android de Capacitor). Le site web, lui, n'a jamais ce problème : il est servi depuis la même origine que l'API en prod, donc aucun preflight CORS n'entre en jeu sur `/auth/*`. Le symptôme est trompeur à cause du fonctionnement du package `cors` : un preflight `OPTIONS` reçoit **toujours** 204, même pour une origine qui va être rejetée — la seule différence (invisible sans inspecter les headers) est l'absence de `Access-Control-Allow-Origin`, qui fait ensuite bloquer le vrai `POST` côté client sans qu'il n'atteigne jamais le serveur. Vu depuis les logs serveur, la route a bien l'air « appelée » (le preflight matche le même chemin) alors que `/auth/login` lui-même n'est jamais réellement reçu. ## Fix `CORS_ORIGIN` devient une liste séparée par des virgules (le type `ExpressServerCoreOptions.corsOrigin` acceptait déjà `string | string[]`) et son default inclut désormais `https://localhost`. L'origine de l'appli packagée est fixe et non secrète (contrairement au domaine du site en prod, qui n'a de toute façon pas besoin d'être dans cette liste puisqu'il est same-origin) — la coder en dur dans le default couvre tout déploiement sans configuration supplémentaire à faire côté Portainer/`.env`. ## Vérification Script ad hoc démarrant le vrai `createServer()` et envoyant un preflight `OPTIONS /auth/login` avec différentes origines : - `https://localhost` (app) et `http://localhost:5173` (Vite dev) reçoivent maintenant `Access-Control-Allow-Origin`. - Une origine arbitraire non listée continue de ne rien recevoir (pas de bypass en wildcard). `pnpm --filter api exec tsc --noEmit` et `pnpm exec biome check` sur les fichiers touchés — tous les deux propres. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
kyuno added 1 commit 2026-09-07 08:23:25 +02:00
fix(api): autorise l'origine WebView Capacitor dans CORS_ORIGIN
All checks were successful
CI / lint (push) Successful in 1m44s
CI / build (push) Successful in 1m44s
CI / intent-service-test (push) Successful in 4m6s
CI / e2e (push) Successful in 7m5s
CI / test (push) Successful in 15m50s
CI / build-android (push) Has been skipped
5e478188a2
L'app Android n'arrivait a se logger/inscrire nulle part (204 +
"erreur inattendue" cote client) : CORS_ORIGIN n'etait jamais defini en
prod (docker-compose.yml ne le passe pas a `app`), donc il retombait
sur son default `http://localhost:5173` (le serveur Vite de dev), qui
ne matche evidemment jamais l'origine reelle de l'appli packagee
(`https://localhost`, cf. capacitor.config.ts). Le site web n'est lui
jamais touche : il est servi depuis la meme origine que l'API en prod,
donc jamais de preflight CORS du tout sur /auth/*.

Le symptome trompeur vient du package `cors` : un preflight OPTIONS
recoit toujours 204, meme pour une origine rejetee — la difference
invisible sans inspecter les headers est l'absence de
Access-Control-Allow-Origin, qui fait ensuite bloquer le vrai POST
cote client sans jamais atteindre le serveur. Vu depuis les logs
serveur, la route a bien l'air "appelee" (le preflight matche le meme
chemin) alors que /auth/login lui-meme n'est jamais reellement recu.

CORS_ORIGIN devient une liste separee par des virgules (le type
`ExpressServerCoreOptions.corsOrigin` acceptait deja `string | string[]`)
et son default inclut desormais `https://localhost` — l'origine de
l'appli packagee est fixe et non secrete (contrairement au domaine du
site en prod, qui n'a de toute facon pas besoin d'etre dans cette
liste puisqu'il est same-origin), donc la coder en dur dans le default
couvre tout deploiement sans configuration supplementaire.

Verifie en local : script ad hoc qui demarre le vrai `createServer()`
et envoie un preflight OPTIONS /auth/login avec differentes origines —
`https://localhost` et `http://localhost:5173` recoivent maintenant
Access-Control-Allow-Origin, une origine arbitraire non listee
continue de ne pas le recevoir (pas de bypass en wildcard). Egalement
`pnpm --filter api exec tsc --noEmit` et `pnpm exec biome check` sur
les fichiers touches.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
kyuno merged commit 94ef8b4133 into main 2026-09-07 08:39:56 +02:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: kyuno/batchCooking#82
No description provided.