In today’s article, I am going to create a REST API in Laravel with Authentication using Laravel Passport.
To demonstrate the API, I am going to continue the creating the Laravel powered ToDo app. I will use Laravel Passport access token in it. The Github repo for the todoappwithlaravel has been updated to this Passport API version.
Let’s get started.
Install and Setup Laravel Passport
To install Laravel Passport, run the following command:
composer require laravel/passport
Once the installation finishes, add the following provider in the config/app.php file:
Laravel\Passport\PassportServiceProvider::class,
Now, run the following command to migrate Laravel Passport tables:
php artisan migrate
Once all the tables have been migrated, run the following command to install it completely:
php artisan passport:install
Now open AuthServiceProvider.php file. In the `boot()` method, add the following line:
public function boot() { $this->registerPolicies(); Passport::routes(); }
Now open config/auth.php file and set passport as your API driver.
'guards' => [ 'web' => [ 'driver' => 'session', 'provider' => 'users', ], 'api' => [ 'driver' => 'passport', 'provider' => 'users', ], ],
At this point, Passport has been installed. Next, I will configure it in the Users model.
Update the Users Model
Now head to the app folder and open users.php file. Add `Laravel\Passport\HasApiTokens` trait in it.
Stop Wasting Time on Servers
Cloudways handle server management for you so you can focus on creating great apps and keeping your clients happy.
<?php namespace App; use Illuminate\Notifications\Notifiable; use Illuminate\Foundation\Auth\User as Authenticatable; use Laravel\Passport\HasApiTokens; class User extends Authenticatable { use Notifiable,HasApiTokens;
I will now create a controller which will handle REST API requests.
Create API Controller for the REST API in Laravel
Now run the following Artisan command to create a new controller.
php artisan make:controller ApiController.php
Now open the newly created file. Let’s start with creating the method for generating access tokens.
public function accessToken(Request $request) { $validate = $this->validations($request,"login"); if($validate["error"]){ return $this->prepareResult(false, [], $validate['errors'],"Error while validating user"); } $user = User::where("email",$request->email)->first(); if($user){ if (Hash::check($request->password,$user->password)) { return $this->prepareResult(true, ["accessToken" => $user->createToken('Todo App')->accessToken], [],"User Verified"); }else{ return $this->prepareResult(false, [], ["password" => "Wrong passowrd"],"Password not matched"); } }else{ return $this->prepareResult(false, [], ["email" => "Unable to find user"],"User not found"); } } Next, I will create a function through which a user can get,create,update and delete todo items. /** * Get a validator for an incoming Todo request. * * @param \Illuminate\Http\Request $request * @param $type * @return \Illuminate\Contracts\Validation\Validator */ public function validations($request,$type){ $errors = [ ]; $error = false; if($type == "login"){ $validator = Validator::make($request->all(),[ 'email' => 'required|email|max:255', 'password' => 'required', ]); if($validator->fails()){ $error = true; $errors = $validator->errors(); } }elseif($type == "create todo"){ $validator = Validator::make($request->all(),[ 'todo' => 'required', 'description' => 'required', 'category' => 'required' ]); if($validator->fails()){ $error = true; $errors = $validator->errors(); } }elseif($type == "update todo"){ $validator = Validator::make($request->all(),[ 'todo' => 'filled', 'description' => 'filled', 'category' => 'filled' ]); if($validator->fails()){ $error = true; $errors = $validator->errors(); } } return ["error" => $error,"errors"=>$errors]; } /** * Display a listing of the resource. * * @param \Illuminate\Http\Request $request * @return \Illuminate\Http\Response */ private function prepareResult($status, $data, $errors,$msg) { return ['status' => $status,'data'=> $data,'message' => $msg,'errors' => $errors]; } /** * Display a listing of the resource. * * @param \Illuminate\Http\Request $request * @return \Illuminate\Http\Response */ public function index(Request $request) { return $this->prepareResult(true, $request->user()->todo()->get(), [],"All user todos"); } /** * Display the specified resource. * * @param \App\Todo $todo * @return \Illuminate\Http\Response */ public function show(Request $request,Todo $todo) { if($todo->user_id == $request->user()->id){ return $this->prepareResult(true, $todo, [],"All results fetched"); }else{ return $this->prepareResult(false, [], "unauthorized","You are not authenticated to view this todo"); } } /** * Store a newly created resource in storage. * * @param \Illuminate\Http\Request $request * @return \Illuminate\Http\Response */ public function store(Request $request) { $error = $this->validations($request,"create todo"); if ($error['error']) { return $this->prepareResult(false, [], $error['errors'],"Error in creating todo"); } else { $todo = $request->user()->todo()->Create($request->all()); return $this->prepareResult(true, $todo, $error['errors'],"Todo created"); } } /** * Update the specified resource in storage. * * @param \Illuminate\Http\Request $request * @param \App\Todo $todo * @return \Illuminate\Http\Response */ public function update(Request $request, Todo $todo) { if($todo->user_id == $request->user()->id){ $error = $this->validations($request,"update todo"); if ($error['error']) { return $this->prepareResult(false, [], $error['errors'],"error in updating data"); } else { $todo = $todo->fill($request->all())->save(); return $this->prepareResult(true, $todo, $error['errors'],"updating data"); } }else{ return $this->prepareResult(false, [], "unauthorized","You are not authenticated to edit this todo"); } } /** * Remove the specified resource from storage. * * @param \App\Todo $todo * @return \Illuminate\Http\Response */ public function destroy(Todo $todo) { if($todo->user_id == $request->user()->id){ if ($todo->delete()) { return $this->prepareResult(true, [], [],"Todo deleted"); } }else{ return $this->prepareResult(false, [], "unauthorized","You are not authenticated to delete this todo"); } }
All the hard work is now over. It is time to create routes for the API.
Create Routes for API
Now open routes/api.php file and add the following routes in it.
Route::get('/login','ApiController@accessToken'); Route::group(['middleware' => ['web','auth:api']], function() { Route::post('/todo/','ApiController@store'); Route::get('/todo/','ApiController@index'); Route::get('/todo/{todo}','ApiController@show'); Route::put('/todo/{todo}','ApiController@update'); Route::delete('/todo/{todo}','ApiController@destroy'); }); Route::middleware('auth:api')->get('/user', function (Request $request) { return $request->user(); });
Now open the VerifyCsrfTokken.php file (located in app/Http/Controllers/Middleware) and find `api/*` in `$except`
protected $except = [ "api/*" ];
It is now time to test how the API performs!
Testing the REST API
I will use Postman to test the API.
I will start with getting an access token for a registered user. For that, send a GET request to “api/login” with parameters, email and password.
Since I have not sent the email, it shows me an error. Now, let’s send a request without errors.
Next, I will create a new todo item with the API. For this, send a POST request to “api/todo” with parameters todo,category and description.
Since I have not added the access token, I will get an error.
A new todo will be created. Now, try to update, delete and get users. I am sure every operation will be fine.
Conclusion
In this article, I first setup Laravel Passport in an existing project. I next created routes for the API. Once done, I tested the Laravel REST API and verified that it works as intended.
If you face any problems in implementing the API, do leave a comment below.
Shahzeb Ahmed
Shahzeb is a Digital Marketer with a Software Engineering background, works as a Community Manager — PHP Community at Cloudways. He is growth ambitious and aims to learn & share information about PHP & Laravel Development through practice and experimentation. He loves to travel and explore new ideas whenever he finds time. Get in touch with him at [email protected]