Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I generate a unique token (for e-mail verification)?

Tags:

random

go

I want to implement a system that after user signs up, user will receive an email includes a link to verify this email is for that user.

The way I generate the token for verifying the email is like this:

import (
    "crypto/rand"
    "encoding/base64"
)

func generateToken() (string, error) {
    b := make([]byte, 35)
    _, err := rand.Read(b)
    if err != nil {
        return "", err
    }
    return base64.URLEncoding.EncodeToString(b), nil
}

But what I want to ask is if this method is OK? How to make all the token generated by this method is unique ?

What is the normal way to implement this system ?

Please give me some ideas and tell me if this method of generating token is good.

Thanks.

like image 845
user3087000 Avatar asked Jan 22 '16 12:01

user3087000


People also ask

How do I find my email verification code?

Sign in to your email to verify your account While you're creating your account, you'll get an email from Google. Open the email and find the verification code.

How can I get email verification code in PHP?

$mail->Subject = 'Email verification'; $mail->Body = 'Please click this button to verify your account: <a href=http://localhost/verification/verify.php?code='.$code.'>Verify</a>' ; $mail->send(); echo 'Message has been sent';


2 Answers

Check out https://pkg.go.dev/github.com/google/uuid#NewRandom.

And you may want to consider storing this in a database with the email address and perhaps an expiry date / time so that the verification doesn't stay there forever. You may only want to allow people to verify within 24 hours, or 7 days and so on. Have another job that periodically cleans expired and non-verified emails.

like image 59
smcstewart Avatar answered Oct 27 '22 11:10

smcstewart


Two points:

  • No, the method as presented won't guarantee them to be unique.
  • You don't need to have all your tokens to be unique.

To expand on these points…

You're dealing with a set of outstanding verification requests. That is:

  1. A request is made by the user;
  2. You generate a unique verification token and store it into some presistent database. This is needed in order for verification to work anyway.
  3. The user receives your e-mail and clicks that link from it which contain your token. At this point you remove the information about this pending verificaton request from your persistent storage.

As you can see, at any given time you only have several outstanding verification requests. Hence this situation has two important properties:

  • You only need the tokens of these outstanding requests be different from one another. It's OK to have a verification token to be the same as that of some past (or future) request.
  • Your tokens have to be hard-to-guess (obviously). I'm sure you already understand that.

So, the approach to generating a new token is as follows:

  1. Generate something hard-to-guess.

  2. Compare it with the tokens bound to the outstanding/pending verification requests persisted in your storage.

    If you find an outstanding request with the same token, you have a collision so go to step (1) and repeat.

    Otherwise the token is OK so proceed with it and persist the data about this request.

  3. Once the request passed verification, remove it from your storage.

Exact algorythm for generating tokens does not matter much. I'd say an UUID or something looking like SHA-256/512 calculated over some random data is OK.

like image 21
kostix Avatar answered Oct 27 '22 09:10

kostix