Project

General

Profile

Development #69221

backend authn : faire que le backend login/mot de passe accepte le numéro de téléphone de l’usager

Added by Paul Marillonnet 4 months ago. Updated about 1 month ago.

Status:
Solution déployée
Priority:
Normal
Category:
-
Target version:
-
Start date:
19 September 2022
Due date:
% Done:

0%

Estimated time:
Patch proposed:
Yes
Planning:
No

Description

Du code déjà présent en partie dans #65173, que je dois déplacer ici et accompagner de davantage de tests, diviser pour mieux régner etc.


Files


Related issues

Related to Publik - Development #49212: Création de compte avec un numéro de téléphone mobileEn cours01 October 2021

Actions
Related to Authentic 2 - Development #70486: forms : avoir un champ et son widget pour l’authentification par numéro de téléphoneSolution déployée19 October 2022

Actions
Related to Authentic 2 - Development #72430: authn : lorsqu’actif faire apparaître le champ téléphone au dessus du champ par mot de passeSolution déployée14 December 2022

Actions
Related to Authentic 2 - Development #72440: authn mobile : XOR sur le username/email et le numéro de téléphoneNouveau14 December 2022

Actions
Related to Authentic 2 - Development #72449: authn mobile : conserver le PhoneField custom pour l’enregistrement uniquement, basculer sur un unique champ username/email/tél pour la page de connexionNouveau15 December 2022

Actions

Associated revisions

Revision f7d6895b (diff)
Added by Paul Marillonnet about 2 months ago

authentication/forms: add user phone as identifier (#69221)

History

#1

Updated by Paul Marillonnet 4 months ago

  • Related to Development #49212: Création de compte avec un numéro de téléphone mobile added
#2

Updated by Paul Marillonnet 4 months ago

  • Status changed from Nouveau to En cours
  • Assignee set to Paul Marillonnet
#3

Updated by Paul Marillonnet 4 months ago

La version au plus simple, qui ne nécessite pas de revoir complètement la façon dont on utilise le ModelBackend de Django. Le prix à payer pour ça est encore un peu de magie dans authentic2.forms.authentication.AuthenticationForm. Je pense que ça reste préférable.

Bien sûr en l’état l’affichage est moche, aucune aide à la sélection entre numéro de tél ou username/email, aucune aide à la saisie du numéro ni au choix du préfixe, aucune validation front de ce numéro -> tout ça c’est l’objet du ticket voisin #69222, que je m’empresse d’aller étudier là maintenant :)

#4

Updated by Agate Berriot 4 months ago

Ça me parait top, une question : je vois qu'on concatène le phone_prefix et le numéro de téléphone pour construire l'identifiant pour la requête. Ça risque pas de bugger sur des inputs type 0612345678 (avec la concaténation, on aura un +330612345678), à matcher avec potentiellement un +33612345678, sans le zéro ? Il me semble qu'un·e utilisateur aura tendance à taper son numéro avec le 0 comme préfixe mais je peux me tromper.

Plus généralement, peut-être que ça a été déjà discuté ailleurs, comment se passe la normalisation des numéros avant stockage en base ?

À part ces questions, c'est okay pour moi :)

#5

Updated by Thomas Noël 4 months ago

Agate Berriot a écrit :

Ça me parait top, une question : je vois qu'on concatène le phone_prefix et le numéro de téléphone pour construire l'identifiant pour la requête. Ça risque pas de bugger sur des inputs type 0612345678 (avec la concaténation, on aura un +330612345678), à matcher avec potentiellement un +33612345678, sans le zéro ? Il me semble qu'un·e utilisateur aura tendance à taper son numéro avec le 0 comme préfixe mais je peux me tromper.

Agate a raison... bienvenue en enfer, Paul ;)

Je vais ajouter qu'il faut ajouter dans les settings les préfixes des DROM, qui font partie du https://fr.wikipedia.org/wiki/Plan_de_num%C3%A9rotation_en_France (bonne lecture).

#6

