web-dev-qa-db-fra.com

En quoi doit consister un e-mail de vérification?

En ce moment, je génère une chaîne de 25 caractères stockée dans la base de données qui ne peut être utilisée qu'une seule fois et expire 30 minutes après l'enregistrement de l'utilisateur.

http://example.com/security/activate/ZheGgUNUFAbui4QJ48Ubs9Epd

Je fais une recherche rapide de base de données et la logique est la suivante:

Si le compte n'est pas activé ET si l'e-mail n'a pas été vérifié ET que le code de validation est toujours valide, activez le compte, marquez l'adresse e-mail comme vérifiée et marquez le code de validation comme utilisé.

Par exemple, toutes les 72 heures, il vidait les codes de validation expirés et utilisés. C'est pour dire à l'utilisateur que le lien d'activation cliqué a expiré par exemple s'il regarde son email le lendemain et essaie le lien.

Dois-je inclure l'UUID de l'utilisateur dans l'URL? Dois-je inclure autre chose?

J'ai pensé à m'assurer que l'adresse IP sur le formulaire d'inscription correspond à l'adresse IP de la demande lorsque le lien d'activation est enfoncé, mais pour moi, je lis principalement mes e-mails sur mon téléphone portable pour ce genre de choses, donc ce serait pénible pour UX .

65
HypeWolf

Comment générez-vous la chaîne de 25 caractères que vous incluez dans l'URL? Est-ce complètement aléatoire, ou est-il basé sur l'heure actuelle ou sur le courrier électronique des utilisateurs? Il doit être aléatoire et non devinable.

Vous devez vous assurer que la page de vérification s'affiche réellement (pas seulement qu'une demande GET s'est produite). Les navigateurs tels que chrome (et les programmes antivirus) chargent souvent les URL sans que l'utilisateur ne les clique explicitement en tant que prélecture ou pour des raisons de sécurité.

Cela pourrait entraîner un scénario où un acteur malveillant (Eve) souhaite créer un compte en utilisant le courrier électronique de quelqu'un d'autre (Alice). Eve s'inscrit et Alice reçoit un e-mail. Alice ouvre l'e-mail parce qu'elle est curieuse d'un compte qu'elle n'a pas demandé. Son navigateur (ou antivirus) demande l'URL en arrière-plan, activant le compte par inadvertance.

J'utiliserais JavaScript sur la page pour vérifier la page réellement affichée, et j'inclurais également un lien dans l'e-mail où les utilisateurs peuvent signaler qu'ils n'ont PAS créé ce compte.

105
Daisetsu

Ajout à la réponse du Daisetsu (car je ne peux pas encore écrire de commentaires).

Il ne serait pas mauvais de créer un formulaire et de demander à l'utilisateur de créer un mot de passe. de cette façon, l'utilisateur devra entrer un nouveau mot de passe et après l'avoir soumis, le compte sera activé. Cela résoudrait la vérification antivirus en arrière-plan.

Quant à l'URL, cela devrait être suffisant tant qu'il s'agit d'une chaîne aléatoire. Il y a très peu de chances que vous ayez 2 clés du même contenu à la fois.

Vérifier l'IP ne serait pas bon car certains FAI peuvent faire pivoter les adresses IP afin que vous bloquiez quelqu'un qui veut s'enregistrer mais ne peut pas.

22
Maros D.

Votre e-mail doit inclure un code d'activation, pas un lien. Vous ne devez pas envoyer de lien utilisé pour la gestion de compte dans un e-mail. Si vous (la partie légitime) liez des courriers électroniques (en particulier avec de longues chaînes de caractères aléatoires) à des utilisateurs, il est alors un peu plus difficile de distinguer les courriers électroniques légitimes des tentatives de phishing.

