Example of Token Based API Authentication System in Laravel 7 using the Sanctum/Airlock package

5 years ago 5 mins read Bhavin Tank

Example of Token Based API Authentication System in Laravel 7 using the Sanctum/Airlock package

GitHub repository: https://github.com/bhavin-tank/sanctum-laravel-7

Create new laravel project by running following command in the terminal

laravel new api-authentication

or

composer create-project --prefer-dist laravel/laravel api-authentication

Create new database called api_authentication and configure database (DB_DATABASE=api_authentication) connectivity in .env file in your project root directory.

Now install the Laravel Sanctum/Airlock Package

composer require laravel/sanctum

Publish the Sanctum configuration and migration files using the vendor:publish Artisan by running following command in the terminal. After run publish command sanctum configuration file will be placed in your config directory.

php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"

Run your database migrations

php artisan migrate

Add the Sanctum's middleware to your api middleware group within your app/Http/Kernel.php

use Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful;

'api' => [
    EnsureFrontendRequestsAreStateful::class,
    'throttle:60,1',
    \Illuminate\Routing\Middleware\SubstituteBindings::class,
],

Add HasApiTokens to the User model in app/User.php.

use Laravel\Sanctum\HasApiTokens;

class User extends Authenticatable
{
    use HasApiTokens, Notifiable;
}

config/cors.php

<?php

return [
  'paths' => ['api/*'],
  'allowed_methods' => ['*'],
  'allowed_origins' => ['*'],
  'allowed_origins_patterns' => [],
  'allowed_headers' => ['*'],
  'exposed_headers' => [],
  'max_age' => 0,
  'supports_credentials' => true,
];

routes/api.php

<?php

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;

Route::namespace('V1')->prefix('v1')->group(function () {
  Route::namespace('Auth')->group(function () {
    Route::post('/login', 'AuthController@login');
    Route::post('/registration', 'AuthController@registration');
    Route::middleware('auth:sanctum')->group(function () {
      Route::Delete('/logout', 'AuthController@logout');
      Route::Delete('/logout-from-all-device', 'AuthController@logoutFromAllDevice');
    });
  });
  Route::middleware('auth:sanctum')->group(function () {
    Route::prefix('user')->group(function () {
      Route::get('/', function (Request $request) {
        return $request->user();
      });
    });
  });
});

app/Http/Controllers/BaseController.php

<?php


namespace App\Http\Controllers;
use Symfony\Component\HttpFoundation\Response as ResponseCode;


class BaseController extends Controller
{
    /**
     * success response method.
     *
     * @return \Illuminate\Http\Response
     */
    public function sendResponse($result, $message)
    {
        $response = [
            'success' => true,
            'data'    => $result,
            'message' => $message,
        ];
        return response()->json($response, ResponseCode::HTTP_OK);
    }



    /**
     * return error response.
     *
     * @return \Illuminate\Http\Response
     */
    public function sendError($error, $errorMessages = [], $code = ResponseCode::HTTP_NOT_FOUND)
    {
        $response = [
            'success' => false,
            'message' => $error,
        ];
        if(!empty($errorMessages)){
            $response['data'] = $errorMessages;
        }
        return response()->json($response, $code);
    }
}

app/Http/Controllers/V1/Auth/AuthController.php

<?php

namespace App\Http\Controllers\V1\Auth;

use App\Http\Controllers\BaseController;
use App\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Symfony\Component\HttpFoundation\Response as ResponseCode;
use Validator;

class AuthController extends BaseController
{
  public function registration(Request $request)
  {
    $validator = Validator::make($request->all(), [
      'name' => 'required',
      'email' => 'required|email|unique:users',
      'password' => 'required',
      'confirm_password' => 'required|same:password',
    ]);

    if ($validator->fails()) {
      return $this->sendError('Validation Error.', $validator->errors(), ResponseCode::HTTP_UNPROCESSABLE_ENTITY);
    }

    $input = $request->all();
    $input['password'] = bcrypt($input['password']);
    $user = User::create($input);
    $success = $user;
    $success['token'] = $user->createToken($request->header('User-Agent'))->plainTextToken;

    return $this->sendResponse($success, 'User register successfully.');
  }

