Geoportail-Luxembourg / geoportailv3

geoportailv3 is the implementation of the v3 of the map viewer of the luxembourgish geoportal
MIT License
25 stars 16 forks source link

Questions sur l'authentification. #148

Closed rmichaelis closed 9 years ago

rmichaelis commented 9 years ago

Hello,

Je suis en train de développer le composant d’authentification. Pour se faire, je me connecte à une base de données ldap et je vérifie que mon utilisateur est valide.

J’ai plusieurs questions :

1) J’ai du installer dans mon environnement des librairies python et ldap. a. Yum install openldap-devel b. Pip install python-ldap c. Pip install pyramid_ldap Comment dois-je faire pour automatiser celà dans le build ?

2) Pour faire mon authentification ldap j’ai créé une vue ldap_user_validator (comme spécifié dans la doc) dans laquelle je vérifie si mon utilisateur et mon de passe sont ok. Dans l’ancienne application, pour chaque tentative de connexion on insère dans une base de données de statistques, l’utilisateur, l’adresse ip et si la connexion à réussi ou échoué. Est-ce que ldap_user_validator est le bon endroit pour faire ca, ou bien dois-je le faire à un autre endroit ?

3) Dans le fichier init.py je configure mon environnement ldap. J’ai ajouté les settings qui sont configurables dans vars_renaud.yaml (tels que ldap url, base_dn, ...) et j’ai modifié les fichiers development.ini.in et production.ini.in afin que ces variables soient accessibles directement dans les settings. Est-ce la bonne manière de procéder ?

4) Mon environnement fonctionne et lorsque je fais http://localhost:8081/login?login=monlogin&password=monpassword celà me retourne true si le login est ok et une erreur 401 si pas ok. Les cookies sont également correctement mis. Tout cela est pris en charge par c2cgeoportal

Maintenant j’aimerais donc travailler sur l’interface graphique pour me connecter. C’est probablement une bête question, mais je vais créer un formulaire html avec une action qui pointe vers /login avec mes paramètres user et password. Comment est-ce que je redirige vers la bonne page à savoir vers la resource demandée lorsque c’est ok ou bien vers un écran de login lorsque c’est une erreur 401 qui est retournée. Je ne comprends pas bien comment faire le lien entre c2cgeoportal et l’application.

5) Dans l'ancien map, lorsqu'un utilisateur était logué, les cookies avaient une date d'expiration car on veut forcer l'utilisateur à se reconnecter après un certain temps. Je n'ai pas trouvé la possibilité dans c2cgeoportal de spécifier le timeout sur le cookie. Est-ce que la possibilité existe ou bien dois-je le reprogrammer moi-même ?

Merci

elemoine commented 9 years ago

Je n'ai toujours pas eu le temps de regarder ça, et je dois passer à autre chose. Je le fais la semaine prochaine. Ou, si c'est urgent, et que @sbrunner a le temps de regarder ça alors je le laisse faire.

sbrunner commented 9 years ago

1) Il faut les ajouter dans le install_requires du setup.py: https://github.com/Geoportail-Luxembourg/geoportailv3/blob/master/setup.py#L18

sbrunner commented 9 years ago

2) Cela me semble effectivement le bon endroit :-)

sbrunner commented 9 years ago

3) Personnellement je les mettrais plutôt dans les variables à exporté soit ajouter CONFIG_VARS += ldap_url ldap_base_dn dans le fichier geoportailv3.mk https://github.com/Geoportail-Luxembourg/geoportailv3/blob/master/geoportailv3.mk#L18

A voir si cela fonctionne, car si on en a besoin avant le include de c2cgeoportal https://github.com/Geoportail-Luxembourg/geoportailv3/blob/master/geoportailv3/__init__.py#L23 on est contraint de le mettre dans les fichiers development.ini.in et production.ini.in

sbrunner commented 9 years ago

4) @elemoine tu as probablement plus d'informations que mois, ce que je peut dire c'est que dans CGXP on effectue une requête d’authentification ajax et on recharge la page uniquement si c'est ok.

sbrunner commented 9 years ago

5) non, cela n'existe pas et il vaut mieux que l'on le fasse dans c2cgeoportal.

elemoine commented 9 years ago

Voici quelques informations au sujet de la question 4) de @rmichaelis:

Le service login de c2cgeoportal fonctionne avec des requêtes GET et POST. Actuellement, avec CGXP, c'est POST qui est utilisé. Et nous utilisons des requêtes XHR.

Lorsque les credentials ne sont pas valides, le service retourne une 401. C'est à la partie client de détecter cette erreur et d'avertir l'utilisateur que ses credentials ne sont pas valides. Il n'y a pas de rechargement de la page dans ce cas.

