← Back to list

Laravel Auth API Standard: Secure and Scalable Authentication Solution by Faizan Ali

Discover the Laravel Auth API Standard, a secure and scalable authentication solution developed by Faizan Ali. This API standard simplifies…

Faizan Rafique · 2024-09-12 07:07 · 1 claps · 5.8 min read
#laravel #api #auth #auth-api #sectum
Open on Medium ↗

Laravel Auth API Standard: Secure and Scalable Authentication Solution by Faizan Ali

Discover the Laravel Auth API Standard, a secure and scalable authentication solution developed by Faizan Ali. This API standard simplifies the integration of strong authentication features into your Laravel projects, ensuring better security and a seamless user experience. Perfect for developers looking for an efficient and reliable way to manage user authentication.

  1. Set Up the Laravel Project

Use the following command to start a new Laravel project if you haven’t already:

composer create-project --prefer-dist laravel/laravel your-project-name
  1. Open the directory for your project:
cd your-project-name

3. Configuring the Database

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=api_db
DB_USERNAME=root
DB_PASSWORD=

4. Open your file directory routes/api.php and paste these route in your file

This code snippet defines routes for a Laravel application that handles user authentication and profile management using API endpoints. Here’s a brief explanation:

  1. Register and Login:
  • Route::post('register', [UserController::class, 'Register']);: This route allows users to register by sending a POST request to the /register endpoint.
  • Route::post('login', [UserController::class, 'Login']);: This route allows users to log in by sending a POST request to the /login endpoint.
  1. Authenticated Routes (Protected by Sanctum Middleware):
  • The routes inside the Route::group are protected by the auth:sanctum middleware, meaning they can only be accessed by authenticated users.
  • Route::get('profile', [UserController::class, 'GetProfile']);: Fetches the authenticated user's profile data.
  • Route::post('update_profile', [UserController::class, 'UpdateProfile']);: Allows the authenticated user to update their profile information.
  • Route::post('update_password', [UserController::class, 'UpdatePassword']);: Enables the authenticated user to change their password.
  • Route::post('logout', [UserController::class, 'Logout']);: Logs out the authenticated user, ending their session.
<?php

use App\Http\Controllers\Api\UserController;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;

/*
|--------------------------------------------------------------------------
| API Routes
|--------------------------------------------------------------------------
|
| Here is where you can register API routes for your application. These
| routes are loaded by the RouteServiceProvider and all of them will
| be assigned to the "api" middleware group. Make something great!
|
*/

//Register Api
Route::post('register', [UserController::class, 'Register']);
Route::post('login', [UserController::class, 'Login']);
//get profile
Route::group(['middleware' => ['auth:sanctum']], function(){
    Route::get('profile', [UserController::class, 'GetProfile']);
    Route::post('update_profile', [UserController::class, 'UpdateProfile']);
    Route::post('update_password', [UserController::class, 'UpdatePassword']);
    Route::post('logout', [UserController::class, 'Logout']);
});

5. Make a UserController

The UserController in Laravel is responsible for managing user authentication and profile-related operations. It handles user registration, login, profile retrieval, profile updates, password changes, and logout functionality, ensuring a smooth and secure user experience within your Laravel application.

<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Http\Requests\Api\LoginUser;
use App\Http\Requests\Api\UpdatePassword;
use App\Http\Requests\Api\UserRegister;
use App\Http\Resources\Api\ProfileResource;
use App\Http\Resources\Api\UpdateProfile;
use App\Models\ActivityLog;
use App\Models\User;
use App\Services\ImageService;
use Illuminate\Auth\Events\Registered;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;