Updated by Paul Marillonnet 4 months ago

Agate Berriot a écrit :

Ça me parait top, une question : je vois qu'on concatène le phone_prefix et le numéro de téléphone pour construire l'identifiant pour la requête. Ça risque pas de bugger sur des inputs type 0612345678 (avec la concaténation, on aura un +330612345678), à matcher avec potentiellement un +33612345678, sans le zéro ? Il me semble qu'un·e utilisateur aura tendance à taper son numéro avec le 0 comme préfixe mais je peux me tromper.

Je m’imaginais faire d’abord un truc qui marche pour les numéros français, avec dans #69222 une aide à la saisie lorsque le préfixe français est sélectionné (par exemple en isolant le premier chiffre puis en regroupant deux par deux les huit chiffres suivants, afin que l’usager capte bien que le zéro initial saute). Mais j’ai zappé ce que Thomas met ici et donc il me faut revoir ma copie :)

Sans cette hypothèse, j’avoue que je ne sais pas trop de quelle façon on peut restreindre davantage ici, notamment parce que https://en.wikipedia.org/wiki/Telephone_numbers_in_Belgium, page à laquelle je ne comprends rien :)

Plus généralement, peut-être que ça a été déjà discuté ailleurs, comment se passe la normalisation des numéros avant stockage en base ?

Non, pas discuté ailleurs, et ici et maintenant peut être l’occasion d’en discuter. J’avais en tête de faire dans #69222 un maximum de sanitization de l’input en front, pour réduire au maximum les écarts entre les données collectées par le formulaire et la version stockée en base. Typiquement juste une suite de chiffres sans le zéro initial, qu’on pourrait vérifier facilement ensuite sans normalisation à proprement parler. J’avais peur qu’à tolérer de trop grands écarts on loupe des choses à la normalisation, genre l’usager qui tape un caractère d’espacement exotique (espace semi-fine insécable " ", tirets typographiques "–" ou encore "—", etc.) qui casserait toute l’affaire. Mais peut-être cette approche est une mauvaise idée, on peut en discuter ici.

À part ces questions, c'est okay pour moi :)

Cool, merci pour ta relecture. Je vais avancer sur les autres tickets liés à #49212 pour pouvoir proposer une démo complète avant qu’on envisage passer tous ces patches.

#7

Updated by Agate Berriot 4 months ago

Thomas Noël a écrit :

Agate Berriot a écrit :

Ça me parait top, une question : je vois qu'on concatène le phone_prefix et le numéro de téléphone pour construire l'identifiant pour la requête. Ça risque pas de bugger sur des inputs type 0612345678 (avec la concaténation, on aura un +330612345678), à matcher avec potentiellement un +33612345678, sans le zéro ? Il me semble qu'un·e utilisateur aura tendance à taper son numéro avec le 0 comme préfixe mais je peux me tromper.

Agate a raison... bienvenue en enfer, Paul ;)

Je vais ajouter qu'il faut ajouter dans les settings les préfixes des DROM, qui font partie du https://fr.wikipedia.org/wiki/Plan_de_num%C3%A9rotation_en_France (bonne lecture).

Pour moi la solution durable, c'est de prendre une bibliothèque type https://pypi.org/project/phonenumbers/#description et tout normaliser via ce biais avant de stocker ou faire des comparaisons. Ça nous permettra de gérer du même coup les espaces, tirets, tous les formats un peu chelous avec les parenthèses, les préfixes avec + ou les doubles 00. Surtout si on commence à accepter des numéros d'autres pays ou de territoires avec des préfixes ou des structures différentes et qu'on bricole un truc maison, ça va être ingérable.

#8

Updated by Paul Marillonnet 4 months ago

Agate Berriot a écrit :

Pour moi la solution durable, c'est de prendre une bibliothèque type https://pypi.org/project/phonenumbers/#description et tout normaliser via ce biais avant de stocker ou faire des comparaisons. Ça nous permettra de gérer du même coup les espaces, tirets, tous les formats un peu chelous avec les parenthèses, les préfixes avec + ou les doubles 00. Surtout si on commence à accepter des numéros d'autres pays ou de territoires avec des préfixes ou des structures différentes et qu'on bricole un truc maison, ça va être ingérable.