Lorsque les credentials sont valides le service retourne une 200 (avec true dans le body mais c'est sans importance). Suite à ça, le composant login de CGXP fait un rechargement de la page, pour que toutes les requêtes initiales soient refaites en utilisant cette fois le cookie d'authentification. Le rechargement de la page n'est pas obligatoire, c'est à la partie client de décider ce qu'elle veut faire.

Si les credentials sont valides il existe aussi un mode où le service login retourne une 302 pour un faire un redirect. Ce mode est activé quand un paramètre came_from est passé à la requête de login. Tu peux très bien tester ça en GET, avec ceci par exemple : http://localhost:8081/login?login=monlogin&password=monpassword&came_from=http://google.com.

Le code du service login est ici: https://github.com/camptocamp/c2cgeoportal/blob/master/c2cgeoportal/views/entry.py#L1203-L1225.

rmichaelis commented 9 years ago

@sbrunner concernant le point 3. J'ai pu ajouter mes variables dans le geoportailv3.mk ca fonctionne super.

Par contre j'ai du ajouter les définition de authtkt_secret, authtkt_cookie_name dans le development.ini.in et production.ini.in . Sans ca, ca ne fonctionnait pas. Est-ce que c'est normal ?

sbrunner commented 9 years ago

Oui, c'est normal :-)

rmichaelis commented 9 years ago

parfait merci ;-)

rmichaelis commented 9 years ago

Quelqu'un a-t-il une idée de pourquoi lorsque je suis connecté je peux retrouver dans mon controlleur pyramid le login de mon utilisateur grâce à authenticated_userid(self.request) et que par contre je ne peux pas le retrouver grâce à self.request.user ?

Autre question, dans c2cgeoportal est-ce que je dois configurer quelque chose pour pouvoir faire un logout ? Actuellement le login fonctionne comme attendu mais le logout me retourne une erreur 404 ?

elemoine commented 9 years ago

Quelqu'un a-t-il une idée de pourquoi lorsque je suis connecté je peux retrouver dans mon controlleur pyramid le login de mon utilisateur grâce à authenticated_userid(self.request) et que par contre je ne peux pas le retrouver grâce à self.request.user ?

Tu utilises le mode standard d'auth de c2cgeoportal ou as-tu déjà des trucs spécifiques ?

Autre question, dans c2cgeoportal est-ce que je dois configurer quelque chose pour pouvoir faire un logout ? Actuellement le login fonctionne comme attendu mais le logout me retourne une erreur 404 ?

Le service logout retourne une 404 si request.user est None. Donc c'est lié à ton premier problème.

rmichaelis commented 9 years ago

J'utilise un validator pour vérifier la connexion dans ldap.

Dans les logs j'obtiens cette info : 2015-02-05 20:01:37,916 INFO [c2cgeoportal.views.entry][Dummy-2] User 'renaud.michaelis' logged in.

Donc je suppose que mon validator fonctionne correctement.

elemoine commented 9 years ago

Il faut que je vois ton code pour comprendre ce qui cloche.

rmichaelis commented 9 years ago

Ici le validator : https://github.com/Geoportail-Luxembourg/geoportailv3/blob/lux_authentication/geoportailv3/views/authentication.py

Et ici l'association du validator avec l'authetification c2cgeoportal:

https://github.com/Geoportail-Luxembourg/geoportailv3/blob/lux_authentication/geoportailv3/__init__.py

elemoine commented 9 years ago

Est-ce que ton utilisateur est aussi dans la base de donnée (table "user") ?

rmichaelis commented 9 years ago

Non je ne l'ai pas défini dans la table user. Si mais j'ai bien compris le but du user validator, c'est justement de ne pas utiliser cette table et de tester le user contre une autre source de données.

Par contre je me demande si le problème ne vient pas du role associé à l'utilisateur. Je vais un peu creuser dans cette direction.

elemoine commented 9 years ago

Il est là le problème. On a besoin d'avoir les utilisateurs dans la table "user", même si leur mot de passe n'y sont pas stockés et même si l'identification se fait par ailleurs. D'ailleurs l'objet request.user est une instance de la classe modèle SQLA "User" définie dans c2cgeoportal.

elemoine commented 9 years ago

Ou alors il faut redéfinir la fonction qui sette le user sur les objets request. C'est expliqué dans la doc : http://docs.camptocamp.net/c2cgeoportal/master/integrator/authentication.html. Mais dans ce cas il faut qu'LDAP fournisse un id permettant de trouver le rôle de l'utilisateur.

rmichaelis commented 9 years ago

Ok je vais voir avec la redéfinition de la fonction. Merci