Le code d'activation doit être composé de caractères qui peuvent être facilement copiés et collés (pas d'espaces, '+', '-', etc.) et qui sont également faciles à saisir manuellement. Les lettres et les chiffres fonctionnent. La sécurité du code d'activation dépend de son caractère imprévisible. Vous dérivez la valeur en utilisant le générateur de nombres aléatoires sécurisé du système, tout comme vous devriez le faire avec les ID de session pour les cookies.

Les codes d'activation doivent être stockés dans une table de base de données, chaque ligne avec un ID de profil, le code d'activation*et le délai d'expiration. Vous ne voulez pas mettre l'ID de profil ou le délai d'expiration dans un cookie, une URL ou le code d'activation.** Un utilisateur malveillant pourrait altérer l'ID pour reprendre un autre compte. Vous devez vérifier ces éléments côté serveur, car votre politique de sécurité ne peut pas faire confiance aux données client à l'aveuglette.

Le code d'activation doit être soumis via une demande POST. Redirigez automatiquement les utilisateurs vers l'URL d'activation du compte (qui peut simplement être https://example.com/security/activate) lorsqu'ils ont terminé avec le reste de l'enregistrement. Facilitez à nouveau l'accès à la page d'activation du compte en cas de fermeture accidentelle.

Vous ne souhaitez pas qu'une requête GET effectue une action. Un lien peut être visité sans interaction de l'utilisateur (en raison de la prélecture du navigateur ou des services de sécurité des e-mails). De plus, le fait de mettre des secrets dans une URL peut entraîner une fuite de données sensibles. (Par le biais d'en-têtes de référence ou d'extensions de navigateur.)

Ne vous inquiétez pas de l'IP, elle peut encore changer. (Idem pour l'agent utilisateur.)

Je ne sais pas si une fonction d'annulation est souhaitable. Je n'utilise même pas les liens de désabonnement dans les e-mails non sollicités, car cela peut être un moyen de déterminer s'il existe ou non un humain associé à une adresse e-mail. Si le code d'activation est suffisamment long pour résister à la force brute ou si vous limitez le nombre de tentatives de code d'activation, je ne vois pas le mal à laisser le code d'activation expirer finalement.

En revanche, il pourrait être intéressant de réduire le nombre d'e-mails d'activation de compte indésirables. Vous pouvez limiter le nombre d'e-mails que vous envoyez à une adresse, pour être poli. Dites un maximum de 3 par jour et un maximum de 5 par mois. (Je ne sais pas si c'est trop élevé ou trop bas.) En tant que non-utilisateur, je ferais simplement des e-mails de votre site Web supprimés ou marqués automatiquement comme lus.

