Rate Limiting
Per-endpoint named rate limiters protect authentication flows from
brute-force and abuse. Driven entirely by config/boilerplate.php and
applied via Laravel’s standard throttle: middleware.
Endpoints covered
| Limiter | Routes | Default |
|---|---|---|
auth-login | POST /auth/{app,web}/login | 10 / min |
auth-register | POST /auth/{app,web}/register | 5 / min |
auth-otp_issue | POST /auth/{app,web}/otp | 5 / min |
auth-otp_verify | POST /auth/{app,web}/otp/verify | 10 / min |
auth-password_forgot | POST /auth/{app,web}/forgot-password | 3 / min |
auth-social | POST /auth/{app,web}/social/{provider}/... | 10 / min |
auth-email_verify_resend | POST /auth/email/verification-notification | 6 / min |
App-token and Web-cookie routes share the same bucket per limiter — they’re the same logical operation.
Bucket key
<limiter>|<user_id> # when authenticated
<limiter>|<client_ip> # otherwise
Configuration
'auth' => [
'rate_limit' => [
'enabled' => env('AUTH_RATE_LIMIT_ENABLED', true),
'limits' => [
'login' => ['max' => 10, 'per_minutes' => 1],
'register' => ['max' => 5, 'per_minutes' => 1],
'otp_issue' => ['max' => 5, 'per_minutes' => 1],
// ...
],
],
],
AUTH_RATE_LIMIT_ENABLED=false bypasses every limiter at runtime — limits
are re-read per request, so it also works via config()->set(...) in tests.
Throttle response
HTTP/1.1 429 Too Many Requests
Retry-After: 60
Content-Type: application/json
{ "message": "Too many requests." }
The 429 envelope comes from the API exception renderer, not the throttle middleware — so the message is configurable like any other response.
Adding a limiter
-
Register a limit in config:
'limits' => [ 'export_pdf' => ['max' => 2, 'per_minutes' => 5], ], -
Apply the middleware:
Route::post('/exports/pdf', ...)->middleware('throttle:auth-export_pdf');
RateLimitServiceProvider auto-registers a limiter for every key, prefixed
auth-. For a fully custom limiter (e.g. by role), define it with
RateLimiter::for(...) in your own provider.