Alexandre Demelas
Alexandre Demelas

Reputation: 4690

Activator link: Which the best way to design?

I'm using PHP and i know that exists many similar question on this site about this. But i don't found a good incisive explanation about points like:

For now, think that i have only the below options to design a good activator link:

  1. Store a unique token inside users table and two parameters to validate account activation: user identifier and your respective token on database. Could be like this:

    $user->token = bin2hex(openssl_random_pseudo_bytes(16));

    hostname/accountConfirm?user=username&token=userUniqueToken

  2. Using only one parameters as token that have a hashed secret value + user email string. This option would not require any database column to store the token. Something like this:

    $secret = 'some_secret_string';

    $hashedToken = password_hash( $secret . $user->email, PASSWORD_DEFAULT );

    hostname/accountConfirm?token=($hashedToken)

My questions:

Upvotes: 1

Views: 54

Answers (1)

Neil McGuigan
Neil McGuigan

Reputation: 48256

It's riskier to access the database than not access the database, esp with unauthenticated users. You can avoid accessing the database in this step by using a hash-based message authentication code (HMAC). This also slows script-kiddies from trying to fill up your db.

So, I like your second option, but you still need to keep the email address / username around somewhere.

This is what I have used (pseudocode):

$email = '[email protected]';
$expires = current time + 24 hours;
$userIP = getUserIP();

$hmac = hmac_function( $serverSecret, $email + $expires + $userIP );

//correctly escaping query params of course...

$confirmationURL = https://hostname/accountConfirm?email=$email&expires=$expires&ip=$userIP&hmac=$hmac

send URL to $email

in accountConfirm handler:

$email = $_GET['email'];
$expires = $_GET['expires'];
$userIP = $_GET['ip'];
$hmac = $_GET['hmac'];

$expectedHmac = hmac_function( $serverSecret, $email + $expires + $userIP);

if($expectedHmac != $hmac) {
  log 'evil request';
  throw 400 error;
}

//check user ip
//check expiry time
//proceed with registration

If someone messes with the IP, email addy, or expiry time, the HMAC will not match.

Upvotes: 1

Related Questions