Building APIs with Laravel is a breeze—until abuse shows up.
Even with authentication and throttling, determined attackers can still hammer your API.
Here are some real-world abuse vectors I’ve faced:
- Brute force login attempts: Repeatedly trying credentials.
- OTP abuse: Spamming SMS/email verification endpoints.
- Resource scraping: Bots pulling massive amounts of data.
- API flooding: Attackers creating hundreds of accounts to spread requests.
Here’s how to detect abuse:
- Track failed login attempts per IP and per account.
- Monitor unusual patterns, like 50 OTP requests in 5 minutes.
- Use Laravel events
Building APIs with Laravel is a breeze—until abuse shows up.
You deploy a shiny new API, everything works in testing, and then… bad actors find it. Bots, scrapers, credential stuffers, you name it.Here’s the truth: an API that “just works” is not the same as an API that’s secure.
Let’s walk through how to bulletproof your Laravel APIs using Sanctum, rate limiting, and abuse detection strategies I’ve learned the hard way.
🔑 Step 1: Authenticate With Sanctum (Not Just Tokens in Headers)
Many devs start out with simple API tokens stored in headers. Easy, yes. Safe, no.
Laravel Sanctum gives you a much stronger approach:
- SPA Authentication: Uses cookies with CSRF protection for single-page apps.
- API Token Authentication: Lets you issue tokens with scopes (abilities).
- Mobile App Authentication: Works seamlessly with personal access tokens.
Here’s how you might issue a token:
$user = User::find(1); $token = $user->createToken('api-token', ['orders:read', 'orders:write']); return ['token' => $token->plainTextToken];
And protect your routes with abilities:
Route::get('/orders', function () { // Only users with 'orders:read' can access })->middleware(['auth:sanctum', 'abilities:orders:read']);
💡 Pro tip: Never give “all abilities” tokens unless you’re absolutely sure. Least privilege always wins.
🚦 Step 2: Apply Smart Rate Limiting
Laravel ships with a throttle middleware that makes rate limiting painless:
Route::middleware('throttle:60,1')->group(function () { Route::get('/api/data', [ApiController::class, 'data']); });
But here’s the thing: 60 requests per minute per IP isn’t always enough.
Attackers can rotate IPs or abuse valid user sessions.Better approach → Custom rate limiters:
use Illuminate\Cache\RateLimiting\Limit; use Illuminate\Support\Facades\RateLimiter; RateLimiter::for('api', function ($request) { return $request->user() ? Limit::perMinute(100)->by($request->user()->id) : Limit::perMinute(20)->by($request->ip()); });
Now you’re rate limiting per user ID and per IP.
🛡️ Step 3: Detect and Block Abuse
Even with authentication and throttling, determined attackers can still hammer your API.
Here are some real-world abuse vectors I’ve faced:
- Brute force login attempts: Repeatedly trying credentials.
- OTP abuse: Spamming SMS/email verification endpoints.
- Resource scraping: Bots pulling massive amounts of data.
- API flooding: Attackers creating hundreds of accounts to spread requests.
🔍 How to Detect Abuse
- Track failed login attempts per IP and per account.
- Monitor unusual patterns, like 50 OTP requests in 5 minutes.
- Use Laravel events (
FailedLogin
,Lockout
) to log incidents.
🚫 How to Block
- Temporary bans with
RateLimiter::tooManyAttempts
.- Captchas on critical endpoints (login, registration).
- Shadow banning scrapers (return fake or delayed responses).
🔄 Step 4: Token Rotation and Logout Handling
One mistake I made early: giving tokens that never expire.
With Sanctum, you can:
- Rotate tokens after login
- Expire them after inactivity
- Invalidate on logout
Example: deleting tokens on logout:
$request->user()->tokens()->delete();
This prevents old tokens from floating around forever.
✅ Step 5: Layer Your Defenses
A secure Laravel API isn’t about one feature. It’s about stacking defenses:
- Sanctum → Authentication with scopes
- Rate Limiting → Per user, per IP, per endpoint
- Abuse Detection → Logging and blocking patterns
- Token Rotation → Preventing long-term token abuse
- Monitoring & Alerts → Know when bad stuff happens
When you combine these, your API isn’t just “working”—it’s battle-ready.
📘 Want to Go Deeper?
This blog is just scratching the surface. If you’re building serious apps with Laravel and want to make them bulletproof, check out my book:
👉 Bulletproof Laravel: Write Code That Hackers Hate
It covers:
- API hardening (Sanctum, Passport, JWT)
- File upload security
- Database query safety
- Production deployment security
- Real-world case studies (like apps hacked because of debug mode!)
💬 Over to You
Have you ever had your Laravel API abused even with throttling on?
What strategies did you use to stop it?Let’s trade war stories in the comments 👇