Back to Blog

How to Build Login and Register REST API in Laravel 12

Admin User

April 18, 2026
14
0

How to Build Login and Register REST API in Laravel 12

uilding secure authentication is one of the first steps when developing modern web or mobile applications. Instead of traditional session-based login systems, developers now prefer REST APIs to handle user authentication because they work seamlessly with frontend frameworks and mobile apps.

In this tutorial, you will learn how to build a Login and Register REST API in Laravel 12 step by step. We will create API endpoints for user registration and login, return authentication tokens, and test everything using tools like Postman.

By the end of this guide, you will have a fully functional authentication API in Laravel 12 that can easily be integrated with React, React Native, Flutter, or any other frontend framework. This approach is widely used for building scalable applications such as mobile apps, SaaS platforms, and modern single-page applications (SPAs).

Step 1: Open your terminal create new project 

composer create-project --prefer-dist laravel/laravel laravel-api-auth
aravel-api-auth

Step 2: Open the migration file which located at

Databae/migration/2026_04_12_000000_create_users_table
public function up()
{
    Schema::create('users', function (Blueprint $table) {
        $table->id();
        $table->string('name');
        $table->string('email')->unique();
        $table->timestamp('email_verified_at')->nullable();
        $table->string('password');
       $table->tinyInteger('status')->default(1); // 1 = Active, 0 =        Inactive
        $table->rememberToken();
        $table->timestamps();
    });
}

Step 03: Update User Model 

<?php
namespace App\Models;

// use Illuminate\Contracts\Auth\MustVerifyEmail;
use App\Models\Employee;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Notifications\Notifiable;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Spatie\Permission\Traits\HasRoles;
use Laravel\Sanctum\HasApiTokens; // Add this line

class User extends Authenticatable
{
    use SoftDeletes;
    use Notifiable;
    use HasRoles;
    use HasApiTokens; // Add this trait
    
    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $guarded = [];
    
    public function role(){
        return $this->hasMany(Role::class,'role');
    }

    public function employee()
    {
        return $this->hasOne(Employee::class);
    }

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'name', 'email', 'password',
    ];

    /**
     * The attributes that should be hidden for arrays.
     *
     * @var array
     */
    protected $hidden = [
        'password', 'remember_token',
    ];

    /**
     * The attributes that should be cast to native types.
     *
     * @var array
     */
    protected $casts = [
        'email_verified_at' => 'datetime',
    ];
}

Step 4: Open your Termianl And Create AuthController 

php artisan make:controller Api/AuthController

Next, we will create an AuthController inside the Api directory to manage user authentication. This controller will handle important authentication operations such as user registration, login, and logout.

By organizing these functions inside a dedicated controller, we keep our API structure clean and maintainable. The AuthController will process incoming requests, validate user data, authenticate credentials, and return appropriate API responses such as authentication tokens and success messages.

This controller will serve as the main entry point for handling authentication in our Laravel 12 REST API. 

<?php

namespace App\Http\Controllers\Api\Auth;

use App\Http\Controllers\Controller;
use App\Models\User;
use Spatie\Permission\Models\Role;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Validation\ValidationException;
use Illuminate\Support\Facades\Validator;

