emc
emc

Reputation: 333

What part does the "token" play in password reset?

I'm using laravel's Auth password reset method and not sure i fully understand what part plays the token in all of this.

  1. I'm sending the user an email with Password::remind('[email protected]') , which generates a token in my password_reminders table. The token is fully visible in the url.

  2. The user goes to a url that looks something like: mywebsite.com/remindpass/xxxxxx[token] .

  3. Then he fills out a form with his email and a new password , sending it trough post to a controller - which uses Password::reset('email','password','xxxxxx') .

The question is how is this secure? What does the generated token do to prevent someone just going to mywebsite.com/remindpass/xxxxxx[token] and change the email & password as he likes?

Can someone please clarify the proccess?

Upvotes: 2

Views: 228

Answers (2)

Quentin
Quentin

Reputation: 944546

What does the generated token do to prevent someone just going to mywebsite.com/remindpass/xxxxxx[token] and change the email & password as he likes?

Because only you and the person you sent the email to (i.e. the account holder) know what the token is.

A strong implementation will takes steps to make it hard to guess tokens:

  • Long (harder to guess) tokens
  • Time limited tokens
  • IP based rate limiting for access to /remindpass/*

Upvotes: 1

Chris Schmitz
Chris Schmitz

Reputation: 20980

I'm sure someone could answer this question better than I could.

Short answer:

The token makes it more difficult for someone to guess the credentials needed to reset the password while making the reset link in the email available.

Long answer:

In the file vendor/laravel/framework/src/Illuminate/Auth/Guard.php, you'll see the method createRememberTokenIfDoesntExist. This method actually references another method right above it called refreshRememberToken to set your token.

It uses the laravel helper function str_random. If you trace this function back to it's source, you'll find it uses the vendor/laravel/framework/src/Illuminate/Support/Str.php class' random method.

public static function random($length = 16)
{
    if (function_exists('openssl_random_pseudo_bytes'))
    {
        $bytes = openssl_random_pseudo_bytes($length * 2);

        if ($bytes === false)
        {
            throw new \RuntimeException('Unable to generate random string.');
        }

        return substr(str_replace(array('/', '+', '='), '', base64_encode($bytes)), 0, $length);
    }

    return static::quickRandom($length);
}

Now we finally get down to where the token is built. This method uses the function openssl_random_pseudo_bytesto generate the token. You can read about that function in the PHP manual page for openssl_random_pseudo_bytes, but basically it generates a cryptographically strong random string.

Laravel then takes this string (still in the random method), base 64 encodes it, replaces some characters, and takes a slice of that string based on either the default setting of 16 (seen in the parameter definition $length = 16) or whatever length is passed into the method by the caller.

So, you get a string that is cryptographically strong and then manipulated as your token.

If you look at the file vendor/laravel/framework/src/Illuminate/Auth/DatabaseUserProvider.php and find the method retrieveByToken, you'll see that laravel uses both the user record ID and the token to find the user who's password needs to change.

For someone to guess that string AND the id of you user record that has that token would be incredibly difficult and would require knowledge of your application's business logic.

Upvotes: 3

Related Questions