Il existe de nombreuses variables à prendre en compte pour les e-mails d'activation indésirables. Cela a probablement plus à voir avec l'expérience utilisateur qu'avec la sécurité. Vous pouvez aller jusqu'à proposer une fonction "annuler mon activation et ne jamais envoyer d'e-mails à cette adresse car je ne vais jamais m'enregistrer", mais cela pose des problèmes évidents. (Vous devez également vérifier l'e-mail de la personne également.)

* Cela ne fait pas de mal de hacher le code d'activation. Il n'est pas non plus essentiel de hacher, comme avec les mots de passe, car chaque code a une utilisation unique, ne contient aucune information privée, est généré de manière aléatoire par le serveur et expire.

** Vous pouvez réellement empêcher la falsification à l'aide d'un MAC cryptographique, mais je déconseille fortement d'essayer cela pour la plupart des développeurs. La cryptographie est difficile à réaliser correctement.

16
Future Security

Comme pour tout domaine où vous utilisez des pratiques de sécurité, l'évaluation de l'exposition et des menaces est quelque chose que vous devrez évaluer pour votre environnement unique et votre cas d'utilisation. Les réponses existantes fournissent de nombreux points de contact pour cette évaluation, ainsi que des pointeurs à éviter, tels que des actions déclenchées par GET. Au lieu de cela, je vais me concentrer davantage sur la partie "utilisateur" de l'UX. Je vais également aborder de nombreux commentaires éparpillés sur la page.

Exactement ce que vous "vérifiez" avec l'action déclenchée par e-mail est également un facteur à considérer. Si tout ce que vous faites est de confirmer qu'il s'agit d'une adresse e-mail valide, alors presque toute action sera suffisante. La vérification de l'e-mail, l'intention de créer le compte et que l'utilisateur qui reçoit l'e-mail est celui qui a initié la création du compte nécessite un peu plus d'efforts.

Un "effort" que vous ne devriez pas prendre, cependant, est l'envoi d'e-mails de rappel. En supposant que l'utilisateur a créé intentionnellement le compte, utilisé une adresse e-mail valide et souhaite utiliser le compte à quelque fin que ce soit que vous proposez, il recherchera l'e-mail et entreprendra le processus d'activation dès qu'il le pourra. Le lien, le code ou autre peut expirer avant de l'utiliser s'il est détourné sur d'autres sujets en attendant l'e-mail. Leur permettre de renvoyer l'e-mail de vérification dans de tels cas est très bien. Un e-mail de rappel, cependant, est beaucoup plus susceptible d'être un déclencheur de spam qu'un avantage pour l'utilisateur.

En tant qu'utilisateur, j'apprécie d'avoir des options disponibles pour activer/vérifier mon compte. Le jeu d'options le plus courant que j'ai rencontré est celui où l'e-mail fournit un lien sur lequel je peux cliquer ou couper et coller, et un code de confirmation que je peux entrer dans un champ de formulaire sur une page de mon zone de paramètres de compte sur le site Web. Le code de confirmation est rarement autre chose qu'un entier de 5 à 9 chiffres.

Les e-mails de vérification qui me donnent, en tant qu'utilisateur, le plus de confiance sont ceux qui ont un hachage crypto dans l'URL (/verify?l=lgGS2SBjMTU4NjkwNjYxMjI5MDBhZDk2YjEyMzMzYjNhZmQxOb), ce qui m'amène à une page unique à moi où je dois ensuite entrer le mot de passe que j'ai utilisé pour créer le compte. L'utilisation du hachage confirme que le lien a été reçu dans un e-mail, non deviné ou forcé brutalement, vérifiant ainsi que l'e-mail est valide. La diffusion de cette page unique, avant toute autre action, permet au serveur de marquer l'e-mail auquel il a été envoyé comme "valide" sans confirmer la création du compte. La saisie du mot de passe confirme qu'il y a un acteur à l'autre extrémité, par opposition à une opération antivirus, de détection de logiciels malveillants ou de prélecture. La validité du mot de passe confirme, à un degré de certitude raisonnable, que le destinataire de l'e-mail et le créateur du compte sont la même personne.

Le délai proposé de 30 minutes semble un peu sévère, alors qu'une période de 24 heures pourrait être trop longue si votre évaluation de la menace suggère que votre exposition en 24 heures est inacceptable. Je crois que 2 heures devraient être suffisantes pour presque tous les environnements d'utilisateurs. Surtout si la possibilité de renvoyer la vérification est disponible. Même en utilisant un appareil mobile avec une connexion de 14 kb/s à un compte POP distant, vous devriez pouvoir terminer l'échange en 120 minutes.

L'utilisation de JS pour vérifier en quelque sorte les actions humaines peut être problématique. JS peut être désactivé, et est beaucoup plus souvent que de nombreux développeurs Web aimeraient savoir. Deuxièmement, les bloqueurs de publicités peuvent bloquer JS sur une base par site ou par source, même lorsque JS est activé dans le navigateur. Je bloque de nombreuses sources JS, y compris les scripts d'analyse de Google, sur une base globale, et j'en liste sur la liste blanche pour des sites, tels que Stack Exchange, où je suis prêt à les soutenir avec l'utilisation de mes données.

Inclure un lien dans l'e-mail, ou sur la page de confirmation, pour "annuler" le compte est un gaspillage. Dans l'e-mail, il est en fait contre-productif, c'est-à-dire que cliquer sur un lien concernant un compte que vous ne voulez pas est une bonne idée. Au lieu de cela, l'e-mail doit inclure un verbiage pour indiquer que ne rien faire entraînera la non-confirmation du compte et sa suppression. Un lien pour annuler sur la page de confirmation est encore pire, car il récompense un mauvais comportement. Je reçois fréquemment des e-mails, dans le cadre d'un ancien snafu Google, dirigés vers un autre compte Gmail, et je suppose que l'inverse est également vrai pour l'autre compte. [Dans le passé, Google ne fusionnait pas les noms d'utilisateurs pointillés et non pointés, donc mon nom d'utilisateur pointillé et la version non pointée de quelqu'un d'autre sont des comptes différents, mais Google glissera de temps en temps et j'obtiens quand même leur e-mail :(]

Le degré de couplage de l'adresse e-mail "vérifiée" avec le lien d'activation est fonction de votre cas d'utilisation et de l'évaluation des menaces. Je suis légèrement ennuyé lorsque je dois revalider mon compte après avoir changé l'adresse e-mail associée. La façon dont j'accepte le processus est proportionnelle à ma "valeur" du compte. Pour mon compte bancaire, Paypal, etc., j'accepte à 100%. Sur PcPartsPicker, cependant, j'accepterais environ 15% d'un tel processus.

Quant à l'IP et/ou l'agent utilisateur, ignorez-les. À titre d'exemple, je vais souvent consulter des sites et choisir de créer un compte à l'aide de mon appareil mobile. Je vais pas, mais ouvrir des e-mails dessus. Si je crée un compte et que j'apprends que je dois le vérifier ou le confirmer d'une manière ou d'une autre et que le courrier électronique est la méthode proposée, j'attendrai jusqu'à ce que je rentre chez moi pour ouvrir le courrier électronique sur mon bureau, où je pourrai l'inspecter. L'IP et l'agent utilisateur seront donc très différents. Mon mot de passe, cependant, restera le même, et cela devrait être suffisant pour me confirmer en tant que créateur du compte d'origine.

N'oubliez pas que les e-mails sont à peu près aussi sécurisés que le Jumbo-tron à Times Square, et procédez en conséquence.

8
user135823

Un e-mail de vérification nécessite peu de choses, à la fois pour être raisonnablement sûr et convivial:

  1. L'utilisateur doit savoir clairement ce qui se passe. On vous explique pourquoi cet e-mail est reçu (par exemple "... quelqu'un a enregistré le compte BLAH sur notre site, c'est pour confirmer ...") exclut la plupart des erreurs stupides et déjoue raisonnablement les mails de pêche . J'espère savoir si vous venez d'enregistrer un compte auprès d'un service (à moins que vous ne soyez complètement dément). Donc, recevoir un e-mail qui explique cela n'est pas une surprise. D'un autre côté, un tel e-mail sachant que vous ne vous êtes enregistré nulle part devrait (enfin, espérons-le) être assez suspect. Si ce n'est pas le cas, et que l'utilisateur clique sur un lien aléatoire envoyé par e-mail, il n'y a rien que vous puissiez faire de toute façon, ne sachant pas quels courriers des personnes que vous ne connaissez pas peuvent recevoir ou non.
  2. Un jeton aléatoire (non séquentiel!) Qui est raisonnablement long (suffisamment long pour garantir qu'il est impossible à deviner et ne se heurte pas) renvoyé au serveur. Ce jeton est également stocké dans la base de données pour comparaison. Peu importe sa durée exacte et son format particulier. Il n'a pas besoin d'être lisible par l'homme. Tout ce qui est supérieur à 20 caractères environ (en supposant un encodage base64) devrait fonctionner, mais j'utiliserais 40 caractères pour être sûr car cela ne vous coûte vraiment rien. Une chaîne pseudo-aléatoire de 240 bits est à peu près garantie d'être unique et impossible à deviner. Pour plus de commodité, je voudrais en faire un lien, et le lien peut en effet être une demande GET. Oui, les utilisateurs ne sont pas censés cliquer sur les liens, mais ils le feront quand même (vous n'allez pas les éduquer!). D'un autre côté, expérience utilisateur est beaucoup mieux que d'avoir à copier-coller une chaîne obscure.
  3. Un formulaire HTML avec un type de bouton "cliquer pour confirmer" qui re -POSTs les données, cela garantit que le chargement spéculatif des URL ne laisse pas les choses se produire (involontairement ou même par malveillance) que l'utilisateur propriétaire du courrier l'adresse n'est pas connue. Le formulaire doit afficher une quantité raisonnable d'informations pour que l'utilisateur sache ce qui se passe et comme dernière chance de déclencher "WTF?" dans le cas où l'utilisateur n'a pas enregistrer ce compte.
    Si vous êtes inquiet pour les robots, le formulaire peut inclure un "Je ne suis pas un robot" si vous le souhaitez (personnellement, je le juge superflu, mais votre kilométrage peut varier).
  4. Une date (ou heure) d'expiration raisonnable. Qu'est-ce qui est raisonnable? Personne ne peut donner une réponse définitive valable pour tous. Je dirais que n'importe quoi de 4 heures à deux jours est probablement bon. Habituellement, lorsque vous vous inscrivez à quelque chose, vous recevez votre e-mail de confirmation dans les 5 à 10 secondes et vous vous asseyez devant l'ordinateur en attendant. Cela peut être plus long si vous utilisez un courrier d'entreprise typique en mode paranoïa qui consacre des minutes à l'analyse de chaque courrier électronique externe. Cependant, vous pourriez recevoir un appel téléphonique ou devoir aller quelque part au milieu de celui-ci, donc avoir le jeton valable pendant quelques heures ou une journée n'est certainement pas une erreur. De plus, le courrier peut être retardé (rare, mais cela arrive).
    D'un autre côté, il est inutile de gaspiller de l'espace disque en conservant des jetons de confirmation (et en bloquant les noms de compte!) Pendant des semaines, des mois ou des années. Non seulement cela consomme des ressources en vain, mais quelqu'un qui ne confirme pas dans un jour ou deux ne le fera probablement jamais, de toute façon. Ou, ils pourraient simplement se réinscrire une autre fois. Ce qui, vraiment, ne coûte rien.
2
Damon

D'après votre question, je prends les hypothèses suivantes et si l'une d'entre elles n'est pas valide, ma réponse l'est également:

  1. l'utilisateur s'inscrit sur votre page Web et définit le nom d'utilisateur/e-mail et le mot de passe lors de l'inscription
  2. la vérification par e-mail a pour but de garantir que l'utilisateur s'est enregistré avec une adresse e-mail correcte.
  3. l'activation du compte est la seule chose que fait le lien e-mail. Il ne permet pas la réinitialisation du mot de passe ou d'autres fonctions de ce type. Il fait essentiellement "UPDATE user SET enabled = true WHERE token =% 1"

Dans ce cas, du point de vue de la sécurité, votre approche est tout à fait correcte. 25 caractères vous donnent suffisamment d'assurance contre les collisions aléatoires et les tentatives de force brute, l'utilisation unique protège contre le reniflement et les attaques similaires et de toute façon la seule chose que quelqu'un pourrait accomplir est d'activer un compte.

Vous voudrez peut-être inclure l'ID utilisateur si vous avez beaucoup d'utilisateurs pour des raisons de performances (MISE À JOUR: pas vraiment, voir les commentaires ci-dessous) La recherche de l'utilisateur par un jeton de chaîne entraînera une analyse de table, tandis que le trouver par ID, puis récupérer et comparer la chaîne est une recherche d'index. Cependant, cela expose l'ID utilisateur, que vous pouvez ou ne souhaitez pas faire.

0
Tom