Securing APIs With Sanctum and Middleware

Introduction

API security has become one of the most essential parts of modern web development. As applications grow increasingly interconnected—serving mobile apps, single-page applications, and third-party integrations—API endpoints become primary entry points for attackers. A secure API ensures that only authorized users, applications, and services can access or modify data. Laravel Sanctum and middleware offer a complete, flexible, and powerful approach to securing your REST APIs. Sanctum uses lightweight authentication tokens and integrates seamlessly with Laravel’s middleware pipeline, enabling robust access control with almost no complexity.

Sanctum allows your API to authenticate users using personal access tokens, SPA authentication, or mobile tokens—without the complexity of OAuth. Combined with middleware such as auth:sanctum, throttle, role/permission checks, and custom security layers, Sanctum provides a clean yet strong security architecture. This long-form post explores Sanctum in great depth, covering how it works, how to protect private endpoints, how tokens are handled, how middleware enhances security, and how to build a fully secure, scalable API using Laravel’s built-in tools.

Understanding Laravel Sanctum

What Sanctum Is

Sanctum is Laravel’s lightweight API authentication system. It is specifically designed to secure:

  • Mobile applications
  • Single-page applications (SPAs)
  • Third-party API consumers
  • Internal systems
  • Personal developer tokens

It offers a simpler alternative to OAuth while still providing strong security.

Why Sanctum Is Popular

Simplicity

No need to manage complex OAuth flows.

Flexibility

It works for SPAs, token-based APIs, and mobile apps.

First-Class Laravel Integration

Sanctum uses Laravel’s authentication system and middleware.

Token Abilities

Each token may have specific permissions (abilities).

Low Overhead

Easy to set up and maintain.

Sanctum is the perfect choice for modern API development.


How Sanctum Works

Personal Access Tokens

When a user logs in via your API, you generate a token:

$token = $user->createToken(‘api-token’)->plainTextToken;

This token is then included in the Authorization header of every API request:

Authorization: Bearer your_token_here

Sanctum validates this token automatically.

Token Storage

Tokens are stored in the personal_access_tokens table—encrypted and secure.

Each token belongs to a user and may have optional abilities (permissions).

Token Validation

Sanctum checks:

  • The token exists
  • The token has not been revoked
  • The token matches the hash
  • The token has required abilities

If everything checks out, the request proceeds.


Protecting Endpoints Using Middleware

The auth:sanctum Middleware

This middleware ensures that only valid token owners can access private routes.

Example:

Route::middleware(‘auth:sanctum’)->group(function () {
Route::get(‘/user’, function (Request $request) {
return $request->user();
});
});

Any request without a valid Sanctum token is denied.

How the Middleware Works

When the request arrives:

  1. The middleware extracts the Bearer token
  2. Sanctum checks token validity
  3. It verifies the user identity
  4. It attaches the authenticated user to the request
  5. Controller logic executes only if token is valid

If token is invalid, a 401 Unauthorized response is returned.


Creating Secure API Authentication

Step 1: Install Sanctum

composer require laravel/sanctum

Step 2: Publish Configuration

php artisan vendor:publish –provider=”Laravel\Sanctum\SanctumServiceProvider”

Step 3: Run Migration

php artisan migrate

Step 4: Add Sanctum Middleware

In api middleware group:

‘auth:sanctum’,

Step 5: Issue Tokens

$user->createToken(‘device_name’)->plainTextToken;

Now your API can authenticate token holders.


Building Secure API Login Flows

Login Endpoint Example

User submits credentials.
If valid, issue token:

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 response()->json(['error' => 'Invalid credentials'], 401);  
} return response()->json([
'token' => $user->createToken('api-token')->plainTextToken  
]);

}


Securing Private Routes

Example of Protected Route Group

Route::middleware(‘auth:sanctum’)->group(function () {
Route::get(‘/dashboard’, function () {
return ‘Private content’;
});
});

Only requests with a valid token may access these endpoints.

What Happens If an Attack Happens Without a Token?

Laravel responds with:

401 Unauthorized
{ “message”: “Unauthenticated.” }

This prevents access before it reaches your controller.


Sanctum Token Abilities (Permissions)

Sanctum allows assigning abilities to tokens.
Example:

$token = $user->createToken(‘token-name’, [‘create’, ‘update’]);

Middleware can check these abilities:

if ($request->user()->tokenCan(‘update’)) {
// Allowed
}

Token abilities offer fine-grained control similar to roles/permissions.


Combining Sanctum With Roles and Permissions

Why Combine Sanctum With Roles?

Sanctum handles authentication.
Roles manage authorization.

This creates a full security system.

Example With Role Check

Inside a controller:

if ($request->user()->role !== ‘admin’) {
return response()->json([‘error’ => ‘Forbidden’], 403);
}

Using Permission Packages

Popular packages like Spatie make it easy to manage roles and permissions.

Example:

$user->hasPermissionTo(‘delete product’);

This, combined with Sanctum, creates a highly secure API.


Rate Limiting APIs

Laravel includes rate limiting middleware out of the box.

Example routes/api.php:

Route::middleware([‘auth:sanctum’, ‘throttle:60,1’])->group(function () {
Route::get(‘/profile’, …);
});

This limits requests to 60 per minute per user/token.

Rate limiting prevents:

  • Brute-force attacks
  • Abuse
  • Performance issues

Middleware Layers for API Security

Middleware executes before your controller handles the request.
It acts as a wall protecting your API.