class UserController extends Controller
{
    //Register a user then return a token
    public function Register(UserRegister $request)
    {
            $user = new User();
            $user->name = $request->name;
            $user->email = $request->email;
            $user->password = bcrypt($request->password);
            $user->fcm_token = $request->fcm_token;
            if($request->hasFile('image')){
                $user->image = ImageService::addImage('images/user_profile', $request->image, 'ProfileImage_');
            }
            $user->save();
            $token = $user->createToken('API Token')->plainTextToken;
            return $this->success(data: [
                'token' => $token
            ], message: 'Successfully Registered');

    }
    //Login a user then return a token
    public function Login(LoginUser $request)
    {
        $user = User::where(function ($query) use ($request) {
            $query->where('email', $request->email)->first();
        })->first();
        if (!$user)
            return $this->error(message: 'Incorrect Email',code: 403);
        if (!auth()->loginUsingId((password_verify($request->password, $user->password)) ? $user->id : 0))
            return $this->error(message: 'Incorrect Password',code: 403);
        $user = auth()->user();
        $token = $user->createToken('API TOKEN')->plainTextToken;
        return $this->success(data: [
            'token' => $token,
        ], message: 'Logged in successfully');
    }
    //Get Profile
    public function GetProfile(Request $request)
    {
        $user = auth()->user();
        $result = ProfileResource::make($user);

        return $this->success(data: $result, message: 'Success');
    }
    //update profile
    public function UpdateProfile(Request $request){

            $auth_user = Auth::user();
            $auth_user->name = $request->input('name') ? $request->input('name') : Auth::user()['name'];
            if($request->image == null){
                if(basename(Auth::user()['image']) == 'avatar.png'){
                    $auth_user->image = null;
                }
                else{
                    $auth_user->image = basename(Auth::user()['image']);
                }
            }
            else{
                $auth_user->image = ImageService::updateImage('images/user_profile',$request->image, Auth::user()['image'],'ProfileImage_');
            }
            $auth_user->save();

            return $this->success(data: [
                'data' => UpdateProfile::make($auth_user),
            ], message: 'Profile updated successfully');

    }
    //change password
    public function UpdatePassword(UpdatePassword $request){
        if (!Hash::check($request->old_password, Auth::user()['password'])) {
            return $this->error(message: 'Old password not matched', code: 403);
        }else {
            User::where('email', Auth::user()['email'])->update(['password' => bcrypt($request->new_password)]);


            return $this->success(data: null, message: 'Password updated successfully');
        }
    }
    //logout
    public function Logout(Request $request){
        $request->user()->currentAccessToken()->delete();
        return $this->success(data: null, message: 'Logged out successfully');
    }
}

6. Make a Service for Image add and update App\Services\ImageService;

<?php

namespace App\Services;

/**
 * Class ImageService
 * @package App\Services
 */
class ImageService
{
    //Add image
    public static function addImage($path, $image, $imageName) {

            $filename = strtolower(
                uniqid($imageName)
                .'.'
                .$image->getClientOriginalExtension()
            );
            str_replace(' ', '-', $filename);
            return basename($image->move($path, $filename));
    }
    //update image
    public static function updateImage($path, $image, $oldImage,$imageName) {
        $filename = strtolower(
            uniqid($imageName)
            .'.'
            .$image->getClientOriginalExtension()
        );
        str_replace(' ', '-', $filename);
        $move_image =  basename($image->move($path, $filename));
        //delete Old Image
        $image_path = public_path().'/'.$path.'/'.basename($oldImage);
        if (file_exists($image_path)) {
            unlink($image_path);
        }
        //end delete Old Image
        return $move_image;
    }
    // Add Multiple images
    public static function addMultipleImage($path, $images, $imageName) {
        $imgData = [] || null;
        foreach ($images as $file) {
            $filename = strtolower(uniqid($imageName).'.'.$file->getClientOriginalExtension());
            $file->move($path, $filename);
            $imgData[] = $filename;
        }
        return json_encode($imgData);
    }
}

7. Makes request UserRegister, LoginUser, and UpdatePassword

php artisan make:request Api/UserRegister
php artisan make:request Api/LoginUser
php artisan make:request Api/UpdatePassword

Api/UserRegister

<?php

namespace App\Http\Requests\Api;

use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;

