Email verification on Account registration
In this article, we will cover on how to verify user’s email and activate the user account once they click on the account activation link sent in the email.
So let's start...
$verifyUser = VerifyUser::create([
'user_id' => $user->id,
'token' => str_random(60)
]);
Mail::to($user->email)->send(new VerifyMail($user));
return $user;
}
Don't forget to import the required classes at the top of the file. i.e,
use Mail;
use App\User;
use App\VerifyUser;
use App\Mail\VerifyMail;
So let's start...
Step 1: Create new Model and Migration for verification
We will be creating a new table in our database which will hold the verification token that is appended in the URL and sent to the users. Let’s begin by generating the required Model and Migration file.
php artisan make:model VerifyUser -m
The make:model command will create a new Model VerifyUser in the \App directory and -m flag will create a new migration file associated with the VerifyUser model with the table name verify_users.
Now we can modify our verify_users migration file like this.
public function up()
{
Schema::create('verify_users', function (Blueprint $table) {
$table->integer('user_id');
$table->string('token');
$table->timestamps();
});
}
php artisan make:model VerifyUser -m
The make:model command will create a new Model VerifyUser in the \App directory and -m flag will create a new migration file associated with the VerifyUser model with the table name verify_users.
Now we can modify our verify_users migration file like this.
public function up()
{
Schema::create('verify_users', function (Blueprint $table) {
$table->integer('user_id');
$table->string('token');
$table->timestamps();
});
}
Also, modify the migration file for the user's table to include a new boolean field to maintain the status of account verification.
$table->boolean('verified')->default(false);
Once that's done don't forget to migrate. run php artisan migrate
$table->boolean('verified')->default(false);
Once that's done don't forget to migrate. run php artisan migrate
Step 2: Setup the relation between models
We can start with the User model. Add the following function to your User model.
public function verifyUser()
{
return $this->hasOne('App\VerifyUser');
}
And also update the $fillable property. Add ['verified']
Now for the VerifyUser model
And also update the $fillable property. Add ['verified']
Now for the VerifyUser model
class VerifyUser extends Model
{
protected $fillable = ['user_id', 'token'];
public function user()
{
return $this->belongsTo('App\User', 'user_id');
}
}
Step 3: Create a mailable class for sending mail
In Laravel all the emails sent by your application must be defined by a Mailable class. To generate one such class for our verify user’s email on registration. Let’s generate a class with artisan command. Run the given below command in your project root.
php artisan make:mail VerifyMail
This will create a new class under \App\Mail folder. Now edit it like this
<?php
namespace App\Mail;
use App\User;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Contracts\Queue\ShouldQueue;
class VerifyMail extends Mailable
{
use Queueable, SerializesModels;
public $user;
/**
* Create a new message instance.
*
* @return void
*/
public function __construct(User $user)
{
$this->user = $user;
}
/**
* Build the message.
*
* @return $this
*/
public function build()
{
return $this->markdown('emails.verifyUser');
}
}
We have modified the name of view files as emails.welcome. We will create a emails folder under resources/views in which we will keep our email views. Also as you can see we have declared the $user as public and we are setting the variable in the constructor.
Whatever variables are declared as public is by default available in the view file. Thus we can directly refer to the $user variable to get the user-related data directly in the view file.
Let’s go ahead and create the view file to send a verification email. Create a new file verifyUser.blade.php under resources/views/emails and put following contents into it.
@component('mail::message')
## Hello {{ $user['user_name'] }},
Your account has been successfully registered. Please click the below link to verify your email address. Your registered email-id is {{ $user['email'] }}.
@component('mail::button', ['url' => url('user/verify', $user->verifyUser->token)])
Verify Email
@endcomponent
Regards,<br>
{{ config('app.name') }}
<hr />
<small>
If you’re having trouble clicking the "Verify Email" button, copy and paste the URL below into your web browser:
[{{ url('user/verify', $user->verifyUser->token) }}]({{ url('user/verify', $user->verifyUser->token) }})
</small>
@endcomponent
php artisan make:mail VerifyMail
This will create a new class under \App\Mail folder. Now edit it like this
<?php
namespace App\Mail;
use App\User;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Contracts\Queue\ShouldQueue;
class VerifyMail extends Mailable
{
use Queueable, SerializesModels;
public $user;
/**
* Create a new message instance.
*
* @return void
*/
public function __construct(User $user)
{
$this->user = $user;
}
/**
* Build the message.
*
* @return $this
*/
public function build()
{
return $this->markdown('emails.verifyUser');
}
}
We have modified the name of view files as emails.welcome. We will create a emails folder under resources/views in which we will keep our email views. Also as you can see we have declared the $user as public and we are setting the variable in the constructor.
Whatever variables are declared as public is by default available in the view file. Thus we can directly refer to the $user variable to get the user-related data directly in the view file.
Let’s go ahead and create the view file to send a verification email. Create a new file verifyUser.blade.php under resources/views/emails and put following contents into it.
@component('mail::message')
## Hello {{ $user['user_name'] }},
Your account has been successfully registered. Please click the below link to verify your email address. Your registered email-id is {{ $user['email'] }}.
@component('mail::button', ['url' => url('user/verify', $user->verifyUser->token)])
Verify Email
@endcomponent
Regards,<br>
{{ config('app.name') }}
<hr />
<small>
If you’re having trouble clicking the "Verify Email" button, copy and paste the URL below into your web browser:
[{{ url('user/verify', $user->verifyUser->token) }}]({{ url('user/verify', $user->verifyUser->token) }})
</small>
@endcomponent
Step 4: Sending email
Now we can modify the create function in RegisterController.php file inside App\Http\Controllers\Auth
protected function create(array $data)
{
protected function create(array $data)
{
$user = User::create([
'name' => $data['name'],
'email' => $data['email'],
'password' => bcrypt($data['password']),
]);
'name' => $data['name'],
'email' => $data['email'],
'password' => bcrypt($data['password']),
]);
$verifyUser = VerifyUser::create([
'user_id' => $user->id,
'token' => str_random(60)
]);
Mail::to($user->email)->send(new VerifyMail($user));
return $user;
}
Don't forget to import the required classes at the top of the file. i.e,
use Mail;
use App\User;
use App\VerifyUser;
use App\Mail\VerifyMail;
Step 5: Verify User Functionality
We can start by creating a new route
Route::get('/user/verify/{token}', 'Auth\RegisterController@verifyUser');
Since the functionality is related to User Registration we will create a new method verifyUser in RegisterController.php
public function verifyUser($token)
{
$verifyUser = VerifyUser::where('token', $token)->first();
if (isset($verifyUser)) {
$user = $verifyUser->user;
if (isset($user)) {
if (!$user->verified) {
$verifyUser->user->verified = 1;
$verifyUser->user->save();
$status = "Your e-mail is verified. You can now login.";
} else {
$status = "Your e-mail is already verified. You can now login.";
}
} else {
return redirect('/login')->with('warning', "Oops! Something happend.");
}
} else {
return redirect('/login')->with('warning', "Sorry your email cannot be identified.");
}
return redirect('/login')->with('status', $status);
}
Since the functionality is related to User Registration we will create a new method verifyUser in RegisterController.php
public function verifyUser($token)
{
$verifyUser = VerifyUser::where('token', $token)->first();
if (isset($verifyUser)) {
$user = $verifyUser->user;
if (isset($user)) {
if (!$user->verified) {
$verifyUser->user->verified = 1;
$verifyUser->user->save();
$status = "Your e-mail is verified. You can now login.";
} else {
$status = "Your e-mail is already verified. You can now login.";
}
} else {
return redirect('/login')->with('warning', "Oops! Something happend.");
}
} else {
return redirect('/login')->with('warning', "Sorry your email cannot be identified.");
}
return redirect('/login')->with('status', $status);
}
Step 6: Restricting Un-Verified User Access
Modify LoginController.php and override the authenticated method from AuthenticatesUsers
public function authenticated(Request $request, $user)
{
if (!$user->verified) {
auth()->logout();
return back()->with('warning', 'You need to confirm your account. We have sent you an activation code, please check your email.');
}
return redirect()->intended($this->redirectPath());
}
The authenticated method is executed just after the user is authenticated. We will override this and will use this to check if the user is activated. If not we will sign-out the user and send back to login page with a warning message.
Modify RegisterController.php and override the registered method from RegistersUsers
protected function registered(Request $request, $user)
{
$this->guard()->logout();
return redirect('/login')->with('status', 'We sent you an activation code. Check your email and click on the link to verify.');
}
The registered method is executed just after the user is registered into the application, we will override and modify this to sign-out the user and send him back to login with a status message.
Last we need to modify our login.blade.php file which is located under resources/views/auth. Add the following snippet to display the appropriate status messages.
@if (session('status'))
<div class="alert alert-success">
{{ session('status') }}
</div>
@endif
@if (session('warning'))
<div class="alert alert-warning">
{{ session('warning') }}
</div>
@endif
Also, don't forget to support my channel by subscribing to it. Click the bell icon for not missing any of my future videos.
public function authenticated(Request $request, $user)
{
if (!$user->verified) {
auth()->logout();
return back()->with('warning', 'You need to confirm your account. We have sent you an activation code, please check your email.');
}
return redirect()->intended($this->redirectPath());
}
The authenticated method is executed just after the user is authenticated. We will override this and will use this to check if the user is activated. If not we will sign-out the user and send back to login page with a warning message.
Modify RegisterController.php and override the registered method from RegistersUsers
protected function registered(Request $request, $user)
{
$this->guard()->logout();
return redirect('/login')->with('status', 'We sent you an activation code. Check your email and click on the link to verify.');
}
The registered method is executed just after the user is registered into the application, we will override and modify this to sign-out the user and send him back to login with a status message.
Last we need to modify our login.blade.php file which is located under resources/views/auth. Add the following snippet to display the appropriate status messages.
@if (session('status'))
<div class="alert alert-success">
{{ session('status') }}
</div>
@endif
@if (session('warning'))
<div class="alert alert-warning">
{{ session('warning') }}
</div>
@endif
Also, don't forget to support my channel by subscribing to it. Click the bell icon for not missing any of my future videos.
Comments
Post a Comment