Closed abulte closed 5 months ago
Merci pour le ticket déjà bien détaillé ! Vous avez une solution de contournement ou c'est vraiment très bloquant chez vous ?
Je vois deux contournements :
1/ je ne pense vraiment pas me lancer là-dedans 👹 et 2/ c'est triste 😢 surtout qu'on travaille sur le SEO en ce moment et que les slugs c'est bien mieux à ce niveau là (et pour les usagers au passage).
Donc ça dépend de ce que tu appelles très bloquant :-) Bloquant mais pas très ?
Idem 404
Access to XMLHttpRequest at 'https://demo.data.gouv.fr/api/2/topics/xxx/' from origin 'http://localhost:5173' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.
@maudetes on a identifié un autre cas où ça nous bloque (https://github.com/ecolabdata/ecospheres/issues/221) donc je change ma priorisation à très bloquant 👹 😉 🙏
A priori le problème vient de la spécification de CORS plutôt que de Nginx ou Flask… Il y a quelques propositions ici sur la page de Firefox https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#preflighted_requests_and_redirects mais la spécification de CORS est en train de changer pour autoriser les redirections de ce que j'en comprends… Peut-être que la solution la plus simple dans ton cas c'est de ne pas envoyer le header Authorization
pour ces requêtes là (qui ne le nécessitent pas ?)
Précision, la section sur le site de Firefox parle d'une redirection après la requête pre-flight ce qui n'est peut-être pas la même chose qu'une redirection en retour de la requête pre-flight, mais je ne vois vraiment pas commet ça pourrait fonctionner côté Python où on a forcément la redirection… Dans tous les cas, ne pas envoyer le header Authorization
devrait fonctionner je pense…
J'ai push une PR https://github.com/opendatateam/udata/pull/3046 qui corrige le problème mais je ne suis pas du tout sûr de la validité de faire ça et si ça posera pas de problème autre part…
Effectivement ça marcherait de ne pas envoyer le header Authorization mais ce n'est pas trivial car il faudrait indiquer pour chaque appel à l'API si on a besoin de l'Authorization ou non. Discriminer sur le verbe ne suffirait pas (eg GET /me
a besoin de Authorization). Possible aussi qu'on ait des cas où on a à la fois besoin d'être authentifié et de faire une requête sur une page qui atterrit en redirect. Par exemple sur un dataset supprimé (410) visible seulement pour un admin ou le owner.
Cool pour https://github.com/opendatateam/udata/pull/3046 mais ça ne traite que le cas des redirections, on en aurait aussi besoin pour les 4xx, voire même les 5xx parce qu'on peut vouloir réagir de manière différente dans ces cas là (d'ailleurs dans ce cas, impossible de savoir à l'avance si on a besoin d'être authentifié ou non).
Je pense que le plus simple pour vous est de le gérer au niveau Nginx. Moins de code à maintenir et réglé une fois pour toute. Vous pourriez même désactiver Flask-Cors
quand pas en mode DEBUG.
NB : quelques issues pas très intéressantes sur Flask-Cors
@jordanguedj Tu as un avis sur ce problème ? On le fait côté Nginx ?
Salut, j'ai déployé sur demo une nouvelle version avec les CORS corrigés. Est-ce que vous avez des pages spécifiques qui plantaient sur ecologie.data.gouv.fr que l'on pourrait tester sur demo.ecologie.data.gouv.fr et vérifier que ça fonctionne mieux ?
Hello ! Plus de page qui plante depuis https://github.com/opendatateam/udata-front-kit/pull/464, on contourne la plupart des problèmes en n'envoyant pas le header d'authorization quand pas besoin.
C'est ok en démo sur les redirections
❯ curl -X OPTIONS -i https://demo.data.gouv.fr/api/2/topics/premier-slug/
HTTP/1.1 308 PERMANENT REDIRECT
server: nginx
date: Wed, 10 Jul 2024 07:39:34 GMT
Ok 401 sur /api/me
❯ curl -X OPTIONS -i https://demo.data.gouv.fr/api/1/me/
HTTP/1.1 200 OK
server: nginx
date: Wed, 10 Jul 2024 07:43:45 GMT
Mais pas sur les autres codes, comme 404 (logique, vu la PR).
❯ curl -X OPTIONS -i https://demo.data.gouv.fr/api/2/topics/not-a-topic/
HTTP/1.1 404 NOT FOUND
server: nginx
date: Wed, 10 Jul 2024 07:39:53 GMT
Je n'ai pas de endpoint pour tester les 5xx, mais ce serait bien qu'on puisse les gérer proprement dans la SPA et donc récupérer la "vraie" requête. Ce serait intéressant d'avoir un endpoint qui retourne arbitrairement une 500 d'ailleurs.
Les requêtes preflight doivent contenir un header Access-Control-Request-Method
et un Origin
sinon elles ne sont pas valides (donc les tests avec uniquement -X OPTIONS
n'exerce pas le nouveau code)
Mais tant que ça fonctionne pour vous, ça me va. Si vous rencontrez d'autres soucis n'hésitez pas à me les envoyer. (normalement le code fonctionne pour tous les codes d'erreurs 3xx, 4xx, 5xx…)
https://demo.data.gouv.fr/api/2/topics/premier-slug/
➜ udata git:(fix_cors) curl -X OPTIONS -H "Access-Control-Request-Method: GET" -H "Origin: demo.ecologie.data.gouv.fr" -i https://demo.data.gouv.fr/api/2/topics/premier-slug/
HTTP/1.1 204 NO CONTENT
server: nginx
date: Wed, 10 Jul 2024 07:59:29 GMT
content-type: text/html; charset=utf-8
access-control-allow-origin: demo.ecologie.data.gouv.fr
vary: Origin, Access-Control-Request-Method, Access-Control-Request-Headers, Access-Control-Request-Method, Origin
access-control-allow-credentials: true
access-control-allow-methods: GET
access-control-allow-headers:
pragma: public
cache-control: public
x-content-type-options: nosniff
x-xss-protection: 1; mode=block
x-frame-options: SAMEORIGIN
https://demo.data.gouv.fr/api/1/me/
➜ udata git:(fix_cors) curl -X OPTIONS -H "Access-Control-Request-Method: GET" -H "Origin: demo.ecologie.data.gouv.fr" -i https://demo.data.gouv.fr/api/1/me/
HTTP/1.1 204 NO CONTENT
server: nginx
date: Wed, 10 Jul 2024 07:59:03 GMT
content-type: text/html; charset=utf-8
access-control-allow-origin: demo.ecologie.data.gouv.fr
vary: Origin, Access-Control-Request-Method, Access-Control-Request-Headers, Access-Control-Request-Method, Origin
access-control-allow-credentials: true
access-control-allow-methods: GET
access-control-allow-headers:
pragma: public
cache-control: public
x-content-type-options: nosniff
x-xss-protection: 1; mode=block
x-frame-options: SAMEORIGIN
https://demo.data.gouv.fr/api/2/topics/not-a-topic/
➜ udata git:(fix_cors) curl -X OPTIONS -H "Access-Control-Request-Method: GET" -H "Origin: demo.ecologie.data.gouv.fr" -i https://demo.data.gouv.fr/api/2/topics/not-a-topic/
HTTP/1.1 204 NO CONTENT
server: nginx
date: Wed, 10 Jul 2024 08:00:15 GMT
content-type: text/html; charset=utf-8
access-control-allow-origin: demo.ecologie.data.gouv.fr
vary: Origin, Access-Control-Request-Method, Access-Control-Request-Headers, Access-Control-Request-Method, Origin
access-control-allow-credentials: true
access-control-allow-methods: GET
access-control-allow-headers:
pragma: public
cache-control: public
x-content-type-options: nosniff
x-xss-protection: 1; mode=block
x-frame-options: SAMEORIGIN
Ah ok, c'est https://github.com/opendatateam/udata/pull/3074 que tu as mis sur démo ? Looks nice, je vais faire quelques tests depuis notre SPA et je te dis.
C'est KO même avec les contournements actuels sur démo.
Tu peux tester sur demo.ecologie.data.gouv.fr et essayer de te logguer. Au retour oauth, la requête vers https://demo.data.gouv.fr/oauth/token plante. A priori la requête preflight est bien passée puisque c'est le POST qui pose problème.
Access to XMLHttpRequest at 'https://demo.data.gouv.fr/oauth/token' from origin 'https://demo.ecologie.data.gouv.fr' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
Request:
POST /oauth/token HTTP/1.1
Accept: application/json, text/plain, */*
Accept-Encoding: gzip, deflate, br, zstd
Accept-Language: fr-FR,fr;q=0.9,en-US;q=0.8,en;q=0.7
Connection: keep-alive
Content-Length: 872
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryC3qW654q1rZ54elU
Host: demo.data.gouv.fr
Origin: https://demo.ecologie.data.gouv.fr
Referer: https://demo.ecologie.data.gouv.fr/
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-site
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36
sec-ch-ua: "Google Chrome";v="125", "Chromium";v="125", "Not.A/Brand";v="24"
sec-ch-ua-mobile: ?0
Response:
HTTP/1.1 200 OK
server: nginx
date: Thu, 11 Jul 2024 07:01:29 GMT
content-type: application/json
content-length: 178
cache-control: no-store
pragma: no-cache
pragma: public
cache-control: public
x-content-type-options: nosniff
x-xss-protection: 1; mode=block
x-frame-options: SAMEORIGIN
Peut-être que le problème ne vient pas de là mais j'ai activé CORS de façon open uniquement sur les endpoints API, j'avais oublié les endpoints OAuth, je viens de l'activer je redéploie et je reteste et je te dis
C'est déployé et le flow OAuth fonctionne :-) N'hésite pas à me dire si tu vois d'autres problèmes
C'est toujours KO sur demo.ecologie.data.gouv.fr pour moi :-/
Tu peux essayer en navigation privée pour voir si c'est pas un problème de cache ?
Oui j'ai fait ça, mais rien n'y fait. Testé sous Chrome et FF.
Je ne sais pas si tu as changé qqchose mais le login marche maintenant :-)
Oui en fait j'avais déployé mon fix sur dev à la place de demo… :-(
Ca marche bien sans les contournements sur notre front (donc en envoyant toujours le header d'Authorization) : 308 et 404 ok 👌
Conditions de reproduction :
Authorization
Dans ce cas :
308
👍Authorization
308
à la réponse à la requête OPTIONS, pas seulement au GET ❌Un code de redirect n'est pas acceptable pour une requête preflight (voir Spécifications, étape 7 : ok status). Chrome affiche une erreur
Redirect is not allowed for a preflight request.
.Il faudrait donc retourner une réponse de type
2xx
(probablement204
) pour OPTIONS, même si la requête GET subséquente retournera bien un3xx
. Cf la conf simplifiée ici qui retourne toujours un204
.Ci-dessous un exemple pour https://demo.data.gouv.fr/api/2/topics/plantabilite-des-arbres/ qui redirige vers https://demo.data.gouv.fr/api/2/topics/calque-de-plantabilite/.
Requête :
Réponse :