Oui, sûr, surtout ne rien bricoler. Je vais regarder cette bibliothèque, déjà empaquetée dans Debian. Je note aussi que des gens ont fait le taff d’intégration directe de cette bibliothèque nativement dans Django, ça donne https://django-phonenumber-field.readthedocs.io/en/latest/, ça a l’air maintenu et c’est aussi disponible dans les dépôts standards Debian.

#9

Updated by Paul Marillonnet 4 months ago

Paul Marillonnet a écrit :

[…] Je note aussi que des gens ont fait le taff d’intégration directe de cette bibliothèque nativement dans Django, ça donne https://django-phonenumber-field.readthedocs.io/en/latest/, ça a l’air maintenu et c’est aussi disponible dans les dépôts standards Debian.

Et non, raté, packagé que dans sid.

#10

Updated by Frédéric Péters 4 months ago

Et non, raté, packagé que dans sid.

Pas un gros problème ça.

#11

Updated by Paul Marillonnet 4 months ago

Frédéric Péters a écrit :

Pas un gros problème ça.

Ok, noté, je regarde plus en détails.

#12

Updated by Benjamin Dauvergne 4 months ago

Thomas Noël a écrit :

Je vais ajouter qu'il faut ajouter dans les settings les préfixes des DROM, qui font partie du https://fr.wikipedia.org/wiki/Plan_de_num%C3%A9rotation_en_France (bonne lecture).

Ça dit :

Tous les correspondants du territoire national (métropole ou DOM) peuvent s'appeler entre eux en utilisant le plan de numérotation français à dix chiffres, sans composer le code pays pour la voix, les SMS et les MMS. À Saint-Pierre-et-Miquelon, les abonnés peuvent se joindre en composant les six derniers chiffres de leurs numéros. 

je pense que les numéros mobiles sont exposés sur les toutes les indicatifs nationaux du plan de numérotation, donc on peut mettre +33 tout le temps.

#13

Updated by Benjamin Dauvergne 4 months ago