  public function login(Request $request)
  {
    $request->validate([
      'email' => 'required|email',
      'password' => 'required',
    ]);

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

    if (!$user || !Hash::check($request->password, $user->password)) {
      return $this->sendError('Unauthorised.', ['error' => 'The provided credentials are incorrect.'], ResponseCode::HTTP_UNAUTHORIZED);
    }

    $success = $user;
    $success['token'] = $user->createToken($request->header('User-Agent'))->plainTextToken;

    return $this->sendResponse($success, 'User login successfully.');
  }

  public function logout()
  {
    auth()->user()->currentAccessToken()->delete();
    return $this->sendResponse([], 'User logout successfully.');
  }

  public function logoutFromAllDevice()
  {
    auth()->user()->tokens()->delete();
    return $this->sendResponse([], 'User logout successfully.');
  }
}

Registration: POST http://127.0.0.1:8000/api/v1/registration

// Request parameters
{
    "name": "Bhavin Tank",
    "email": "bhavintank16@gmail.com",
    "password": "123456789",
    "confirm_password": "123456789"
}

// Response
{
    "success": true,
    "data": {
        "name": "Bhavin Tank",
        "email": "bhavintank16@gmail.com",
        "updated_at": "2020-04-11T04:38:59.000000Z",
        "created_at": "2020-04-11T04:38:59.000000Z",
        "token": "gHMQpe3tP2GQoHPZvOTIY3xugoWpPHrtUVXhz40PYVf7tmBRxkM53Wbme4zhhfOsThWYhLCpXyHfjcHz"
    },
    "message": "User register successfully."
}

Login: POST http://127.0.0.1:8000/api/v1/login

// Request parameters
{
    "email": "bhavintank16@gmail.com",
    "password": "123456789"
}

// Response
{
    "success": true,
    "data": {
        "name": "Bhavin Tank",
        "email": "bhavintank16@gmail.com",
        "email_verified_at": null,
        "created_at": "2020-04-11T04:38:59.000000Z",
        "updated_at": "2020-04-11T04:38:59.000000Z",
        "token": "rNw9eI0DePRsdTZ4wDC4JJvTQdokeCowvc8i2H1sX37KqHlt3LSTxAfi5NO6NEPGKZs3hJdu2jt1wcQl"
    },
    "message": "User login successfully."
}

Logout: DELETE http://127.0.0.1:8000/api/v1/logout

// Request with header parameter
key: Authorization
value: Bearer rNw9eI0DePRsdTZ4wDC4JJvTQdokeCowvc8i2H1sX37KqHlt3LSTxAfi5NO6NEPGKZs3hJdu2jt1wcQl

// Response
{
    "success": true,
    "data": [],
    "message": "User logout successfully."
}

Logout from all device: DELETE http://127.0.0.1:8000/api/v1/logout-from-all-device

// Request with header parameter
key: Authorization
value: Bearer rNw9eI0DePRsdTZ4wDC4JJvTQdokeCowvc8i2H1sX37KqHlt3LSTxAfi5NO6NEPGKZs3hJdu2jt1wcQl

// Response
{
    "success": true,
    "data": [],
    "message": "User logout from all device successfully."
}

User Details: GET http://127.0.0.1:8000/api/v1/user

// Request with header parameter
key: Authorization
value: Bearer rNw9eI0DePRsdTZ4wDC4JJvTQdokeCowvc8i2H1sX37KqHlt3LSTxAfi5NO6NEPGKZs3hJdu2jt1wcQl

// Response
{
    "name""Bhavin Tank",
    "email""bhavintank16@gmail.com",
    "email_verified_at"null,
    "created_at""2020-04-11T04:38:59.000000Z",
    "updated_at""2020-04-11T04:38:59.000000Z"
}
Token Based API Authentication System Airlock Laravel Sanctum/Airlock Sanctum Laravel 7
James Lee

Bhavin Tank

Full Stack Developer