Common middleware used with Sanctum:

auth:sanctum

Validates tokens.

throttle

Limits request frequency.

verified

Ensures email verification.

can

Checks authorization abilities.

custom middleware

You can write security rules tailored to your application.

Middleware creates a powerful security chain.


Building a Complete Secure API Flow

Step 1: Authenticate User

User logs in → receives a token.

Step 2: Use Token in Requests

Each request includes:

Authorization: Bearer token

Step 3: auth:sanctum Middleware Validates the Token

Only valid tokens allow access.

Step 4: Implement Authorization

Use:

  • token abilities
  • roles
  • policies
  • permissions

Step 5: Rate Limit Requests

Throttle middleware protects your API.

Step 6: Log Activity

Activity logs help detect suspicious behavior.

Step 7: Encrypt Sensitive Data

Never expose sensitive info in API responses.

This creates a full security workflow.


Protecting CRUD APIs With Sanctum

CRUD APIs are frequently targeted because they manage critical resources.

Example:

Route::apiResource(‘products’, ProductController::class)->middleware(‘auth:sanctum’);

This ensures that:

  • Listing
  • Creating
  • Updating
  • Deleting

can only be done by authenticated tokens.


Example of a Fully Secured Controller

Inside each controller method:

public function update(Request $request, Product $product)
{
if (! $request->user()->tokenCan(‘update’)) {
return response()->json([‘error’ => ‘Forbidden’], 403);
}

$product->update($request->all());  
return response()->json($product);  

}

Token abilities protect sensitive operations.


Token Revocation

Revoke Token on Logout

$request->user()->currentAccessToken()->delete();

Revoke All Tokens

$request->user()->tokens()->delete();

Revoking tokens is essential when:

  • A device is lost
  • A session expires
  • A user logs out
  • A security breach occurs

Sanctum makes this easy.


Expiring Tokens for Security

Tokens remain valid forever unless revoked.
For higher security, manually expire tokens:

$token->forceFill([‘expires_at’ => now()->addDays(7)])->save();

Or delete old tokens via a cron job.


Protecting Public and Private APIs

Public Endpoints

Visible to everyone:

Route::get(‘/products’, …);

Private Endpoints

Require authentication:

Route::get(‘/orders’, …)->middleware(‘auth:sanctum’);

Use middleware to divide access clearly.


Using Policies for Deeper Authorization

Policies ensure that only the resource owner can modify or delete it.

Example:

public function update(User $user, Product $product)
{
return $user->id === $product->owner_id;
}

Use with:

$this->authorize(‘update’, $product);

Policies give you professional-level security.


Custom Security Middleware

You can write your own security rules:

php artisan make:middleware EnsureUserIsActive

Inside handle():

if (! $request->user()->is_active) {
return response()->json([‘error’ => ‘Account inactive’], 403);
}

Apply to routes:

->middleware(‘active’)

Custom middleware helps tailor security for specific business needs.


Common API Attack Types (Sanctum Helps Prevent Them)

Token Theft

Using HTTPS prevents sniffing.
Sanctum validates and revokes tokens.

Brute Force

Throttle middleware blocks repeated attempts.

Unauthorized Access

auth:sanctum ensures only valid tokens enter.

Privilege Escalation

Roles and policies prevent users from performing unauthorized actions.

Data Tampering

Sanctum ties actions to authenticated users.

CSRF Attacks

Sanctum handles SPA authentication securely.

Sanctum is a complete protection layer against common attacks.


Best Practices for Securing APIs with Sanctum and Middleware

Always Use HTTPS

Never send tokens over plain HTTP.

Rotate Tokens Regularly

Delete and reissue tokens periodically.

Limit Token Abilities

Never give a token more permissions than it needs.

Use Policies for Complex Permissions

Organize and centralize authorization logic.

Separate Admin and User Tokens

Admin tokens should have more security checks.

Keep Middleware Lean

Avoid heavy operations inside middleware.

Validate All Input

Sanctum secures access but not data quality.

Monitor Logs

Failed token attempts indicate attacks.


Advanced Security Practices

Device-Based Token Naming

Use meaningful device names:
phone_ipad_2025
office_laptop_chrome

Token Fingerprinting

Compare device/user-agent information with stored metadata.

Automatic Token Revocation

Revoke tokens after suspicious activity.

Limit Number of Tokens per User

Prevent abuse by restricting token count.

Scoped API Keys

Give external developers scoped keys that limit access.


When to Use Sanctum vs Passport

Sanctum is ideal for:

  • SPAs
  • Mobile apps
  • Internal APIs
  • Lightweight authentication

Passport is ideal for:

  • First-party and third-party OAuth
  • Complex external authentication
  • Enterprise-level integration

Sanctum is lightweight, fast, and perfect for most modern APIs.


Logging and Monitoring API Activity

Log API Usage

Log every authenticated request.

Store IP Addresses

Track unusual access patterns.

Create an Audit Log

Store:

  • User
  • Endpoint
  • HTTP method
  • Timestamp
  • Token ID

Monitoring strengthens your security posture.


Example API Workflow Using Sanctum

  1. User logs in using email/password
  2. Server issues a personal access token
  3. User stores token securely on the client
  4. All API requests include the Bearer token
  5. auth:sanctum middleware verifies the token
  6. Role/permission middleware checks authorization
  7. Controller executes logic
  8. Response returned
  9. User logs out → token revoked

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *