Panel admin refuse les connections (local) #60

Closed
opened 2020-07-22 13:09:33 +02:00 by Lephenixnoir · 14 comments
Owner

Sur mon instance locale je ne peux pas accéder au panel admin ; peu importe mes droits, je me fais déconnecter et renvoyer vers la page de connexion.

Une idée sur le changement que j'ai manqué là-dessus ?

Sur mon instance locale je ne peux pas accéder au panel admin ; peu importe mes droits, je me fais déconnecter et renvoyer vers la page de connexion. Une idée sur le changement que j'ai manqué là-dessus ?
Owner

C'est quelle route qui pose problème ? Tu peux tenter un flask shell, puis :

> from app.models.users import Member
> m = Member.query.filter_by(name="Lephe").first()
> print(m.priv('access-admin-panel'))

Ce qui est bizarre, c'est que à aucun moment le décorateur @priv_required ne renvoie vers la page de déconnexion.

C'est quelle route qui pose problème ? Tu peux tenter un `flask shell`, puis : ``` > from app.models.users import Member > m = Member.query.filter_by(name="Lephe").first() > print(m.priv('access-admin-panel')) ``` Ce qui est bizarre, c'est que à aucun moment le décorateur `@priv_required` ne renvoie vers la page de déconnexion.
Author
Owner

C'est /admin qui pose le problème. Le privilège est bien là, ce code renvoie True.

Voilà la réponse exacte à la requête, c'est une 302 :

[pid: 1376163|app: 0|req: 19/19] ::1 () {48 vars in 1302 bytes} [Wed Jul 22 16:28:35 2020] GET /admin => generated 255 bytes in 1 msecs (HTTP/1.1 302) 5 headers in 334 bytes (1 switches on core 0)
C'est `/admin` qui pose le problème. Le privilège est bien là, ce code renvoie `True`. Voilà la réponse exacte à la requête, c'est une 302 : ``` [pid: 1376163|app: 0|req: 19/19] ::1 () {48 vars in 1302 bytes} [Wed Jul 22 16:28:35 2020] GET /admin => generated 255 bytes in 1 msecs (HTTP/1.1 302) 5 headers in 334 bytes (1 switches on core 0) ```
Author
Owner

Ce comportement est bien causé par @priv_required et visiblement je tombe dans le cas not current_user.is_authenticated alors que je suis connecté. Du coup ça ne me surprend pas trop qu'il me déconnecte au passage. Par contre difficile de savoir comment j'ai atteri là.

Ce comportement est bien causé par `@priv_required` et visiblement je tombe dans le cas `not current_user.is_authenticated` alors que je suis connecté. Du coup ça ne me surprend pas trop qu'il me déconnecte au passage. Par contre difficile de savoir comment j'ai atteri là.
Author
Owner

Correction : même sans @priv_required, je ne suis jamais connecté quand j'arrive sur le panel admin. Le current_user est toujours un AnonymousUserMixin. Peut-être que les informations de session ne sont pas importées pour une raison ou une autre ?

Correction : même sans `@priv_required`, je ne suis jamais connecté quand j'arrive sur le panel admin. Le `current_user` est toujours un `AnonymousUserMixin`. Peut-être que les informations de session ne sont pas importées pour une raison ou une autre ?
Author
Owner

Ce n'est pas lié au code spécifiquement de routes/admin/index.py parce que coller une version de la page de profil ici (modulo renommer la fonction et modifier l'URL de la route) donne le même résultat. Ça doit donc être dans l'environnement, eg. la façon dont la route est importée...

Ce n'est pas lié au code spécifiquement de `routes/admin/index.py` parce que coller une version de la page de profil ici (modulo renommer la fonction et modifier l'URL de la route) donne le même résultat. Ça doit donc être dans l'environnement, eg. la façon dont la route est importée...
Author
Owner

Pour reproduire :

  • Pull dev
  • Visiter /admin

Comportement attendu : Panel admin ou 403

Comportement observé : Page de connexion

Pour reproduire plus avant :

  • Commenter le @priv_required dans routes/admin/index.py
  • Visiter /admin

Comportement attendu : Panel admin avec le compte connecté dans la navbar

Comportement observé : Panel admin mais le compte n'est plus connecté

Pour reproduire : * Pull `dev` * Visiter `/admin` Comportement attendu : Panel admin ou 403 Comportement observé : Page de connexion Pour reproduire plus avant : * Commenter le `@priv_required` dans `routes/admin/index.py` * Visiter `/admin` Comportement attendu : Panel admin avec le compte connecté dans la navbar Comportement observé : Panel admin mais le compte n'est plus connecté
Owner

Je n'arrive pas à reproduire ici… 😕

Ça peut pas être un problème de cache Nginx mal configuré ? Le code 302 Found me fait penser à ça.

Tu peux essayer la même chose mais en passant par flask run ?

Je n'arrive pas à reproduire ici… :confused: Ça peut pas être un problème de cache Nginx mal configuré ? Le code `302 Found` me fait penser à ça. Tu peux essayer la même chose mais en passant par `flask run` ?
Author
Owner

Bieeen vu, je ne peux pas reproduire avec flask run. J'avais oublié cette option. Mais je n'ai rien non plus de particulier dans la config nginx, et je ne vois pas exactement comment le cache peut produire ce problème - le script Flask est bien appelé, je debugge des variables dedans.

