Laravel 10 REST API using Passport Authentication
Today in this tutorial, we will learn about how to build Laravel 10 REST API using Passport authentication. We will learn it with example application in Laravel REST API authentication with Passport with step by step guide.
We will develop very simple Laravel 10 Passport API for authentication so that anyone can easily understand it, building API is very easy with Laravel Passport and we can easily build Laravel 10 Passport SPA API.
Previously, we have also shared how to develop a Laravel 10 REST API using Sanctum Authentication, Sanctum is another package in Laravel which is also used for building APIs.
What is API?
Before start developing the API, lets learn what is an API. In simple words, API (application programming interface) is just a way communication between two or more computer programs.
These APIs are mostly used for web and mobile applications development, this is why developing RESTful APIs are very important to learn for all web and mobile application developers.
What is Laravel Passport?
We will use Laravel Passport which provides a complete OAuth2 server implementation and also issue API tokens for authentication and developing APIs for SPAs (single page applications) which are used in web and mobile applications.
Although, you can use Laravel Sanctum Authentication as well for issuing tokens. But in this example we will learn how to use Laravel Passport by building Restful APIs.
We will use access tokens for registered users, we can generate multiple tokens using Laravel Passport which will help us to access all protected routes/end points of our application.
For this example, we are using the Laravel 10.10 and Passport 11.10 versions.
Laravel Passport help us to generate access tokens for the protected routes/end points which will be stored in our oauth_access_tokens table.
We are using Laravel Passport only for the protected routes of our application. To access public routes, we do not need to use the access token.
Application Flow
In our example application, we will first create a products table which will hold all products information. There will be two columns in products table with name as name and description.
We will develop APIs for Laravel 10 custom user registration and login as we will generate access tokens for registered users using Laravel Passport. We will build user logout API as well.
In our app, user registration and login are public routes, these routes will return the access token to access the protected routes of our app by passing these tokens as a bearer token. Logout route is a protected route therefore we will pass the access token to logout from our Laravel application.
We will pass access tokens to create, update and delete product from the database, as these are protected routes and we can not perform these operations until we pass the correct access tokens with them.
To achieve this objective we will develop CRUD operations API for our products.
In order to view all products, single product and search products, we do not need token as these are public routes and we can access public routes without access tokens.
Before start building, you must be aware of how to perform CRUD operations in Laravel, you can also checkout the tutorial of Laravel 10 CRUD application.
Now without further delay, lets start developing a Laravel 10 REST API authentication application with Laravel Passport example.
Steps to Create Laravel 10 REST API using Passport Authentication
Follow the below step by step guide to create a Laravel 10 REST API using Passport authentication application.
- Install Laravel 10 App
- Install or Enable PHP’s Sodium Extension
- Configure Database Credentials
- Install Laravel Passport
- Add API Driver in Guards in auth.php
- Add HasApiTokens Traits in User Model
- Create and Update LoginRegister Controller
- Create and Update Product Model with Migration and Model API Resource Controller
- Define API Endpoints in routes/api.php
- Migrate Product Table to Database
- Run Laravel Development Server & Test the Application
1. Install Laravel 10 App
Install Laravel 10 application with name laravel-10-passport-api by running the below command on terminal or command prompt.
composer create-project --prefer-dist laravel/laravel:^10 laravel-10-passport-api
Go to the laravel-10-passport-api directory by running the below command.
cd laravel-10-passport-api
2. Install or Enable PHP’s Sodium Extension
Now, before moving ahead make sure that PHP’s Sodium extension is enabled, we are using XAMPP for PHP.
In XAMPP, we need to enable PHP’s Sodium extension. Typically if installed in C drive. Just go to C:\xampp\php\php.ini and remove the semi-colon (;) before extension=sodium and restart apache server.
//Before
;extension=sodium
//After
extension=sodium
Normally, this resolves the issue of mostly users. In case if your issue is not resolved make sure that libsodium.dll file exist in PHP directory in XAMPP.
Alternatively, you can install the latest XAMPP, complete and step by step guide is available here about how to Install XAMPP on Windows.
3. Configure Database Credentials
Now we need to update the database credentials which are database name, username and password. All you need is to update the .env file which is available on the root directory in your application.
Open the .env file and update it with your database credentials like below.
Database Credentials:
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=your_db_name
DB_USERNAME=your_db_username
DB_PASSWORD=your_db_password
4. Install Laravel Passport
Now install Laravel Passport in your application by running the below command.
composer require laravel/passport
Now make sure that your database is running, then we need to migrate all migrations, just run the below command to migrate all Laravel tables along with Laravel passport OAuth2 clients and access tokens tables:
php artisan migrate
And then run the below command.
php artisan passport:install
5. Add API Driver in Guards in auth.php
We need to add API driver in guards, just go to the config/auth.php and update the following code in guards.
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'passport',
'provider' => 'users',
],
],
6. Add HasApiTokens Traits in User Model
Simply add the following code in your user model here \app\Models\User.php
<?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\Passport\HasApiTokens;
class User extends Authenticatable
{
use HasApiTokens, HasFactory, Notifiable;
/**
* The attributes that are mass assignable.
*
* @var array<int, string>
*/
protected $fillable = [
'name',
'email',
'password',
];
/**
* The attributes that should be hidden for serialization.
*
* @var array<int, string>
*/
protected $hidden = [
'password',
'remember_token',
];
/**
* The attributes that should be cast.
*
* @var array<string, string>
*/
protected $casts = [
'email_verified_at' => 'datetime',
'password' => 'hashed',
];
}
7. Create and Update LoginRegister Controller
In this step, we will create Login and Register Controller. Simply run the below command in your terminal window.
php artisan make:controller Auth\LoginRegisterController
Then, just go to the \Http\Controllers\Auth\LoginRegisterController.php and copy paste the following code in it.
<?php
namespace App\Http\Controllers\Auth;
use App\Models\User;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Hash;
use Validator;
class LoginRegisterController extends Controller
{
/**
* Register a new user.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function register(Request $request)
{
$validate = Validator::make($request->all(), [
'name' => 'required|string|max:250',
'email' => 'required|string|email:rfc,dns|max:250|unique:users,email',
'password' => 'required|string|min:8|confirmed'
]);
if($validate->fails()){
return response()->json([
'status' => 'failed',
'message' => 'Validation Error!',
'data' => $validate->errors(),
], 403);
}
$user = User::create([
'name' => $request->name,
'email' => $request->email,
'password' => Hash::make($request->password)
]);
$data['token'] = $user->createToken($request->email)->accessToken;
$data['user'] = $user;
$response = [
'status' => 'success',
'message' => 'User is created successfully.',
'data' => $data,
];
return response()->json($response, 201);
}
/**
* Authenticate the user.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function login(Request $request)
{
$validate = Validator::make($request->all(), [
'email' => 'required|string|email',
'password' => 'required|string'
]);
if($validate->fails()){
return response()->json([
'status' => 'failed',
'message' => 'Validation Error!',
'data' => $validate->errors(),
], 403);
}
// Check email exist
$user = User::where('email', $request->email)->first();
// Check password
if(!$user || !Hash::check($request->password, $user->password)) {
return response()->json([
'status' => 'failed',
'message' => 'Invalid credentials'
], 401);
}
$data['token'] = $user->createToken($request->email)->accessToken;
$data['user'] = $user;
$response = [
'status' => 'success',
'message' => 'User is logged in successfully.',
'data' => $data,
];
return response()->json($response, 200);
}
/**
* Log out the user from application.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function logout(Request $request)
{
auth()->user()->tokens()->delete();
return response()->json([
'status' => 'success',
'message' => 'User is logged out successfully'
], 200);
}
}
8. Create and Update Product Model with Migration and Model API Resource Controller
In the step 6, first we need to create product model with migration and model API resource controller, we have options either we can create each of these files individually or we can also create all of them together.
Simply run the below command in your terminal to create all these files.
php artisan make:model Product -mcr --api
After that, just go to \database\migrations directory and locate your product migration file with name like YYYY_MM_DD_TIMESTAMP_create_products_table.php, open this file and update the following code in it.
<?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('products', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->text('description');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('products');
}
};
After migration code, now we need to update the product model code, just go to the \app\Models\Product.php and update the following code in it.
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Product extends Model
{
use HasFactory;
protected $fillable = [
'name',
'description'
];
}
In the last, we need to go to the product controller \app\Http\Controllers\ProductController.php and update the following code in it.
<?php
namespace App\Http\Controllers;
use App\Models\Product;
use Illuminate\Http\Request;
use Validator;
class ProductController extends Controller
{
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index()
{
$products = Product::latest()->get();
if (is_null($products->first())) {
return response()->json([
'status' => 'failed',
'message' => 'No product found!',
], 200);
}
$response = [
'status' => 'success',
'message' => 'Products are retrieved successfully.',
'data' => $products,
];
return response()->json($response, 200);
}
/**
* Store a newly created resource in storage.
*/
public function store(Request $request)
{
$validate = Validator::make($request->all(), [
'name' => 'required|string|max:250',
'description' => 'required|string|'
]);
if($validate->fails()){
return response()->json([
'status' => 'failed',
'message' => 'Validation Error!',
'data' => $validate->errors(),
], 403);
}
$product = Product::create($request->all());
$response = [
'status' => 'success',
'message' => 'Product is added successfully.',
'data' => $product,
];
return response()->json($response, 200);
}
/**
* Display the specified resource.
*/
public function show($id)
{
$product = Product::find($id);
if (is_null($product)) {
return response()->json([
'status' => 'failed',
'message' => 'Product is not found!',
], 200);
}
$response = [
'status' => 'success',
'message' => 'Product is retrieved successfully.',
'data' => $product,
];
return response()->json($response, 200);
}
/**
* Update the specified resource in storage.
*/
public function update(Request $request, $id)
{
$validate = Validator::make($request->all(), [
'name' => 'required',
'description' => 'required'
]);
if($validate->fails()){
return response()->json([
'status' => 'failed',
'message' => 'Validation Error!',
'data' => $validate->errors(),
], 403);
}
$product = Product::find($id);
if (is_null($product)) {
return response()->json([
'status' => 'failed',
'message' => 'Product is not found!',
], 200);
}
$product->update($request->all());
$response = [
'status' => 'success',
'message' => 'Product is updated successfully.',
'data' => $product,
];
return response()->json($response, 200);
}
/**
* Remove the specified resource from storage.
*/
public function destroy($id)
{
$product = Product::find($id);
if (is_null($product)) {
return response()->json([
'status' => 'failed',
'message' => 'Product is not found!',
], 200);
}
Product::destroy($id);
return response()->json([
'status' => 'success',
'message' => 'Product is deleted successfully.'
], 200);
}
/**
* Search by a product name
*
* @param str $name
* @return \Illuminate\Http\Response
*/
public function search($name)
{
$products = Product::where('name', 'like', '%'.$name.'%')
->latest()->get();
if (is_null($products->first())) {
return response()->json([
'status' => 'failed',
'message' => 'No product found!',
], 200);
}
$response = [
'status' => 'success',
'message' => 'Products are retrieved successfully.',
'data' => $products,
];
return response()->json($response, 200);
}
}
9. Define API Endpoints in routes/api.php
Finally, we need to define all the API routes / endpoints for the user registration, login and log out, and also product CRUD routes with search products route.
Simply update the following code in \routes\api.php
<?php
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\ProductController;
use App\Http\Controllers\Auth\LoginRegisterController;
/*
|--------------------------------------------------------------------------
| API Routes
|--------------------------------------------------------------------------
|
| Here is where you can register API routes for your application. These
| routes are loaded by the RouteServiceProvider and all of them will
| be assigned to the "api" middleware group. Make something great!
|
*/
// Public routes of authtication
Route::controller(LoginRegisterController::class)->group(function() {
Route::post('/register', 'register');
Route::post('/login', 'login');
});
// Public routes of product
Route::controller(ProductController::class)->group(function() {
Route::get('/products', 'index');
Route::get('/products/{id}', 'show');
Route::get('/products/search/{name}', 'search');
});
// Protected routes of product and logout
Route::middleware('auth:api')->group( function () {
Route::post('/logout', [LoginRegisterController::class, 'logout']);
Route::controller(ProductController::class)->group(function() {
Route::post('/products', 'store');
Route::post('/products/{id}', 'update');
Route::delete('/products/{id}', 'destroy');
});
});
10. Migrate Product Table to Database
Now, we have reach towards the final step which is migration of our product table in database. Just run the below command on your terminal to migrate product migration table in your database.
php artisan migrate
11. Run Laravel Development Server & Test the Application
Now, we have completed our application, we can start the Laravel development server and test our Laravel 10 REST APIs with Passport authentication.
Run the below command to start server.
php artisan serve
After that open the Postman application to test our APIs, make sure that you already installed Postman, it is an application that helps to test our APIs.
if you do not have Postman account then first you will need to install Postman into your machine and then create your Postman account and login with your credentials.
Now on the Postman application go to the top left, there is a New button to create new API request. Click on New button and then select the HTTP from the given options.
Additionally, keep in mind that you add the Accept => application/json in the Header of all APIs requests. Screenshot is given below for your understanding.
End Points / Routes of API:
Register and Login Routes:
1) User Registration API URL: http://127.0.0.1:8000/api/register
Method: POST
Registration is a public route, just enter required fields data then press Send button to get the response from user registration API. You will get a response in the body section of your request just like below screenshot.
In the “data” -> “token” is returned which we will need to pass to access the protected routes.
Once user is registered, you can login the user with user credentials on the login route.
2) User Login API URL: http://127.0.0.1:8000/api/login
Method: POST
Login is also a public route, just enter required fields data then press Send button to get the response from the user login API. You will get response like below screenshot.
Login API also returns the “token” in data, we can use this token to access product protected route to create, update and delete a product.
You will need to pass the token with each protected routes in the Authorization -> Type -> Bearer Token in Token field same like in below screenshot.
Product CRUD Application and Logout Routes:
3) Create Product API URL: http://127.0.0.1:8000/api/products
Method: POST
Create product is a protected route, pass token and enter required fields data then press Send button, you will a response like below screenshot.
4) Show All Products API URL: http://127.0.0.1:8000/api/products
Method: GET
This is a public route, just press a Send button and you will get the response like below screenshot.
5) Show Single Product API URL: http://127.0.0.1:8000/api/products/{id}
Method: GET
This is a public route, pass the product ID in URL and press a Send button and get the response like below screenshot.
6) Update Product API URL: http://127.0.0.1:8000/api/products/{id}
Method: POST
This is a protected route, just add token, pass the product ID in URL and enter required fields data then press a Send button and you will get the response like below screenshot.
7) Search Products API URL: http://127.0.0.1:8000/api/products/search/{name}
Method: GET
This is also a public route, just pass the search keyword in URL and press a Send button and get the response like below screenshot.
8) Delete Product API URL: http://127.0.0.1:8000/api/products/{id}
Method: DELETE
This is a protected route, simply add access token, pass the product ID in URL and press a Send button and then you will get the response same like below screenshot.
9) Logout User API URL: http://127.0.0.1:8000/api/logout
Method: POST
This is also a protected route, just add token and press a Send button and you will get response like below screenshot.
Conclusion
In the end of this tutorial, we hope that you have learnt how to create a Laravel 10 REST API using Passport authentication application by following the above step by step guide.
If you found this tutorial helpful, share it with your friends and developers group.
We spent several hours to create this tutorial, if you want to say thanks so like our page on Facebook, Twitter and share it.
Facebook Official Page: All PHP Tricks
Twitter Official Page: All PHP Tricks
Great Article for beginners.
Dear Keerthy,
Glad to know that you found it helpful. 🙂
This tutorial helped me a lot, I was able to register, log in, and obtain the data. but now I don’t know how to do it, for example, show the list of products on another domain. If you could make another one explaining how to consume the api from another site it would be great, thank you