X
    Categories: Learn Laravel Tutorials, Tips And Guides

Create a RESTful API Authentication Using Laravel Passport

In today’s article, I am going to create a REST API in Laravel 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.

<?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

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 API and verified that it works as intended.

If you face any problems in implementing the API, do leave a comment below.

Ahmed Khan: Ahmed was a PHP community expert at Cloudways - A Managed PHP Hosting Cloud Platform. He is a software engineer with extensive knowledge in PHP and SEO. He loves watching Game of Thrones is his free time. Follow Ahmed on Twitter to stay updated with his works. You can email him at ahmed.khan@cloudways.com