(Au passage j'ai plein de 308 sur le forum, /forum/news est réécrit en /forum/news/ par le validateur donc ça crée des redirections. Faudra s'en défaire.)

Bieeen vu, je ne peux pas reproduire avec `flask run`. J'avais oublié cette option. Mais je n'ai rien non plus de particulier dans la config nginx, et je ne vois pas exactement comment le cache peut produire ce problème - le script Flask est bien appelé, je debugge des variables dedans. (Au passage j'ai plein de 308 sur le forum, `/forum/news` est réécrit en `/forum/news/` par le validateur donc ça crée des redirections. Faudra s'en défaire.)
Darks added the
bug
label 2020-07-23 11:37:50 +02:00
Author
Owner

Soit dit au passage, la 302 c'est la redirection vers la page de connexion donc parfaitement normale. Si je vire le décorateur @priv_required la réponse à la requête est une 200 normale mais je suis quand même déconnecté.

[pid: 2857188|app: 0|req: 5/5] ::1 () {48 vars in 1289 bytes} [Thu Jul 23 14:46:53 2020] GET /admin => generated 14428 bytes in 13 msecs (HTTP/1.1 200) 4 headers in 247 bytes (1 switches on core 0)

Bon je vais utiliser flask run je crois, même si ça m'emmerde pas savoir d'où ça vient tout ça...

Soit dit au passage, la 302 c'est la redirection vers la page de connexion donc parfaitement normale. Si je vire le décorateur `@priv_required` la réponse à la requête est une 200 normale mais je suis quand même déconnecté. ``` [pid: 2857188|app: 0|req: 5/5] ::1 () {48 vars in 1289 bytes} [Thu Jul 23 14:46:53 2020] GET /admin => generated 14428 bytes in 13 msecs (HTTP/1.1 200) 4 headers in 247 bytes (1 switches on core 0) ``` Bon je vais utiliser `flask run` je crois, même si ça m'emmerde pas savoir d'où ça vient tout ça...
Author
Owner

J'ai l'immense plaisir de préciser que j'ai également ce problème avec flask run, donc dans l'immédiat j'ai un environnement à moitié cassé pour développer...

J'ai l'immense plaisir de préciser que j'ai *également* ce problème avec `flask run`, donc dans l'immédiat j'ai un environnement à moitié cassé pour développer...
Author
Owner

Nouvelle information et nouveau workaround : ça ne le fait qu'avec Firefox, et pas avec Qutebrowser chez moi. Peut-être un cookie qui se fait éjecter, un truc à surveiller côté uBlock ou le "ad" qui gêne.

Nouvelle information et nouveau workaround : ça ne le fait qu'avec Firefox, et pas avec Qutebrowser chez moi. Peut-être un cookie qui se fait éjecter, un truc à surveiller côté uBlock ou le "ad" qui gêne.
Author
Owner

Ça se précise pas mal avec un message dans la console pour chaque requête ou presque :

Cookie “session” will be soon treated as cross-site cookie against “http://localhost:5000/<url>” because the scheme does not match.

J'ai regardé dans app/static/scripts/pc-utils.js, grep https et cookie dans le dépôt mais je ne vois rien qui empêche le cookie de fonctionner en HTTP. Y a-t-il une protection qui a été mise en place de ce côté-là ?

Ça se précise pas mal avec un message dans la console pour chaque requête ou presque : ```plain Cookie “session” will be soon treated as cross-site cookie against “http://localhost:5000/<url>” because the scheme does not match. ``` J'ai regardé dans `app/static/scripts/pc-utils.js`, grep `https` et `cookie` dans le dépôt mais je ne vois rien qui empêche le cookie de fonctionner en HTTP. Y a-t-il une protection qui a été mise en place de ce côté-là ?
Author
Owner

Les paramètres de sécurité des cookies sont en cause ici. Ils sont bien expliqués sur MDN, en gros trois paramètres sont importants :

  • Secure pour n'envoyer les cookies que sur des connexions HTTPS (mitige MITM) ;
  • HttpOnly pour ne pas exposer les cookies au Javascript (mitige front-end malveillant ou injection JS) ;
  • SameSite={Strict,Lax,None} pour ne pas envoyer les cookies aux origines croisées sauf via actions statiques, liens, etc (idem).

En les spécifiant plus strictement y'a plus les warnings et le problème de connexion au panel admin disparaît. Faudrait juste confirmer que ça cassera rien en prod.

Les paramètres de sécurité des cookies sont en cause ici. Ils sont bien expliqués [sur MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies), en gros trois paramètres sont importants : * `Secure` pour n'envoyer les cookies que sur des connexions HTTPS (mitige MITM) ; * `HttpOnly` pour ne pas exposer les cookies au Javascript (mitige front-end malveillant ou injection JS) ; * `SameSite={Strict,Lax,None}` pour ne pas envoyer les cookies aux origines croisées sauf via actions statiques, liens, etc (idem). En les spécifiant plus strictement y'a plus les warnings et le problème de connexion au panel admin disparaît. Faudrait juste confirmer que ça cassera rien en prod.
Author
Owner

Puisque ce commit est en preprod depuis longtemps et n'a rien cassé, je suis content de pouvoir fermer cette issue. ^^

Puisque ce commit est en preprod depuis longtemps et n'a rien cassé, je suis content de pouvoir fermer cette issue. ^^
Sign in to join this conversation.
No description provided.