What should a verification email consist of?

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP











up vote
10
down vote

favorite
2












Right now I'm generation a 25 character string stored in the database that can only have a 1 time use and expires 30 minutes after user registration.



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


I do a quick database lookup and the logic is as follow:
If the account is not activated AND if the email was not verified AND the validation code is still valid, activate the account, mark the email address as verified and mark the validation code as used.



Every 72 hours for example it would flush expired and used validation codes.
This is in order to tell the user that the activation link clicked has expired for example if he look at his email the day after and try the link.



Should I include the user UUID in the url? Do I need to include something else?



I thought about making sure the IP address on the registration form match the IP address of the request when the activation link is pressed, but for me I mainly read my emails on my cellphone for this kind of stuff so it would be a pain for UX.



EDIT



After reading Daisetsu's answer below, I would also send the user a "cancel" link that would flag the original IP for the system to watch like so:



http://test.com/security/cancelActivation/ZheGgUNUFAbui4QJ48Ubs9Epd









share|improve this question









New contributor




HypeWolf is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.























    up vote
    10
    down vote

    favorite
    2












    Right now I'm generation a 25 character string stored in the database that can only have a 1 time use and expires 30 minutes after user registration.



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


    I do a quick database lookup and the logic is as follow:
    If the account is not activated AND if the email was not verified AND the validation code is still valid, activate the account, mark the email address as verified and mark the validation code as used.



    Every 72 hours for example it would flush expired and used validation codes.
    This is in order to tell the user that the activation link clicked has expired for example if he look at his email the day after and try the link.



    Should I include the user UUID in the url? Do I need to include something else?



    I thought about making sure the IP address on the registration form match the IP address of the request when the activation link is pressed, but for me I mainly read my emails on my cellphone for this kind of stuff so it would be a pain for UX.



    EDIT



    After reading Daisetsu's answer below, I would also send the user a "cancel" link that would flag the original IP for the system to watch like so:



    http://test.com/security/cancelActivation/ZheGgUNUFAbui4QJ48Ubs9Epd









    share|improve this question









    New contributor




    HypeWolf is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
    Check out our Code of Conduct.





















      up vote
      10
      down vote

      favorite
      2









      up vote
      10
      down vote

      favorite
      2






      2





      Right now I'm generation a 25 character string stored in the database that can only have a 1 time use and expires 30 minutes after user registration.



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


      I do a quick database lookup and the logic is as follow:
      If the account is not activated AND if the email was not verified AND the validation code is still valid, activate the account, mark the email address as verified and mark the validation code as used.



      Every 72 hours for example it would flush expired and used validation codes.
      This is in order to tell the user that the activation link clicked has expired for example if he look at his email the day after and try the link.



      Should I include the user UUID in the url? Do I need to include something else?



      I thought about making sure the IP address on the registration form match the IP address of the request when the activation link is pressed, but for me I mainly read my emails on my cellphone for this kind of stuff so it would be a pain for UX.



      EDIT



      After reading Daisetsu's answer below, I would also send the user a "cancel" link that would flag the original IP for the system to watch like so:



      http://test.com/security/cancelActivation/ZheGgUNUFAbui4QJ48Ubs9Epd









      share|improve this question









      New contributor




      HypeWolf is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.











      Right now I'm generation a 25 character string stored in the database that can only have a 1 time use and expires 30 minutes after user registration.



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


      I do a quick database lookup and the logic is as follow:
      If the account is not activated AND if the email was not verified AND the validation code is still valid, activate the account, mark the email address as verified and mark the validation code as used.



      Every 72 hours for example it would flush expired and used validation codes.
      This is in order to tell the user that the activation link clicked has expired for example if he look at his email the day after and try the link.



      Should I include the user UUID in the url? Do I need to include something else?



      I thought about making sure the IP address on the registration form match the IP address of the request when the activation link is pressed, but for me I mainly read my emails on my cellphone for this kind of stuff so it would be a pain for UX.



      EDIT



      After reading Daisetsu's answer below, I would also send the user a "cancel" link that would flag the original IP for the system to watch like so:



      http://test.com/security/cancelActivation/ZheGgUNUFAbui4QJ48Ubs9Epd






      authentication email






      share|improve this question









      New contributor




      HypeWolf is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.











      share|improve this question









      New contributor




      HypeWolf is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.









      share|improve this question




      share|improve this question








      edited 4 mins ago





















      New contributor




      HypeWolf is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.









      asked 6 hours ago









      HypeWolf

      535




      535




      New contributor




      HypeWolf is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.





      New contributor





      HypeWolf is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.






      HypeWolf is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.




















          1 Answer
          1






          active

          oldest

          votes

















          up vote
          12
          down vote



          accepted










          How are you generating the 25 character string which you include in the URL? Is it completely random, or is it based off the current time, or the users email? It should be random and not guessable.



          You should make sure the verification page actually renders (not just that a GET request occurred). Browsers such as chrome (and antivirus programs) often load URLs without the user explicitly clicking them as either a pre-fetch or to scan for security reasons.



          That could result in a scenario where a malicious actor (Eve) wants to make an account using someone else's email (Alice).
          Eve signs up, and Alice received an email. Alice opens the email because she is curious about an account she didn't request. Her browser (or antivirus) requests the URL in the background, inadvertently activating the account.



          I would use JavaScript on the page to verify the page actually rendered, and also include a link in the email where users can report that they did NOT create this account.






          share|improve this answer




















          • Awesome, thank you very much for your insight. The string is indeed generated from crypto.randomBytes function of NodeJS and the application already call a javascript function but not for the reason you stated. This is a thorough answer that highlight things I didn't think of.
            – HypeWolf
            6 hours ago










          Your Answer








          StackExchange.ready(function()
          var channelOptions =
          tags: "".split(" "),
          id: "162"
          ;
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function()
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled)
          StackExchange.using("snippets", function()
          createEditor();
          );

          else
          createEditor();

          );

          function createEditor()
          StackExchange.prepareEditor(
          heartbeatType: 'answer',
          convertImagesToLinks: false,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: null,
          bindNavPrevention: true,
          postfix: "",
          imageUploader:
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          ,
          noCode: true, onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          );



          );






          HypeWolf is a new contributor. Be nice, and check out our Code of Conduct.









           

          draft saved


          draft discarded


















          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fsecurity.stackexchange.com%2fquestions%2f197004%2fwhat-should-a-verification-email-consist-of%23new-answer', 'question_page');

          );

          Post as a guest






























          1 Answer
          1






          active

          oldest

          votes








          1 Answer
          1






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes








          up vote
          12
          down vote



          accepted










          How are you generating the 25 character string which you include in the URL? Is it completely random, or is it based off the current time, or the users email? It should be random and not guessable.



          You should make sure the verification page actually renders (not just that a GET request occurred). Browsers such as chrome (and antivirus programs) often load URLs without the user explicitly clicking them as either a pre-fetch or to scan for security reasons.



          That could result in a scenario where a malicious actor (Eve) wants to make an account using someone else's email (Alice).
          Eve signs up, and Alice received an email. Alice opens the email because she is curious about an account she didn't request. Her browser (or antivirus) requests the URL in the background, inadvertently activating the account.



          I would use JavaScript on the page to verify the page actually rendered, and also include a link in the email where users can report that they did NOT create this account.






          share|improve this answer




















          • Awesome, thank you very much for your insight. The string is indeed generated from crypto.randomBytes function of NodeJS and the application already call a javascript function but not for the reason you stated. This is a thorough answer that highlight things I didn't think of.
            – HypeWolf
            6 hours ago














          up vote
          12
          down vote



          accepted










          How are you generating the 25 character string which you include in the URL? Is it completely random, or is it based off the current time, or the users email? It should be random and not guessable.



          You should make sure the verification page actually renders (not just that a GET request occurred). Browsers such as chrome (and antivirus programs) often load URLs without the user explicitly clicking them as either a pre-fetch or to scan for security reasons.



          That could result in a scenario where a malicious actor (Eve) wants to make an account using someone else's email (Alice).
          Eve signs up, and Alice received an email. Alice opens the email because she is curious about an account she didn't request. Her browser (or antivirus) requests the URL in the background, inadvertently activating the account.



          I would use JavaScript on the page to verify the page actually rendered, and also include a link in the email where users can report that they did NOT create this account.






          share|improve this answer




















          • Awesome, thank you very much for your insight. The string is indeed generated from crypto.randomBytes function of NodeJS and the application already call a javascript function but not for the reason you stated. This is a thorough answer that highlight things I didn't think of.
            – HypeWolf
            6 hours ago












          up vote
          12
          down vote



          accepted







          up vote
          12
          down vote



          accepted






          How are you generating the 25 character string which you include in the URL? Is it completely random, or is it based off the current time, or the users email? It should be random and not guessable.



          You should make sure the verification page actually renders (not just that a GET request occurred). Browsers such as chrome (and antivirus programs) often load URLs without the user explicitly clicking them as either a pre-fetch or to scan for security reasons.



          That could result in a scenario where a malicious actor (Eve) wants to make an account using someone else's email (Alice).
          Eve signs up, and Alice received an email. Alice opens the email because she is curious about an account she didn't request. Her browser (or antivirus) requests the URL in the background, inadvertently activating the account.



          I would use JavaScript on the page to verify the page actually rendered, and also include a link in the email where users can report that they did NOT create this account.






          share|improve this answer












          How are you generating the 25 character string which you include in the URL? Is it completely random, or is it based off the current time, or the users email? It should be random and not guessable.



          You should make sure the verification page actually renders (not just that a GET request occurred). Browsers such as chrome (and antivirus programs) often load URLs without the user explicitly clicking them as either a pre-fetch or to scan for security reasons.



          That could result in a scenario where a malicious actor (Eve) wants to make an account using someone else's email (Alice).
          Eve signs up, and Alice received an email. Alice opens the email because she is curious about an account she didn't request. Her browser (or antivirus) requests the URL in the background, inadvertently activating the account.



          I would use JavaScript on the page to verify the page actually rendered, and also include a link in the email where users can report that they did NOT create this account.







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered 6 hours ago









          Daisetsu

          3,114619




          3,114619











          • Awesome, thank you very much for your insight. The string is indeed generated from crypto.randomBytes function of NodeJS and the application already call a javascript function but not for the reason you stated. This is a thorough answer that highlight things I didn't think of.
            – HypeWolf
            6 hours ago
















          • Awesome, thank you very much for your insight. The string is indeed generated from crypto.randomBytes function of NodeJS and the application already call a javascript function but not for the reason you stated. This is a thorough answer that highlight things I didn't think of.
            – HypeWolf
            6 hours ago















          Awesome, thank you very much for your insight. The string is indeed generated from crypto.randomBytes function of NodeJS and the application already call a javascript function but not for the reason you stated. This is a thorough answer that highlight things I didn't think of.
          – HypeWolf
          6 hours ago




          Awesome, thank you very much for your insight. The string is indeed generated from crypto.randomBytes function of NodeJS and the application already call a javascript function but not for the reason you stated. This is a thorough answer that highlight things I didn't think of.
          – HypeWolf
          6 hours ago










          HypeWolf is a new contributor. Be nice, and check out our Code of Conduct.









           

          draft saved


          draft discarded


















          HypeWolf is a new contributor. Be nice, and check out our Code of Conduct.












          HypeWolf is a new contributor. Be nice, and check out our Code of Conduct.











          HypeWolf is a new contributor. Be nice, and check out our Code of Conduct.













           


          draft saved


          draft discarded














          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fsecurity.stackexchange.com%2fquestions%2f197004%2fwhat-should-a-verification-email-consist-of%23new-answer', 'question_page');

          );

          Post as a guest













































































          Comments

          Popular posts from this blog

          Long meetings (6-7 hours a day): Being “babysat” by supervisor

          Is the Concept of Multiple Fantasy Races Scientifically Flawed? [closed]

          Confectionery