Je suis d'avis de ne rien faire de tout ça, d'accepter seulement ^0[67][0-9]{8}$ et l'équivalent pour la Belgique et d'avoir en dur une fonction pour convertir ça vers le numéro à appeler (et idem à l'enregistrement/la modification).

#14

Updated by Paul Marillonnet 4 months ago

Benjamin Dauvergne a écrit :

Je vais ajouter qu'il faut ajouter dans les settings les préfixes des DROM, qui font partie du https://fr.wikipedia.org/wiki/Plan_de_num%C3%A9rotation_en_France (bonne lecture).

Ça dit :
[...]
je pense que les numéros mobiles sont exposés sur les toutes les indicatifs nationaux du plan de numérotation, donc on peut mettre +33 tout le temps.

Hmm, à lire de la doc ici et là à ce sujet, il est dit que ça marche parce que les opérateurs savent “en général” reconstituer le code pays lorsqu’on tape un numéro à dix chiffres sans préfixe. Donc j’ai l’impression que justement non on ne peut pas mettre +33 tout le temps, l’intelligence est du côté opérateur qui retrouve le code. Quelqu’un a une compréhension différente de l’affaire ?

Est-ce qu’on est sûr que ça va marcher quand on a recours à un service tiers d’envoi de SMS ? Notamment est-ce que ces services acceptent systématiquement d’envoyer à numéros à dix chiffres sans mention du code pays ? Ou bien est-ce à nous de retrouver ce code avant l’appel au service d’envoi (auquel cas il faut aller dans le sens de ce que propose Agate) ?

Bref trop d’interrogations, avant de poursuivre je dois me renseigner là-dessus.

#15

Updated by Agate Berriot 4 months ago

Paul Marillonnet a écrit :

Benjamin Dauvergne a écrit :

Je vais ajouter qu'il faut ajouter dans les settings les préfixes des DROM, qui font partie du https://fr.wikipedia.org/wiki/Plan_de_num%C3%A9rotation_en_France (bonne lecture).

Ça dit :
[...]
je pense que les numéros mobiles sont exposés sur les toutes les indicatifs nationaux du plan de numérotation, donc on peut mettre +33 tout le temps.

Hmm, à lire de la doc ici et là à ce sujet, il est dit que ça marche parce que les opérateurs savent “en général” reconstituer le code pays lorsqu’on tape un numéro à dix chiffres sans préfixe. Donc j’ai l’impression que justement non on ne peut pas mettre +33 tout le temps, l’intelligence est du côté opérateur qui retrouve le code. Quelqu’un a une compréhension différente de l’affaire ?

Est-ce qu’on est sûr que ça va marcher quand on a recours à un service tiers d’envoi de SMS ? Notamment est-ce que ces services acceptent systématiquement d’envoyer à numéros à dix chiffres sans mention du code pays ? Ou bien est-ce à nous de retrouver ce code avant l’appel au service d’envoi (auquel cas il faut aller dans le sens de ce que propose Agate) ?

Bref trop d’interrogations, avant de poursuivre je dois me renseigner là-dessus.

Pour moi, si on doit s'interfacer avec des services / APIs tiers type Twilio ou SMS Factor, c'est quasiment sûr qu'il faudra un format unique et standard avec le prefixe (par exemple sms factor demande le prefixe 33 pour la france métropolitaine et si je me base sur https://www.smsfactor.com/tarifs-api-sms, il y a un pricing différent pour la Guyane ou la Réunion, et ça m'étonnerait fortement qu'ils fassent de la magie pour reconnaître quoi envoyer où si on ne fournit pas le bon indicateur pays).

#16

Updated by Paul Marillonnet 4 months ago

  • Status changed from Solution proposée to En cours

Agate Berriot a écrit :

Pour moi, si on doit s'interfacer avec des services / APIs tiers type Twilio ou SMS Factor, c'est quasiment sûr qu'il faudra un format unique et standard avec le prefixe (par exemple sms factor demande le prefixe 33 pour la france métropolitaine et si je me base sur https://www.smsfactor.com/tarifs-api-sms, il y a un pricing différent pour la Guyane ou la Réunion, et ça m'étonnerait fortement qu'ils fassent de la magie pour reconnaître quoi envoyer où si on ne fournit pas le bon indicateur pays).

Oui c’est ma compréhension de l’affaire, je vais partir là-dessus.

J’ai poussé une branche qui reprend le premier patche mais avec l’usage d’un MultiValueField de Django, avec son MultiWidget qui va avec. Ça simplifie le code du formulaire et facilitera l’usage de phonenumbers. Je reprends ça demain.

#17

Updated by Paul Marillonnet 4 months ago

Paul Marillonnet a écrit :

J’ai poussé une branche qui reprend le premier patche mais avec l’usage d’un MultiValueField de Django, avec son MultiWidget qui va avec. Ça simplifie le code du formulaire et facilitera l’usage de phonenumbers. Je reprends ça demain.

Voilà, ça simplifie les choses en effet, en particulier l’usage de phonenumbers, la possibilité de réutiliser cette class PhoneField(MultiValueField): pour l’enregistrement du compte de l’usager, et le travail d’affichage du champ à l’usager (#69222).

#18

Updated by Benjamin Dauvergne 3 months ago

  • Status changed from Solution proposée to En cours
  • je ne suis pas pour l'ajout d'un PhoneField dans LoginForm, ça complexifie, il faut prendre n'importe quelle entrée qui ressemble à un numéro de téléphone, éventuellement la normaliser et chercher la desssus (comme on peut le faire en recherche libre sur les utilisateur).
  • le PhoneField devrait sélectionner le pays par défaut
  • le champ indicatif devrait rappeler le territoire avant l'indicatif "Guyane française (+xxx)", y a peut-être moyen d'extraire ça de libphonenumber d'aillerus
#19

Updated by Benjamin Dauvergne 3 months ago

On peut peut-être poussé tout ce qui est widget/field ici, et garder les aspects formulaire d'authent dans un autre ticket, pour avancer.

#20

Updated by Paul Marillonnet 3 months ago

Benjamin Dauvergne a écrit :

On peut peut-être poussé tout ce qui est widget/field ici, et garder les aspects formulaire d'authent dans un autre ticket, pour avancer.

Ok, je fais un autre ticket.

#21

Updated by Paul Marillonnet 3 months ago

  • Related to Development #70486: forms : avoir un champ et son widget pour l’authentification par numéro de téléphone added
#22

Updated by Paul Marillonnet 2 months ago

Benjamin Dauvergne a écrit :

  • je ne suis pas pour l'ajout d'un PhoneField dans LoginForm, ça complexifie,

L’idée est de faire dans #69222 le travail en front de simplification, avoir un switch pour que l’un ou l’autre des champs email et téléphone s’affiche à l’usager dans la mire d’authentification, mais pas les deux à là fois.

  • le PhoneField devrait sélectionner le pays par défaut

Ok.

  • le champ indicatif devrait rappeler le territoire avant l'indicatif "Guyane française (+xxx)", y a peut-être moyen d'extraire ça de libphonenumber d'aillerus

Ok.

#23

Updated by Paul Marillonnet 2 months ago

Paul Marillonnet a écrit :

  • le PhoneField devrait sélectionner le pays par défaut

Ok.

Dans le champ PhoneField :

    def __init__(self, **kwargs):
        fields = (
            CharField(max_length=8, initial=settings.DEFAULT_COUNTRY_CODE),
            # […]
        )

  • le champ indicatif devrait rappeler le territoire avant l'indicatif "Guyane française (+xxx)", y a peut-être moyen d'extraire ça de libphonenumber d'aillerus

Ok.

Dans le widget associé, PhoneWidget :

        prefixes = (
            (code, '{area} (+{code})'.format(area=value['area'], code=code))
            for code, value in settings.PHONE_COUNTRY_CODES.items()
        )

et dans les settings :
PHONE_COUNTRY_CODES = {
    '32': {'lang': 'BE', 'area': _('Belgium')},
    '33': {'lang': 'FR', 'area': _('Metropolitan France')},
    '262': {'lang': 'FR', 'area': _('Réunion')},
    '508': {'lang': 'FR', 'area': _('Saint Pierre and Miquelon')},
    '590': {'lang': 'FR', 'area': _('Guadeloupe')},
    '594': {'lang': 'FR', 'area': _('French Guiana')},
    '596': {'lang': 'FR', 'area': _('Martinique')},
}

#24

Updated by Benjamin Dauvergne about 2 months ago

  • Status changed from Solution proposée to Solution validée
#25

Updated by Paul Marillonnet about 2 months ago

  • Status changed from Solution validée to Résolu (à déployer)
commit f7d6895b94a102abdcace776366e4a41d9942559
Author: Paul Marillonnet <pmarillonnet@entrouvert.com>
Date:   Mon Sep 19 09:52:12 2022 +0200

    authentication/forms: add user phone as identifier (#69221)
#26

Updated by Paul Marillonnet about 2 months ago

  • Related to Development #72430: authn : lorsqu’actif faire apparaître le champ téléphone au dessus du champ par mot de passe added
#27

Updated by Paul Marillonnet about 2 months ago

  • Related to Development #72440: authn mobile : XOR sur le username/email et le numéro de téléphone added
#28

Updated by Paul Marillonnet about 2 months ago

  • Related to Development #72449: authn mobile : conserver le PhoneField custom pour l’enregistrement uniquement, basculer sur un unique champ username/email/tél pour la page de connexion added
#29

Updated by Transition automatique about 1 month ago

  • Status changed from Résolu (à déployer) to Solution déployée

Also available in: Atom PDF