class AuthController extends Controller
{
    /**
     * Register new user
     */
    public function register(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'name'     => 'required|string|max:255',
            'email'    => 'required|email|unique:users',
            'password' => 'required|string|min:6|confirmed',
            'role'     => 'required|string',
        ]);

        if ($validator->fails()) {
            return response()->json([
                'errors' => $validator->errors()
            ], 422);
        }

        try {
            $user = User::create([
                'name'     => $request->name,
                'email'    => $request->email,
                'password' => Hash::make($request->password),
            ]);

            $role = Role::where('name', $request->role)->first();
            if ($role) {
                $user->assignRole($role->name);
            }

            // Create token for immediate login after registration
            $token = $user->createToken('auth_token')->plainTextToken;

            return response()->json([
                'message' => 'User registered successfully',
                'user' => $user,
                'access_token' => $token,
                'token_type' => 'Bearer',
                'roles' => $user->getRoleNames(),
                'permissions' => $user->getAllPermissions()->pluck('name')
            ], 201);

        } catch (\Exception $e) {
            return response()->json([
                'message' => 'Registration failed',
                'error' => $e->getMessage()
            ], 500);
        }
    }

    /**
     * Login user
     */
    public function login(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'email'    => 'required|string|email',
            'password' => 'required|string',
        ]);

        if ($validator->fails()) {
            return response()->json([
                'errors' => $validator->errors()
            ], 422);
        }

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

        if (!$user || !Hash::check($request->password, $user->password)) {
            return response()->json([
                'message' => 'Invalid email or password',
            ], 401);
        }

        try {
            // Revoke all existing tokens (optional - for single device login)
            // $user->tokens()->delete();

            $token = $user->createToken('auth_token')->plainTextToken;

            return response()->json([
                'message' => 'Login successful',
                'user'    => $user,
                'access_token' => $token,
                'token_type' => 'Bearer',
                'roles' => $user->getRoleNames(),
                'permissions' => $user->getAllPermissions()->pluck('name')
            ]);

        } catch (\Exception $e) {
            return response()->json([
                'message' => 'Login failed',
                'error' => $e->getMessage()
            ], 500);
        }
    }

    /**
     * Logout user
     */
    public function logout(Request $request)
    {
        try {
            $request->user()->currentAccessToken()->delete();

            return response()->json([
                'message' => 'Logged out successfully',
            ]);

        } catch (\Exception $e) {
            return response()->json([
                'message' => 'Logout failed',
                'error' => $e->getMessage()
            ], 500);
        }
    }

    /**
     * Get authenticated user
     */
    public function user(Request $request)
    {
        try {
            $user = $request->user();
            
            return response()->json([
                'user' => $user,
                'roles' => $user->getRoleNames(),
                'permissions' => $user->getAllPermissions()->pluck('name')
            ]);

        } catch (\Exception $e) {
            return response()->json([
                'message' => 'Failed to fetch user data',
                'error' => $e->getMessage()
            ], 500);
        }
    }
}

Step 5: Defind Api Routes:

<?php

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

/*
|--------------------------------------------------------------------------
| API Routes
|--------------------------------------------------------------------------
|
| Here is where you can register API routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| is assigned the "api" middleware group. Enjoy building your API!
|
*/ 
Route::post('/register', [AuthController::class, 'register']);
Route::post('/login', [AuthController::class, 'login']);

Route::middleware('auth:sanctum')->group(function () {
    Route::post('/logout', [AuthController::class, 'logout']);
    Route::get('/user', [AuthController::class, 'user']); 
});

API Endpoints Overview

POST /api/register – Register a new user

POST /api/login – Authenticate user and return token

POST /api/logout – Logout authenticated user and revoke token

GET /api/user – Get currently authenticated user details

Using auth:sanctum middleware ensures that protected routes can only be accessed with a valid authentication token.

Testing APIs in Postman

Finally, you can test all these APIs using Postman.

  1. Register API
    • Method: POST
    • URL: http://127.0.0.1:8000/api/register
    • Body (JSON):
{
    "name": "John Doe",
    "email": "john@example.com",
    "password": "12345678",
    "password_confirmation": "12345678"
}
  1. Login API
    • Method: POST
    • URL: http://127.0.0.1:8000/api/login
  2. Get User API
    • Method: GET
    • URL: http://127.0.0.1:8000/api/user
    • Add Header:
Authorization: Bearer YOUR_TOKEN
  1. Logout API
    • Method: POST
    • URL: http://127.0.0.1:8000/api/logout
    • Add Header:
Authorization: Bearer YOUR_TOKEN

Once these endpoints are tested successfully in Postman, your Laravel 12 Login and Register REST API is ready to integrate with any frontend or mobile application.