Laravel 5.6 Custom Token Base API Authentication

4 4,473

In this article, we will discuss how to create Laravel 5.6 Custom Token Base API Authentication. As we discuss the JWT Auth in our previous article. But Laravel is open to creating a custom authentication for our API’s. I’m assuming you are familiar with the Laravel framework if not then you can start with given tutorials.

Setup Laravel 5.6 Custom Token Base API Authentication

Create APIToken Middleware

Let’s create a middleware name APIToken. Basically, its used to protect our API where we need the user to login. You can get more details on middleware here.

Use the given command to create middleware.

php artisan make:middleware APIToken

Newly created APIToken.php middleware located at app/Http/Middleware. Just open the middleware and update the handle function as per given code.

public function handle($request, Closure $next)
{
  if($request->header('Authorization')){
    return $next($request);
  }
  return response()->json([
    'message' => 'Not a valid API request.',
  ]);
}

In the above code snippet, we are checking the request header. Is header contains the Authorization Token? If the token is available then request is processed to next request otherwise an error message thrown.

Now time to update the newly create middleware in Kernel.php.

protected $routeMiddleware = [
    ...
    'APIToken' => \App\Http\Middleware\APIToken::class,
    ...
];

Setup Migration for API Token

Use the given command to create a migration.

php artisan make:migration add_api_token_user_table --table=users

After command execution, migration file is located at database/migrations.

<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class AddApiTokenInUsers extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::table('users', function (Blueprint $table) {
            $table->string('api_token',100)->nullable();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::table('users', function (Blueprint $table) {
            $table->string('api_token',100)->nullable();
        });
    }
}

Setup AuthController

Use the given command to create the AuthController.

php artisan make:controller API/AuthController

After, execution of above command. The controller is located at app/Http/Controller/API directory. We will add our logic for Login, Register, and Logout functionality.

<?php

namespace App\Http\Controllers\API;

use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use DB;
use App\User;
use Validator;

class AuthController extends Controller
{
  private $apiToken;

  public function __construct()
  {
    // Unique Token
    $this->apiToken = uniqid(base64_encode(str_random(60)));
  }
  /**
   * Client Login
   */
  public function postLogin(Request $request)
  {
    // Validations
    $rules = [
      'email'=>'required|email',
      'password'=>'required|min:8'
    ];
    $validator = Validator::make($request->all(), $rules);
    if ($validator->fails()) {
      // Validation failed
      return response()->json([
        'message' => $validator->messages(),
      ]);
    } else {

      // Fetch User
      $user = User::where('email',$request->email)->first();

      if($user) {
        // Verify the password
        if( password_verify($request->password, $user->password) ) {

          // Update Token
          $postArray = ['api_token' => $this->apiToken];
          $login = User::where('email',$request->email)->update($postArray);
          
          if($login) {

            return response()->json([
              'name'         => $user->name,
              'email'        => $user->email,
              'access_token' => $this->apiToken,
            ]);
          }

        } else {
          return response()->json([
            'message' => 'Invalid Password',
          ]);
        }
      } else {
        return response()->json([
          'message' => 'User not found',
        ]);
      }
    }
  }

  /**
   * Register
   */
  public function postRegister(Request $request)
  {
    // Validations
    $rules = [
      'name'     => 'required|min:3',
      'email'    => 'required|unique:users,email',
      'password' => 'required|min:8'
    ];
    $validator = Validator::make($request->all(), $rules);
    if ($validator->fails()) {
      // Validation failed
      return response()->json([
        'message' => $validator->messages(),
      ]);
    } else {

      $postArray = [
        'name'      => $request->name,
        'email'     => $request->email,
        'password'  => bcrypt($request->password),
        'api_token' => $this->apiToken
      ];
      // $user = User::GetInsertId($postArray);
      $user = User::insert($postArray);
  
      if($user) {
        return response()->json([
          'name'         => $request->name,
          'email'        => $request->email,
          'access_token' => $this->apiToken,
        ]);
      } else {
        return response()->json([
          'message' => 'Registration failed, please try again.',
        ]);
      }

    }
  }

  /**
   * Logout
   */
  public function postLogout(Request $request)
  {
    $token = $request->header('Authorization');
    $user = User::where('api_token',$token)->first();
    if($user) {
      $postArray = ['api_token' => null];
      $logout = User::where('id',$user->id)->update($postArray);
      if($logout) {
        return response()->json([
          'message' => 'User Logged Out',
        ]);
      }
    } else {
      return response()->json([
        'message' => 'User not found',
      ]);
    }
  }

}

In the above code snippet, AuthController.php contains three function Login, Register, and Logout. Also, class constructor contains a unique token. Let’s  discuss those functions in detail:

Login Function, require email id and password. And return unique access token. Which is used in further API calls where user authentication is required.

Register Function,  require name, email, and password. And return the user details with an access token. Also, you can check this. I’m using Laravel default validator for the validations. The Validator check for required fields, minimum character length and most important check for unique email and password. If an email and phone no already registered then validator thrown an error.

Both functions Login and Register store the unique api_token in the database. When Login API called then the new api_token will be generated and stored in the database.

Logout Function, require only access token in the form of the request header. In our example, we are using a Bearer Token that means Bearer keyword is added to the token. We will split this keyword at the time of the query for the user check. Then simply forget this token, so that token is not valid for the further API calls.

Setup API Route

Laravel provides an option to make separate all the API routes from the web-routes. All the API routes added in the api.php located at routes directory.

Route::prefix('v1')->namespace('API')->group(function () {
  // Login
  Route::post('/login','AuthController@postLogin');

  // Register
  Route::post('/register','AuthController@postRegister');

  // Protected with APIToken Middleware
  Route::middleware('APIToken')->group(function () {
    // Logout
    Route::post('/logout','AuthController@postLogout');
  });
});

We are using a prefix to add additional value to the API URL.

After setup the route, time to test our API’s.

Register a new user using API.

Laravel 5.6 Custom Token Base API Authentication

Register API returns name, email, and access_token. An access token is used in further API call. The app developer can use this token to authenticate the users.

Login a registered user.

Laravel 5.6 Custom Token Base API Authentication

Login API returns same as like register API.

Logout API

Laravel 5.6 Custom Token Base API Authentication

Logout API receive request header with key Authorization. And return message after success. If a token is not found in the database then an error is thrown.

Conclusion

In this article, we will discuss the Laravel 5.6 Custom Token Base API Authentication. I know lots of packages available to achieve this kind of functionality such as JWT Authentication, Laravel Passport and many more. We will discuss those in future. Hope the basic idea behind the token base API is clear to you. Please feel free to add the comment if any query.

Leave A Reply

Your email address will not be published.

4 Comments
  1. Orihime says

    How to add filters like sortBy, search, perPage etc etc??

    1. Code Briefly says

      Hi Orihime,

      Please update your question, where you want to apply those filters?

  2. Md Nazim Mahmud khan says

    Hi,

    Nice tutorial. But do you think the middleware is correct? Your middleware checks if the token exists only. But it should also check where the token resembles with the access_token stored in database during login.

    Thank you.

    1. Code Briefly says

      Hi Md Nazim M. Khan,

      Yes, In this example middleware just check token is available in the request or not. You can extend this middleware per your requirement.