Laravel 5.2 Email Verification with Activation Code

You can do this on two ways:

  • not allow to login at all
  • allow with reduced access

I will cover the first case.

In this example I will add mail confirmation on top of the Laravel’s default auth scaffolding. It can be applied even if you already have working application.

If starting from scratch create a new laravel project and do the basic auth scaffold.

php artisan make:auth

Create a table which will hold all activation codes.

php artisan make:migration create_user_activations_table --create=user_activations

With these columns

Schema::create('user_activations', function (Blueprint $table) { $table->integer('user_id')->unsigned(); $table->string('token')->index(); $table->timestamp('created_at'); });

Add one more column to the users table (create new migration or add it to the existing one

$table->boolean('activated')->default(false);

And start migrations

php artisan migrate

Next, we need ActivationRepository which will handle activation codes in database. Method getToken is taken from Illuminate/Auth/Passwords/DatabaseTokenRepository class. Other methods will be used in ActivationService.

namespace App; use Carbon\Carbon; use Illuminate\Database\Connection; class ActivationRepository { protected $db; protected $table = 'user_activations'; public function __construct(Connection $db) { $this->db = $db; } protected function getToken() { return hash_hmac('sha256', str_random(40), config('app.key')); } public function createActivation($user) { $activation = $this->getActivation($user); if (!$activation) { return $this->createToken($user); } return $this->regenerateToken($user); } private function regenerateToken($user) { $token = $this->getToken(); $this->db->table($table)->where('user_id', $user->id)->update([ 'token' => $token, 'created_at' => new Carbon() ]); return $token; } private function createToken($user) { $token = $this->getToken(); $this->db->table($this->table)->insert([ 'user_id' => $user->id, 'token' => $token, 'created_at' => new Carbon() ]); return $token; } public function getActivation($user) { return $this->db->table($this->table)->where('user_id', $user->id)->first(); } public function getActivationByToken($token) { return $this->db->table($this->table)->where('token', $token)->first(); } public function deleteActivation($token) { $this->db->table($this->table)->where('token', $token)->delete(); } }

Now define route to handle request when user clicks on the activation link. Add to routes.php

Route::get('user/activation/{token}', 'Auth\AuthController@activateUser')->name('user.activate');

It is best to put it under the Route::auth().

Now ActivationService which will wrap logic for creating activation codes and sending emails. Two main methods are sendActivationMail and activateUser which are self explanatory.

Method shouldSend is checking if email is already sent, or it is sent recently. Property $resendAfter is number of hours that needs to pass before we send a now activation email but only if user request it. You will probably want to change default email sending function to use html template. Replace ->raw with ->send.

namespace App; use Illuminate\Mail\Mailer; use Illuminate\Mail\Message; class ActivationService { protected $mailer; protected $activationRepo; protected $resendAfter = 24; public function __construct(Mailer $mailer, ActivationRepository $activationRepo) { $this->mailer = $mailer; $this->activationRepo = $activationRepo; } public function sendActivationMail($user) { if ($user->activated || !$this->shouldSend($user)) { return; } $token = $this->activationRepo->createActivation($user); $link = route('user.activate', $token); $message = sprintf('Activate account %s', $link, $link); $this->mailer->raw($message, function (Message $m) use ($user) { $m->to($user->email)->subject('Activation mail'); }); } public function activateUser($token) { $activation = $this->activationRepo->getActivationByToken($token); if ($activation === null) { return null; } $user = User::find($activation->user_id); $user->activated = true; $user->save(); $this->activationRepo->deleteActivation($token); return $user; } private function shouldSend($user) { $activation = $this->activationRepo->getActivation($user); return $activation === null || strtotime($activation->created_at) + 60 * 60 * $this->resendAfter

AuthController


Originally published at www.laravelfeed.com.

One clap, two clap, three clap, forty?

By clapping more or less, you can signal to us which stories really stand out.