There are lots of packages available to authenticate the APIs request in Laravel. Such as Passport, JWT, and Sanctum. We are already familiar with Laravel Passport and JWT (JSON Web Token) to authenticate the APIs. Sanctum is introduced in Laravel 7 and really this is also a secured package. The Sanctum provides the authentication for the SPA (Single Page Application), mobile application, and the token-based APIs. In this post, we will be creating the Laravel 8 Sanctum auth for the token-based APIs. I have already shared the tutorial for creating RESTful APIs using Passport Authentication. The main difference between passport and sanctum is passport usage OAuth for the authentication. But, Sanctum generates the API tokens without the complication of OAuth.
Prerequisites
Before creating this Laravel 8 Sanctum auth project, you will require to have the following tools.
- PHP >= 7.3
- MySQL (version > 5)
- Apache/Nginx Server
- VS Code Editor
- Composer
- Postman/Insomnia
Create Project For Laravel 8 Sanctum Auth APIs
We will be creating the Laravel 8 project using the composer. You can use the Laravel installer as well. So, open the terminal and hit the below command.
composer create-project --prefer-dist laravel/laravel sanctum-api
The above command will create a folder and start the installation.
It will take a couple of minutes, so after finishing the installation let’s move to the next step.
How to Upload Image in CKEditor 5 Using Laravel 8
Create and Configure a Database
For managing the data, I will create a database in the MySQL. So, here, I am creating a new database.
CREATE DATABASE laravel_sanctum;
Here, I have created the database. Now, let’s establish the connection with the Laravel 8 project.
Hence, open the project and navigate to the .env file. Then replace the database credentials as showing below.
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel_sanctum
DB_USERNAME=root
DB_PASSWORD=root
Now, we have connected the database with the project successfully. In the next step, we will install the Sanctum auth package.
Install Laravel 8 Sanctum Authentication
Here, we will install a package for the Sanctum auth. So, inside the project directory open the terminal. Then install it by hitting the below command.
composer require laravel/sanctum
Here, the package has ben installed.
You can check the composer.json file for the package.
How to Implement CKEditor 5 in Laravel 8 From Scratch
Publish Sanctum Configuration
After installing the package, we will have to register the sanctum provider. So, we can do it by publishing it’s configuration using the vendor publish.
php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"
Here, the publishing has been completed.
After publishing the sanctum configuration, we will create the models and migrations.
Add Models and Migrations
Here, we will create the RESTful APIs with authentication. So, for creating the auth token, we will have to login. After a successful login, the sanctum auth will generate the authentication token. Therefore, we will create the APIs for the user sign up, login, and the token-based APIs for the todo.
For the User module, we have the default Model and migration. Hence, we will require to create a model for the Task.
php artisan make:model Task -m
The above command created a Task model and migration.
In the next step, we will set up the fields in the migrations. So, we have two migrations one for the user and another for the task.
Hence, let’s add the fields in each migration one by one.
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('email')->unique();
$table->string('phone');
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
}
Similarly, we will add the fields for the task migration.
public function up()
{
Schema::create('tasks', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->string('description');
$table->bigInteger('user_id');
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
$table->timestamps();
});
}
After setting up the fields in the migrations, we will add the fillable data in the Models.
How to Create Pagination in Laravel 8 with Eloquent
Add Mass Assignment For the Models
The User module will have the login and token authentication. That’s why we will have to use the Authenticable and API token. Here, we are using the Sanctum auth API, so, we will import the namespace for the sanctum.
use Laravel\Sanctum\HasApiTokens;
Also, we will have to use the HasApiTokens inside the class. So, this will be the final snippet in the User.php file.
<?php
namespace App\Models;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;
class User extends Authenticatable
{
use HasApiTokens, HasFactory, Notifiable;
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'name',
'email',
'phone',
'password',
];
/**
* The attributes that should be hidden for arrays.
*
* @var array
*/
protected $hidden = [
'password',
'remember_token',
];
/**
* The attributes that should be cast to native types.
*
* @var array
*/
protected $casts = [
'email_verified_at' => 'datetime',
];
public function task()
{
return $this->hasMany('App\Models\Task');
}
}
Similarly, add the fillable data in the Task.php file.
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Task extends Model
{
use HasFactory;
protected $fillable = [
'user_id', 'title', 'description'
];
}
After adding the fillable data in the models, we will have to migrate the tables.
php artisan migrate
In the migration, you will see the Laravel Sanctum Auth API added only one table to manage the tokens. The table is personal_access_tokens_table.
So, the tables are created in the database. Now, we will have to set the guard as a Sanctum.
How to Use Guzzle Http in Laravel 8 For Request Handling
Add Sanctum Authentication Guard
When we’ll set the sanctum auth middleware, every API request will check the auth token. So, we will have to set the driver for the API request in the guards. In the below snippet, I have added the sanctum driver for the API.
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'sanctum',
'provider' => 'users',
'hash' => false,
],
],
Now, that’s it for the configuration. In the next step, we will create the controllers and write the logic.
How to Create and Use Database Seeder in Laravel 8
Create Controllers
As per our application, we will create two controllers. One for the User and another for the Task. So, let’s create them one by one.
php artisan make:controller UserController
and
php artisan make:controller TaskController --resource
Here, the controllers are created. I have used the resource for the task controller so that we will have the predefined methods for the CRUD.
In the next step, we will add the functionality for the user sign up, login and the user detail. So, add the below snippet in the UserController.php.
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Facades\Auth;
use App\Models\User;
class UserController extends Controller
{
// User Register
public function register(Request $request) {
$validator = Validator::make($request->all(), [
"name" => "required",
"email" => "required|email",
"phone" => "required",
"password" => "required"
]);
if($validator->fails()) {
return response()->json(["status" => "failed", "validation_errors" => $validator->errors()]);
}
$inputs = $request->all();
$inputs["password"] = Hash::make($request->password);
$user = User::create($inputs);
if(!is_null($user)) {
return response()->json(["status" => "success", "message" => "Success! registration completed", "data" => $user]);
}
else {
return response()->json(["status" => "failed", "message" => "Registration failed!"]);
}
}
// User login
public function login(Request $request) {
$validator = Validator::make($request->all(), [
"email" => "required|email",
"password" => "required",
]);
if($validator->fails()) {
return response()->json(["validation_errors" => $validator->errors()]);
}
$user = User::where("email", $request->email)->first();
if(is_null($user)) {
return response()->json(["status" => "failed", "message" => "Failed! email not found"]);
}
if(Auth::attempt(['email' => $request->email, 'password' => $request->password])){
$user = Auth::user();
$token = $user->createToken('token')->plainTextToken;
return response()->json(["status" => "success", "login" => true, "token" => $token, "data" => $user]);
}
else {
return response()->json(["status" => "failed", "success" => false, "message" => "Whoops! invalid password"]);
}
}
// User Detail
public function user() {
$user = Auth::user();
if(!is_null($user)) {
return response()->json(["status" => "success", "data" => $user]);
}
else {
return response()->json(["status" => "failed", "message" => "Whoops! no user found"]);
}
}
}
In the above controller, I have added the functions for user registration, login and user detail.
In the next step, we will add the functionalities for managing task. Hence, add the below snippet in the TaskController.php.
<?php
namespace App\Http\Controllers;
use App\Models\Task;
use Illuminate\Support\Facades\Validator;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class TaskController extends Controller
{
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index()
{
// check logged user
$user = Auth::user();
if(!is_null($user)) {
$tasks = Task::where("user_id", $user->id)->get();
if(count($tasks) > 0) {
return response()->json(["status" => "success", "count" => count($tasks), "data" => $tasks], 200);
}
else {
return response()->json(["status" => "failed", "count" => count($tasks), "message" => "Failed! no task found"], 200);
}
}
}
/**
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(Request $request) {
// check logged user
$user = Auth::user();
if(!is_null($user)) {
// create task
$validator = Validator::make($request->all(), [
"title" => "required",
"description" => "required"
]);
if($validator->fails()) {
return response()->json(["status" => "failed", "validation_errors" => $validator->errors()]);
}
$taskInput = $request->all();
$taskInput['user_id'] = $user->id;
$task = Task::create($taskInput);
if(!is_null($task)) {
return response()->json(["status" => "success", "message" => "Success! task created", "data" => $task]);
}
else {
return response()->json(["status" => "failed", "message" => "Whoops! task not created"]);
}
}
}
/**
* Display the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function show($id)
{
$user = Auth::user();
if(!is_null($user)) {
$task = Task::where("user_id", $user->id)->where("id", $id)->first();
if(!is_null($task)) {
return response()->json(["status" => "success", "data" => $task], 200);
}
else {
return response()->json(["status" => "failed", "message" => "Failed! no task found"], 200);
}
}
else {
return response()->json(["status" => "failed", "message" => "Un-authorized user"], 403);
}
}
/**
* Update the specified resource in storage.
*
* @param \Illuminate\Http\Request $request
* @param int $id
* @return \Illuminate\Http\Response
*/
public function update(Request $request, Task $task)
{
$input = $request->all();
$user = Auth::user();
if(!is_null($user)) {
// validation
$validator = Validator::make($request->all(), [
"title" => "required",
"description" => "required",
]);
if($validator->fails()) {
return response()->json(["status" => "failed", "validation_errors" => $validator->errors()]);
}
// update post
$update = $task->update($request->all());
return response()->json(["status" => "success", "message" => "Success! task updated", "data" => $task], 200);
}
else {
return response()->json(["status" => "failed", "message" => "Un-authorized user"], 403);
}
}
/**
* Remove the specified resource from storage.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function destroy(Task $task)
{
$user = Auth::user();
if(!is_null($user)) {
$task = Task::where("id", $task)->where("user_id", $user->id)->delete();
return response()->json(["status" => "success", "message" => "Success! task deleted"], 200);
}
else {
return response()->json(["status" => "failed", "message" => "Un-authorized user"], 403);
}
}
}
Here, we have added the functionalities for the User and Task. In the next step, we will have to add the routes for the both controllers functions.
How to Implement Yajra DataTables in Laravel 8
Add Routes
We are creating RESTful APIs using Laravel Sanctum. Therefore, we will have to add the routes in the api.php file.
<?php
use App\Http\Controllers\TaskController;
use App\Http\Controllers\UserController;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
// user controller routes
Route::post("register", [UserController::class, "register"]);
Route::post("login", [UserController::class, "login"]);
// sanctum auth middleware routes
Route::middleware('auth:api')->group(function() {
Route::get("user", [UserController::class, "user"]);
Route::resource('tasks', TaskController::class);
});
I have used the route group for managing the task by the logged user. So, the route put inside the middleware will require the auth token.
Now, we will be testing the APIs endpoint. For APIs testing, I will be using Insomnia.
Test APIs Result
We will check the APIs endpoint one by one. Firstly, start with the user module.
1. User Sign Up
In the user sign up, we will have the below endpoint. The request type will be POST.
EndPoint: http://localhost:8000/api/register
RequestType: POST
After hitting the API without any inputs, it will ask for the required fields.
Now, I will enter the required fields.
Now, try again to register. In the response, you will have the success result with user detail.
Here, user registration has completed. Now, will check the next endpoint that is login.
How to Implement Yajra DataTables in Laravel 8
2. User Login
Similarly, the user login endpoint will have the POST request type.
EndPoint: http://localhost:8000/api/login
RequestType: POST
So, firstly, I will try hitting the API without any inputs.
Here, we have the validation errors message.
Now, try login with incorrect email that is not registered. In the response, you will get the below result.
Let’s try with the wrong password. Here, I have entered the correct email but the password is incorrect. As the result, we have the message of an incorrect password.
Lastly, we will try with the correct email and password. In the result, we have the success response along with the token and user data.
So, finally, we got the auth token after the logged in. Here, you will notice, the token size is small than the passport auth token.
3. User Detail
For getting the user data, we have the below endpoint. But, this endpoint will require the auth token in the header.
EndPoint: http://localhost:8000/api/user
RequestType: GET
Header
Authorization: Bearer AuthToken
Hit the endpoint to get the result. Here, you will get the user detail in the response.
Finally, the user’s endpoint have completed. Now, we will use the same approach with auth token for managing the tasks.
3. Create Task
For creating the task, we have the below endpoint.
EndPoint: http://localhost:8000/api/tasks
RequestType: POST
Header
Authorization: Bearer AuthToken
Here, I have hit the API without any inputs. But, passed the auth token in the header.
So, now, I have entered the required fields that is title and description.
Now, try hitting again the endpoint. This time, you will get the success response as showing below.
Now, we have created the task. So, let’s list out the task using the next endpoint.
4. Fetch Tasks
For listing out the tasks, we will check the logged user. It will list out all tasks created by the current logged user only. Because, you can not get the detail of task created by someone else.
EndPoint: http://localhost:8000/api/tasks
RequestType: GET
Header
Authorization: Bearer AuthToken
After hitting the API, you will get the below response. Here, you will to pass the auth token in the header.
In the next endpoint, we will get the task detail through the task id.
5. Task Detail
The endpoint will require a parameter as a task id. Also, will require to pass the auth token in the header.
EndPoint: http://localhost:8000/api/tasks/{taskId}
RequestType: GET
Header
Authorization: Bearer AuthToken
Here, we got the task of entered task id.
In the next endpoint, we will update the task.
6. Update Task
For updating the task, we will use the PUT method. Here, is the endpoint.
EndPoint: http://localhost:8000/api/tasks/{taskId}
RequestType: PUT
Header
Authorization: Bearer AuthToken
Content-Type: application/x-www-form-urlencoded
Here, I have used the PUT method to update the task. For the input, you can pass the key value in the param. In that case, you will not require to pass the Content-Type.
In the header, I have passed the auth token and content type. Then changed the content in the input.
After that, I have hit the API and in the response I got the success. Here, the task has updated.
After updating the task. The final endpoint will be to delete a task.
7. Delete Task
For deleting a task, we have the below endpoint. This endpoint will take auth token in the header.
EndPoint: http://localhost:8000/api/tasks/{taskId}
RequestType: DELETE
Header
Authorization: Bearer AuthToken
Hit the above endpoint to get the result. Here, I got the success result and the task is deleted successfully.
Conclusion
Finally, we have created the RESTful API in Laravel 8 using Sanctum Auth. The sanctum auth api token is small in the size and easy to implement. You can use any of these API authentication package in Laravel. This Laravel 8 Sanctum Auth API can be used to implement in your real projects. So, I hope, you will find it helpful. For any kind of issue or suggestion don’t forget to write me through the comment section. I would love to hear from you with your queries. Thank you.
Cesare says
Hey! First of all, thanks for awesome tutorial you’ve created. Each line of code is explained very well, you know, find a complete tutorial on web isn’t that easy 😅
Anyway, could you implement the password reset feature using Sanctum? It would be great 😉
Thanks again! Bye,
Cesare.
Umesh Rana says
Hi Cesare,
Thank you very much for your appreciation for this tutorial.
Yes, I will implement the password reset feature using Sanctum in my upcoming tutorial.