class UserRegister extends FormRequest
{
    /**
     * Determine if the user is authorized to make this request.
     */
    public function authorize(): bool
    {
        return true;
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array<string, \Illuminate\Contracts\Validation\Rule|array|string>
     */
    public function rules(): array
    {
        return [
            'name'          => ['required', 'string', 'max:255'],
            'email'         => ['required', 'string', 'email', 'max:255', 'unique:users'],
            'fcm_token'     => ['string'],
            'password'      => ['required', 'string'],
            'confirm_password' => ['required', 'same:password'],
            'image'        => ['file', 'mimes:jpeg,png,jpg,gif,svg', 'max:2048'],

        ];
    }
    //coustom error message
    public function messages()
    {
        return [
            'name.required' => 'Name is required',
            'email.required' => 'Email is required',
            'password.required' => 'Password is required',
            'email.unique' => 'Email already exist',
        ];
    }
    //change validation error response
    protected function failedValidation(\Illuminate\Contracts\Validation\Validator $validator)
    {
        throw new \Illuminate\Validation\ValidationException($validator, response()->json([
            'message' => $validator->errors()->first(),
            'data' => null,
        ], 422));
    }

}

Api/LoginUser

<?php

namespace App\Http\Requests\Api;

use Illuminate\Foundation\Http\FormRequest;

class LoginUser extends FormRequest
{
    /**
     * Determine if the user is authorized to make this request.
     */
    public function authorize(): bool
    {
        return true;
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array<string, \Illuminate\Contracts\Validation\Rule|array|string>
     */
    public function rules(): array
    {
        return [
            //
            'email' => ['required', 'string', 'email', 'max:255'],
            'password' => ['required', 'string'],
        ];
    }
    public function messages()
    {
        return [
            'email.required' => 'Email is required',
            'password.required' => 'Password is required',
        ];
    }
    //change validation error response
    protected function failedValidation(\Illuminate\Contracts\Validation\Validator $validator)
    {
        throw new \Illuminate\Validation\ValidationException($validator, response()->json([
            'message' => $validator->errors()->first(),
            'data' => null,
        ], 422));
    }
}

Api/UpdatePassword

<?php

namespace App\Http\Requests\Api;

use Illuminate\Foundation\Http\FormRequest;

class UpdatePassword extends FormRequest
{
    /**
     * Determine if the user is authorized to make this request.
     */
    public function authorize(): bool
    {
        return true;
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array<string, \Illuminate\Contracts\Validation\Rule|array|string>
     */
    public function rules(): array
    {
        return [
            'old_password' => ['required', 'string'],
            'new_password'      => ['required', 'string'],
            'confirm_new_password' => ['required', 'same:new_password'],
        ];
    }
    //coustom error message
    public function messages()
    {
        return [
            'old_password.required' => 'Old Password is required',
            'new_password.required' => 'Password is required',
        ];
    }
    //change validation error response
    protected function failedValidation(\Illuminate\Contracts\Validation\Validator $validator)
    {
        throw new \Illuminate\Validation\ValidationException($validator, response()->json([
            'message' => $validator->errors()->first(),
            'data' => null,
        ], 422));
    }
}

8. Make a Trait file for response of api App\Traits\CanResponseTrait;

<?php

namespace App\Traits;

use Illuminate\Http\JsonResponse;
use Symfony\Component\HttpFoundation\Response;

trait CanResponseTrait
{
    /**
     * The Success Response Method for API
     *
     * @param mixed|null $data Data to be sent
     * @param string $message Message to be sent
     * @param int $code Status code to be sent
     * @return JsonResponse Response that will be sent
     */
    protected function success(
        string $message = 'success',
        int    $code = Response::HTTP_OK,
        mixed  $data = null,
    ): JsonResponse
    {
        return response()->json([
            'message' => $message,
            'data' => $data
        ], status: $code);
    }
    /**
     * The Error Response Method for API
     *
     * @param mixed|null $data Data to be sent
     * @param string $message Message to be sent
     * @param int $code Status code to be sent
     * @return JsonResponse Response that will be sent
     */
    protected function error(
        mixed  $data = null,
        string $message = 'error',
        int    $code = Response::HTTP_BAD_REQUEST
    ): JsonResponse
    {
        return response()->json([
            'message' => $message,
            'data' => $data
        ], status: $code);
    }

    /**
     * The NotFound Response Method for API
     *
     * @param mixed|null $data Data to be sent
     * @param string $message Message to be sent
     * @param int $code Status code to be sent
     * @return JsonResponse Response that will be sent
     */
    protected function notFound(
        mixed  $data = null,
        string $message = 'not found',
        int    $code = Response::HTTP_NOT_FOUND
    ): JsonResponse
    {
        return response()->json([
            'message' => $message,
            'data' => $data
        ], status: $code);
    }
}

Register your Traits in your controller App\Http\Controllers\Controller.php

<?php

namespace App\Http\Controllers;

use App\Traits\CanResponseTrait;
use App\Traits\FailedValidation;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Foundation\Validation\ValidatesRequests;

abstract class Controller
{
    //
    use AuthorizesRequests, ValidatesRequests, CanResponseTrait;
}

메타데이터
post_id
5962103fd704
slug
laravel-auth-api-standard-secure-and-scalable-authentication-solution-by-faizan-ali-5962103fd704
url
https://medium.com/@faizanrafique/laravel-auth-api-standard-secure-and-scalable-authentication-solution-by-faizan-ali-5962103fd704
canonical_url
https://medium.com/@faizanrafique/laravel-auth-api-standard-secure-and-scalable-authentication-solution-by-faizan-ali-5962103fd704
author_url
https://medium.com/@faizanrafique
status
ok
fetched_at
2026-07-19 21:38:15