Laravel 11 using Sanctum REST API Authentication Tutorial
In Laravel 11, the Sanctum Auth package allows users to create a login, and register REST API by token-based authentication.
Let’s start installing and configuring Passport auth to create token-based authentication:
Prerequisites:
* Git: Git is a version control system that tracks source code changes during software development. Make sure Git is installed on your system. You can download Git from https://git-scm.com/ and follow the installation instructions for your operating system.
* PHP: Laravel requires PHP to be installed on your system. You need PHP version 7.3 or higher. You can check your PHP version by running php -v in your terminal.
* Composer: Composer is a dependency manager for PHP and is used to install Laravel and its dependencies. You can download Composer from https://getcomposer.org/ and follow the installation instructions for your operating system.
* Web Server: You'll need a web server to serve your Laravel application. While Laravel comes with a built-in development server, it's recommended that Apache or Nginx be used for production deployments.
* Database: If the cloned project uses a database, make sure you have the required database management system (e.g., MySQL, PostgreSQL, SQLite) installed on your system.
* Postman: is an API platform for building and using APIs. Postman simplifies each step of the API lifecycle and streamlines collaboration so you can create better APIs faster. Can download https://postman.com/
Step 1: Install Laravel and Create a New Project
This step is not required; however, if you have not created the Laravel app, then you may go ahead and execute the below command:
composer create-project --prefer-dist laravel/laravel sanctum-auth-example
composer create-project --prefer-dist laravel/laravel sanctum-auth-example
Step 2: Install Laravel Sanctum
Run the following command to install Sanctum:
composer require laravel/sanctum
composer require laravel/sanctum
Step 3: Configure Sanctum
Edit your user.php model from the app/models folder, and add the HasApiTokens trait:
<?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<int, string>
*/
protected $fillable = [
"user_id",
"name",
"email",
"join_date",
"last_login",
"phone_number",
"status",
"role_name",
"email",
"role_name",
"avatar",
"position",
"department",
"password",
];
/**
* The attributes that should be hidden for serialization.
*
* @var array<int, string>
*/
protected $hidden = ["password", "remember_token"];
/**
* Get the attributes that should be cast.
*
* @return array<string, string>
*/
protected function casts(): array
{
return [
"email_verified_at" => "datetime",
"password" => "hashed",
];
}
/** auto create id */
protected static function boot()
{
parent::boot();
self::creating(function ($model) {
$getUser = self::orderBy("user_id", "desc")->first();
if ($getUser) {
$latestID = intval(substr($getUser->user_id, 3));
$nextID = $latestID + 1;
} else {
$nextID = 1;
}
$model->user_id = "KH_" . sprintf("%03s", $nextID);
while (self::where("user_id", $model->user_id)->exists()) {
$nextID++;
$model->user_id = "KH_" . sprintf("%03s", $nextID);
}
});
}
}
<?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<int, string>
*/
protected $fillable = [
"user_id",
"name",
"email",
"join_date",
"last_login",
"phone_number",
"status",
"role_name",
"email",
"role_name",
"avatar",
"position",
"department",
"password",
];
/**
* The attributes that should be hidden for serialization.
*
* @var array<int, string>
*/
protected $hidden = ["password", "remember_token"];
/**
* Get the attributes that should be cast.
*
* @return array<string, string>
*/
protected function casts(): array
{
return [
"email_verified_at" => "datetime",
"password" => "hashed",
];
}
/** auto create id */
protected static function boot()
{
parent::boot();
self::creating(function ($model) {
$getUser = self::orderBy("user_id", "desc")->first();
if ($getUser) {
$latestID = intval(substr($getUser->user_id, 3));
$nextID = $latestID + 1;
} else {
$nextID = 1;
}
$model->user_id = "KH_" . sprintf("%03s", $nextID);
while (self::where("user_id", $model->user_id)->exists()) {
$nextID++;
$model->user_id = "KH_" . sprintf("%03s", $nextID);
}
});
}
}
Step 4: Add User Table
Next, we need to create a migration for the products table using the Laravel artisan command. So first, execute the command below:
php artisan make:migration create_user_table
php artisan make:migration create_user_table
After this command, you will find one file in the following path: database/migrations. To create the products table, you must put the code below in your migration file.
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration {
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create("users", function (Blueprint $table) {
$table->id();
$table->string("user_id")->nullable();
$table->string("name")->nullable();
$table->string("email")->nullable();
$table->string("date_of_birth")->nullable();
$table->string("join_date")->nullable();
$table->string("phone_number")->nullable();
$table->string("status")->nullable();
$table->string("two_step")->nullable();
$table->string("last_login")->nullable();
$table->string("role_name")->nullable();
$table->string("avatar")->nullable();
$table->string("position")->nullable();
$table->string("department")->nullable();
$table->timestamp("email_verified_at")->nullable();
$table->string("password");
$table->rememberToken();
$table->timestamps();
});
Schema::create("password_reset_tokens", function (Blueprint $table) {
$table->string("email")->primary();
$table->string("token");
$table->timestamp("created_at")->nullable();
});
Schema::create("sessions", function (Blueprint $table) {
$table->string("id")->primary();
$table
->foreignId("user_id")
->nullable()
->index();
$table->string("ip_address", 45)->nullable();
$table->text("user_agent")->nullable();
$table->longText("payload");
$table->integer("last_activity")->index();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists("users");
Schema::dropIfExists("password_reset_tokens");
Schema::dropIfExists("sessions");
}
};
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration {
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create("users", function (Blueprint $table) {
$table->id();
$table->string("user_id")->nullable();
$table->string("name")->nullable();
$table->string("email")->nullable();
$table->string("date_of_birth")->nullable();
$table->string("join_date")->nullable();
$table->string("phone_number")->nullable();
$table->string("status")->nullable();
$table->string("two_step")->nullable();
$table->string("last_login")->nullable();
$table->string("role_name")->nullable();
$table->string("avatar")->nullable();
$table->string("position")->nullable();
$table->string("department")->nullable();
$table->timestamp("email_verified_at")->nullable();
$table->string("password");
$table->rememberToken();
$table->timestamps();
});
Schema::create("password_reset_tokens", function (Blueprint $table) {
$table->string("email")->primary();
$table->string("token");
$table->timestamp("created_at")->nullable();
});
Schema::create("sessions", function (Blueprint $table) {
$table->string("id")->primary();
$table
->foreignId("user_id")
->nullable()
->index();
$table->string("ip_address", 45)->nullable();
$table->text("user_agent")->nullable();
$table->longText("payload");
$table->integer("last_activity")->index();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists("users");
Schema::dropIfExists("password_reset_tokens");
Schema::dropIfExists("sessions");
}
};
Edit config/auth.php file and API driver:
[
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'sanctum',
'provider' => 'users',
],
],
[ 'web' => [ 'driver' => 'session', 'provider' => 'users', ], 'api' => [ 'driver' => 'sanctum', 'provider' => 'users', ], ],
Step 5: Set Up Database
Edit the .env file and configure database details in it:
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=here your database name here
DB_USERNAME=here database username here
DB_PASSWORD=here database password here
DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=here your database name here DB_USERNAME=here database username here DB_PASSWORD=here database password here
Step 6: Migrate Database
Run the database migrations to create the necessary tables in your database:
php artisan migrate
php artisan migrate
Step 7: Install route api
You may install Laravel Sanctum via the install:api Artisan command:
php artisan install:api
php artisan install:api
Step 8: Create API Routes
Next, define the routes for your API endpoints. Open your api.php file located at routes/api.php and define your routes:
<?php
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
Route::group(["namespace" => "App\Http\Controllers\API"], function () {
// --------------- register and login ----------------//
Route::controller(AuthenticationController::class)->group(function () {
Route::post("register", "register")->name("register");
Route::post("login", "login")->name("login");
Route::post("login/out", "logOut")->name("login/out");
});
// ------------------ get data ----------------------//
Route::controller(AuthenticationController::class)->group(function () {
Route::get("get-user", "userInfo")
->middleware("auth:api")
->name("get-user");
});
});
<?php
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
Route::group(["namespace" => "App\Http\Controllers\API"], function () {
// --------------- register and login ----------------//
Route::controller(AuthenticationController::class)->group(function () {
Route::post("register", "register")->name("register");
Route::post("login", "login")->name("login");
Route::post("login/out", "logOut")->name("login/out");
});
// ------------------ get data ----------------------//
Route::controller(AuthenticationController::class)->group(function () {
Route::get("get-user", "userInfo")
->middleware("auth:api")
->name("get-user");
});
});
Step 9: Create Controller and Method
Create a controller file by using the following command:
php artisan make:controller API/AuthenticationController
php artisan make:controller API/AuthenticationController
Now implement authentication methods into it to handle login, registration, and user detail functionality from the database:
<?php
namespace App\Http\Controllers\API;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Validator;
use Illuminate\Http\Request;
use App\Models\User;
use Carbon\Carbon;
use Auth;
use Hash;
class AuthenticationController extends Controller
{
/** register new account */
public function register(Request $request)
{
$request->validate([
"name" => "required|min:4",
"email" => "required|string|email|max:255|unique:users",
"password" => "required|min:8",
]);
$dt = Carbon::now();
$join_date = $dt->toDayDateTimeString();
$user = new User();
$user->name = $request->name;
$user->email = $request->email;
$user->password = Hash::make($request->password);
$user->save();
$data = [];
$data["response_code"] = "200";
$data["status"] = "success";
$data["message"] = "success Register";
return response()->json($data);
}
/**
* Login Req
*/
public function login(Request $request)
{
$request->validate([
"email" => "required|string",
"password" => "required|string",
]);
try {
$email = $request->email;
$password = $request->password;
if (Auth::attempt(["email" => $email, "password" => $password])) {
$user = Auth::User();
$accessToken = $user->createToken($user->email)->plainTextToken;
$data = [];
$data["response_code"] = "200";
$data["status"] = "success";
$data["message"] = "success Login";
$data["user_info"] = $user;
$data["token"] = $accessToken;
return response()->json($data);
} else {
$data = [];
$data["response_code"] = "401";
$data["status"] = "error";
$data["message"] = "Unauthorized";
return response()->json($data);
}
} catch (\Exception $e) {
\Log::info($e);
$data = [];
$data["response_code"] = "401";
$data["status"] = "error";
$data["message"] = "fail Login";
return response()->json($data);
}
}
/** user info */
public function userInfo()
{
try {
$userDataList = User::latest()->paginate(10);
$data = [];
$data["response_code"] = "200";
$data["status"] = "success";
$data["message"] = "success get user list";
$data["data_user_list"] = $userDataList;
return response()->json($data);
} catch (\Exception $e) {
\Log::info($e);
$data = [];
$data["response_code"] = "400";
$data["status"] = "error";
$data["message"] = "fail get user list";
return response()->json($data);
}
}
}
<?php
namespace App\Http\Controllers\API;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Validator;
use Illuminate\Http\Request;
use App\Models\User;
use Carbon\Carbon;
use Auth;
use Hash;
class AuthenticationController extends Controller
{
/** register new account */
public function register(Request $request)
{
$request->validate([
"name" => "required|min:4",
"email" => "required|string|email|max:255|unique:users",
"password" => "required|min:8",
]);
$dt = Carbon::now();
$join_date = $dt->toDayDateTimeString();
$user = new User();
$user->name = $request->name;
$user->email = $request->email;
$user->password = Hash::make($request->password);
$user->save();
$data = [];
$data["response_code"] = "200";
$data["status"] = "success";
$data["message"] = "success Register";
return response()->json($data);
}
/**
* Login Req
*/
public function login(Request $request)
{
$request->validate([
"email" => "required|string",
"password" => "required|string",
]);
try {
$email = $request->email;
$password = $request->password;
if (Auth::attempt(["email" => $email, "password" => $password])) {
$user = Auth::User();
$accessToken = $user->createToken($user->email)->plainTextToken;
$data = [];
$data["response_code"] = "200";
$data["status"] = "success";
$data["message"] = "success Login";
$data["user_info"] = $user;
$data["token"] = $accessToken;
return response()->json($data);
} else {
$data = [];
$data["response_code"] = "401";
$data["status"] = "error";
$data["message"] = "Unauthorized";
return response()->json($data);
}
} catch (\Exception $e) {
\Log::info($e);
$data = [];
$data["response_code"] = "401";
$data["status"] = "error";
$data["message"] = "fail Login";
return response()->json($data);
}
}
/** user info */
public function userInfo()
{
try {
$userDataList = User::latest()->paginate(10);
$data = [];
$data["response_code"] = "200";
$data["status"] = "success";
$data["message"] = "success get user list";
$data["data_user_list"] = $userDataList;
return response()->json($data);
} catch (\Exception $e) {
\Log::info($e);
$data = [];
$data["response_code"] = "400";
$data["status"] = "error";
$data["message"] = "fail get user list";
return response()->json($data);
}
}
}
Step 10: Testing
Run the artisan serve command to start the application server:
php artisan serve
php artisan serve
* Register a User:
- Open Postman.
- Set the request type to POST.
- Enter http://yourdomain.com/api/register in the address bar (replace yourdomain.com with your actual domain).
- Go to the Body tab.
- Choose x-www-form-urlencoded and select JSON.
- Enter the user registration data in JSON format, including name, email, and password.
- Click on the Send button to register the user.
* Login:
- Set the request type to POST.
- Enter the URL of your Laravel application followed by /api/login (e.g., http://yourdomain.com/api/login).
- Go to the Body tab.
- Select x-www-form-urlencoded and set the format to JSON.
- Enter the user’s credentials (email and password) in JSON format.
- Click on the Send button to log in. You will receive a token in the response if the login is successful.
* Get User Info:
- Set the request type to GET.
- Enter the URL of your Laravel application followed by /api/get-user (e.g., http://yourdomain.com/api/get-user).
- Go to the Headers tab.
- Add a new header with the key Authorization and the value, where <token> the token is obtained during the login process.
- Click on the Send button to get the user information.