This website uses cookies

Our website, platform and/or any sub domains use cookies to understand how you use our services, and to improve both your experience and our marketing relevance.

Create a REST API for ToDo App with Authentication Using Lumen

October 4, 2021

7 Min Read
lumen api

Using the same fundamental libraries as Laravel Authentication, Lumen is configured in quite an unexpected way from the Laravel framework. Stateless components such as API tokens must be used to confirm incoming requests since Lumen does not support session state.

In the first installment of the series on creating a ToDo App with Laravel 5.4, I added an API_KEY column in the user table and commented that I might use it in the future. Now, in this second installment of the series, it will be handy.

In this article, I am going to use the same tables that I created in the ToDo App. I will connect it with Lumen and create a REST API. This API will feature:

  • An API Key will be generated and sent to the user once a login request is sent to the API.
  • In order to perform CRUD operations, the user needs to add this API key in the authorization header. If the API key is not valid, the request will not proceed.

The complete code for this tutorial can be found on Github repo.

Create a New Lumen Project

I will start by creating a new Lumen project for the ToDo REST API. For this, run the following command:

composer create-project --prefer-dist laravel/lumen todorest

Wait for a composer to create the Lumen project. Now, edit the .env file and update it with the database information. I am going to use the same tables that I have created in the first part of the ToDo app.

Now head to the app folder and create a new file. Name it Users.php and paste the following code in it.

$app->withFacades();
$app->withEloquent();
$app->register(App\Providers\AppServiceProvider::class);
$app->register(App\Providers\AuthServiceProvider::class);
$app->routeMiddleware([
'auth' => App\Http\Middleware\Authenticate::class,
]);

Create the User Model

Now head to the app folder and create a new file. Name it Users.php and paste the following code in it.

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

use Illuminate\Contracts\Auth\Authenticatable;

use Illuminate\Auth\Authenticatable as AuthenticableTrait;


class Users extends Model implements Authenticatable

{

   //

   use AuthenticableTrait;

   protected $fillable = ['username','email','password','userimage'];

   protected $hidden = [

   'password'

   ];

   /*

   * Get Todo of User

   *

   */

   public function todo()

   {

       return $this->hasMany('App\Todo','user_id');

   }

}

In the Users model, I defined its relationship with the Todo Table along with foreign id.

Stop Wasting Time on Servers

Cloudways handle server management for you so you can focus on creating great apps and keeping your clients happy.

Create a ToDo Model

Now, in the same folder, create a new file and name it Todo.php, then paste the following code in it.

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Todo extends Model

{

   //

   protected $table = 'todo';

   protected $fillable = ['todo','category','user_id','description'];

}

 

Create the User Controller

Now go to app/Http/Controllers and create a new file with the name UsersController.php. Paste the following code in it:

<?php

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;

use Illuminate\Support\Facades\Hash;

use Illuminate\Http\Request;

use App\Users;

class UsersController extends Controller

{

  public function __construct()

   {

     //  $this->middleware('auth:api');

   }

   /**

    * Display a listing of the resource.

    *

    * @return \Illuminate\Http\Response

    */

   public function authenticate(Request $request)

   {

       $this->validate($request, [

       'email' => 'required',

       'password' => 'required'

        ]);

      $user = Users::where('email', $request->input('email'))->first();

     if(Hash::check($request->input('password'), $user->password)){

          $apikey = base64_encode(str_random(40));

          Users::where('email', $request->input('email'))->update(['api_key' => "$apikey"]);;

          return response()->json(['status' => 'success','api_key' => $apikey]);

      }else{

          return response()->json(['status' => 'fail'],401);

      }

   }

}    

?>

In this controller, I created an authenticate model which checks whether the user is valid. If the user is valid, it returns an API key. If not, it returns a fail error with the response code 401.

Update the Auth Service Provider

Now, head to the app/Providers and open AutheServiceProvider.php file. In this file, I will check the validity of the API key that the user sends in for performing ToDo operations.

In the file, at the top of the code, after namespace, add the following line:

use App\Users;

Now go to the `boot()` method and replace the code in it with the following:

$this->app['auth']->viaRequest('api', function ($request) {
if ($request->header('Authorization')) {
$key = explode(' ',$request->header('Authorization'));
$user = Users::where('api_key', $key[1])->first();
if(!empty($user)){
$request->request->add(['userid' => $user->id]);

}
return $user;
}
});

In this code, I will check that the user have a valid API key and then append the verified userid to the request. If the API is not verified, it will return Unauthorized. In order to customized this message, head to the app/Http/Middleware folder and open Authenticate.php file. In this file, go to the `handle()` method and change the line inside the `if` with the following.

return response()->json(['error' => 'Unauthorized'], 401);

The next action item is the creation of the routes.

Create the ToDo Controller

Now in the Controllers folder, create a new file and name it TodoController.php. Paste the following code in it:

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Todo;
use Auth;

class TodoController extends Controller
{
    /**
     * Create a new controller instance.
     *
     * @return void
     */
    public function __construct()
    {
        $this->middleware('auth');
    }
    
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index(Request $request)
    {
        $todo = Auth::user()->todo()->get();
        return response()->json(['status' => 'success','result' => $todo]);
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        $this->validate($request, [
        'todo' => 'required',
        'description' => 'required',
        'category' => 'required'
         ]);
        if(Auth::user()->todo()->Create($request->all())){
            return response()->json(['status' => 'success']);
        }else{
            return response()->json(['status' => 'fail']);
        }

    }

    /**
     * Display the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function show($id)
    {
        $todo = Todo::where('id', $id)->get();
        return response()->json($todo);
        
    }

    /**
     * Show the form for editing the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function edit($id)
    {
        $todo = Todo::where('id', $id)->get();
        return view('todo.edittodo',['todos' => $todo]);
    }

    /**
     * Update the specified resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function update(Request $request, $id)
    {
        $this->validate($request, [
        'todo' => 'filled',
        'description' => 'filled',
        'category' => 'filled'
         ]);
        $todo = Todo::find($id);
        if($todo->fill($request->all())->save()){
           return response()->json(['status' => 'success']);
        }
        return response()->json(['status' => 'failed']);
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function destroy($id)
    {
        if(Todo::destroy($id)){
             return response()->json(['status' => 'success']);
        }
    }
}

In this code, I am simply performing CRUD operation once the user have a valid API key. The auth middleware tests whether the user have a valid API key. I have created a different validation method in it; one is for creating a new ToDo item, which is the `store()` method in which I am validating all the required fields. But in the `edit()` method, I am only testing if that field is in parameter and that it shouldn’t be empty.

Create Routes For the Todo API

Now go to the routes folder and open the web.php file. Inside this file, add the following routes.

$app->group(['prefix' => 'api/'], function ($app) {
$app->get('login/','[email protected]');
$app->post('todo/','[email protected]');
$app->get('todo/', '[email protected]');
$app->get('todo/{id}/', '[email protected]');
$app->put('todo/{id}/', '[email protected]');
$app->delete('todo/{id}/', '[email protected]');
});

All the hard work is done. I will now test it!

Test the ToDo REST API

For testing the REST API, I will use PostMan. Before getting started with the testing, run the following command inside the Lumen app folder to start a server.

php -S localhost:8000 -t public

Login using the API

Now in the PostMan, try to login with the email and password you used for the ToDo app.

Send a GET request to: http://localhost:8000/api/login/ along with the email and password parameter

Login using the API

You will receive a Success message along with the API Key.

Get All the ToDo Items

I will now try to get all the ToDo items of a user, without adding an API key. For this, send a GET request to: http://localhost:8000/api/todo

Get All the ToDo Items

You will get an error of Unauthorized. Now I will add the API key in the Authorization header, and then send the request again.

API key

This time, you will get all the ToDo items of the user.

Create a New ToDo Item

I will now create a new ToDo item. For this, send a POST request to: http://localhost:8000/api/todo along with todo, description and category parameters. Remember to add the API key in the header or else you will get the error message.

New ToDo Item

If all fields are filled, you will get the Success message.

I will now test validation by trying to send a ToDo create request with an empty description field.

ToDo create

As expected, you will get an error.

Edit a ToDo

To edit a todo send a PUT request to http://localhost:8000/api/todo/{id} along with the todo,description and category parameters you like to edit.

Edit a ToDo

Delete a ToDo Item

I will now delete a ToDo item. Send a DELETE request to http://localhost:8000/api/todo/{id}.

Delete a ToDo Item

Now, when you try to get all ToDo items, you will see that the particular item has been deleted.

get all ToDo items

Final Words

Lumen has good performance with API as compared to Laravel. Lumen is one of the best performing micro-framework APIs for building microservices. Laravel has destitute execution and speed compared to Lumen.

This piece is a simple demonstration of what can be done. The complete code can be found on Github. If you are unable to understand anything or would like to contribute to the discussion, do leave a comment below.

Q. How do I add authentication to REST API ?

A: REST API can authenticate by giving a user ID and secret word to the REST API login asset with the HTTP POST method. An LTPA token is created that empowers the client to confirm future demands. This LTPA token has the prefix LtpaToken2. The client can log out by utilizing the HTTP Erase strategy, and can inquire the login data of the current client with the HTTP GET strategy.

Share your opinion in the comment section. COMMENT NOW

Share This Article

Customer Review at

“Cloudways hosting has one of the best customer service and hosting speed”

Sanjit C [Website Developer]

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 [email protected]

×

Get Our Newsletter
Be the first to get the latest updates and tutorials.

Thankyou for Subscribing Us!

×

Webinar: How to Get 100% Scores on Core Web Vitals

Join Joe Williams & Aleksandar Savkovic on 29th of March, 2021.

Do you like what you read?

Get the Latest Updates

Share Your Feedback

Please insert Content

Thank you for your feedback!

Do you like what you read?

Get the Latest Updates

Share Your Feedback

Please insert Content

Thank you for your feedback!