Kokil Thapa - Professional Web Developer in Nepal
Freelancer Web Developer in Nepal with 15+ Years of Experience

Kokil Thapa is an experienced full-stack web developer focused on building fast, secure, and scalable web applications. He helps businesses and individuals create SEO-friendly, user-focused digital platforms designed for long-term growth.

API Security OWASP API Top 10 Checklist

By Kokil Thapa | Last reviewed: August 2026

Shipping a public or partner-facing API without a structured security review is a liability, especially when handling payments, legal documents, or personal data. The API Security OWASP API Top 10 Checklist provides the definitive framework for identifying and mitigating the most critical vulnerabilities in modern REST and GraphQL endpoints. In my experience building legal-tech portals and eCommerce systems in Nepal, applying this checklist during development—not as an afterthought—prevents costly breaches and compliance failures.

What Is the API Security OWASP API Top 10 Checklist and Why Does It Matter?

The OWASP API Security Top 10 (2023 edition, current through 2026) differs fundamentally from the traditional web application Top 10 because APIs expose structured data and business logic directly to clients, often bypassing browser-based protections. While traditional web security focuses heavily on XSS and CSRF, API security centers on authorization flaws, excessive data exposure, and automated abuse. For developers building Laravel APIs, this distinction is critical: your routes are your attack surface, and every endpoint must be treated as potentially hostile.

In practice, I have found that three categories account for over 80% of real-world API incidents in production systems I maintain: Broken Object Level Authorization (API1), Broken Authentication (API2), and Unrestricted Resource Consumption (API4). These are not theoretical; they manifest as users accessing other customers' invoices, tokens that never expire, and bots scraping entire databases through paginated endpoints. The checklist forces you to address these systematically rather than relying on ad-hoc fixes after a penetration test.

OWASP Risks → Laravel Defense LayersAPI1: BOLAMissing Object AuthZAPI2: Broken AuthWeak Token / SessionAPI4: Rate LimitingUnrestricted ResourcesPolicy + Model Binding$user->can('view', $model)Sanctum / PassportToken Scopes + ExpiryThrottle Middlewareper-user + global limitsShared Foundation: Input Validation + Logging + HTTPSForm Requests • Structured Logs • TLS 1.3 • CORS Policy
Mapping OWASP API Top 10 risks to specific Laravel defense mechanisms prevents gaps between theory and implementation.

For teams in Nepal working with limited security budgets, this checklist also serves as a communication tool with clients. When building platforms like legal-tech portals that handle sensitive case files, demonstrating compliance with OWASP standards builds trust more effectively than vague assurances about "security." It transforms security from an abstract concern into a verifiable engineering deliverable.

How Do You Prevent Broken Object Level Authorization (BOLA) in Laravel APIs?

BOLA (API1) is consistently the #1 vulnerability because it exploits a fundamental assumption: that authenticated users only access their own resources. In reality, if your controller fetches a record by ID without verifying ownership, any authenticated user can enumerate and access all records. This is especially dangerous in multi-tenant systems, legal portals, and eCommerce order APIs where data isolation is non-negotiable.

Use Policies and Route Model Binding Together

Laravel’s authorization policies combined with implicit route model binding provide the most reliable defense against BOLA. Never trust client-supplied IDs without server-side verification. Here is the pattern I use on every resource endpoint:

<?php
// app/Policies/DocumentPolicy.php
namespace App\Policies;

use App\Models\Document;
use App\Models\User;

class DocumentPolicy
{
    public function view(User $user, Document $document): bool
    {
        // Strict ownership check - no exceptions
        return $document->user_id === $user->id 
            || $user->hasRole('admin');
    }
    
    public function update(User $user, Document $document): bool
    {
        return $document->user_id === $user->id;
    }
}
<?php
// app/Http/Controllers/Api/DocumentController.php
public function show(Document $document): JsonResource
{
    // Policy automatically invoked via model binding
    $this->authorize('view', $document);
    
    return new DocumentResource($document);
}

// In routes/api.php - implicit binding enforces policy
Route::apiResource('documents', DocumentController::class)
    ->middleware(['auth:sanctum']);

A common mistake is checking authorization inside the controller method but forgetting to apply it to related resources. If a document has attachments, each attachment endpoint must independently verify the parent document’s ownership. Chained authorization checks prevent horizontal privilege escalation through nested relationships.

Avoid Direct Database Queries Without Context

Raw queries bypass Laravel’s authorization layer entirely. When building reporting or search endpoints, always scope queries to the authenticated user’s context:

  • Use global scopes for tenant isolation when appropriate
  • Never expose primary keys in URLs if sequential enumeration is a risk; use UUIDs or hashed identifiers
  • Log authorization failures separately from general errors for security monitoring
  • Test BOLA explicitly in your test suite with assertions that verify User A cannot access User B’s resources

How Should You Handle Authentication and Token Management Securely?

Broken Authentication (API2) encompasses weak token generation, missing expiration, insufficient entropy, and improper session handling. For Laravel APIs in 2026, Sanctum remains the standard for SPAs and mobile apps, while Passport serves OAuth2 server requirements. Both require explicit configuration to avoid default insecure states.

Configure Token Lifetimes and Scopes Explicitly

Default Sanctum tokens never expire unless configured. This violates OWASP API2 guidelines. Set reasonable expiration based on your application’s risk profile:

// config/sanctum.php
'expiration' => 60 * 24, // 24 hours for mobile apps
// For high-security legal portals: 60 * 2 (2 hours)

// When issuing tokens with scopes
$token = $user->createToken(
    'mobile-app',
    ['documents:read', 'documents:write'],
    now()->addHours(2)
)->plainTextToken;

Scopes limit damage from compromised tokens. A token stolen from a mobile device should not grant admin privileges or access to unrelated subsystems. Define granular scopes matching your API’s functional boundaries, and validate them in middleware or policy checks.

Secure Token Storage and Transmission

Tokens transmitted over HTTP or stored in localStorage are vulnerable to interception and XSS. For SPAs, use Sanctum’s cookie-based authentication with SameSite=Strict and Secure flags. For mobile and third-party integrations, transmit tokens only over HTTPS and store them in secure platform keystores, never in plaintext preferences or logs.

I have encountered production systems where API keys were logged in plaintext during debugging, then exposed through log aggregation services. Configure your logging to redact Authorization headers and token parameters. Laravel’s $exceptions->dontReport() and custom log formatters help prevent accidental credential leakage.

Secure Token Lifecycle (Sanctum)1. AuthenticatePOST /loginEmail + PasswordRate Limited2. Issue TokencreateToken()Scoped + TTLHashed in DB3. Validateauth:sanctumCheck Scope + TTLLoad User4. RevokedeleteToken()Logout / ExpireImmediateCritical Configuration Defaults to ChangeSet expiration • Define scopes • Enable hash verification • Configure SameSite cookies❌ Anti-Patterns• Tokens without expiry• Storing tokens in localStorage• Logging raw Authorization headers✅ Secure Patterns• Short-lived scoped tokens• HttpOnly + Secure cookies for SPAs• Token rotation + revocation endpoint
Complete token lifecycle management prevents broken authentication vulnerabilities in Laravel Sanctum APIs.

How Do You Implement Effective Rate Limiting and Prevent Resource Exhaustion?

Unrestricted Resource Consumption (API4) enables denial-of-service attacks, brute-force attempts, and cost amplification through unbounded queries. Every public API endpoint must enforce rate limits proportional to business value and infrastructure capacity. Laravel’s throttle middleware provides the foundation, but effective protection requires layered configuration.

Configure Tiered Rate Limits

Apply different limits based on authentication state, endpoint sensitivity, and user tier. Anonymous endpoints need aggressive limits; authenticated endpoints can be more permissive but still bounded:

// routes/api.php
use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Support\Facades\RateLimiter;

// In RouteServiceProvider or bootstrap/app.php
RateLimiter::for('api', function (Request $request) {
    return $request->user()
        ? Limit::perMinute(120)->by($request->user()->id)
        : Limit::perMinute(20)->by($request->ip());
});

RateLimiter::for('auth-sensitive', function (Request $request) {
    return Limit::perMinute(5)->by($request->ip());
});

// Apply to routes
Route::post('/login', [AuthController::class, 'login'])
    ->middleware('throttle:auth-sensitive');

Route::apiResource('/documents', DocumentController::class)
    ->middleware(['auth:sanctum', 'throttle:api']);

Protect Against Expensive Operations

Rate limiting alone does not prevent single requests that consume disproportionate resources. Paginate all list endpoints with maximum page size enforcement. Set query timeouts for complex aggregations. Validate file upload sizes and processing complexity before accepting payloads. On a recent eCommerce project, we prevented catalog scraping by combining rate limits with pagination caps and response-time monitoring that triggered temporary blocks for slow-query patterns.

Endpoint TypeRecommended LimitRationale
Authentication (login/register)5/min/IPPrevent brute force; legitimate users rarely exceed this
Password reset / OTP3/min/IP + 10/hour/emailPrevent enumeration and SMS/email bombing
Authenticated read (lists)60–120/min/userBalance UX with abuse prevention
Authenticated write (create/update)30–60/min/userWrites are costlier; lower limits acceptable
File uploads10/min/user + size validationStorage and processing cost multiplier
Search / complex queries20–30/min/user + timeoutDatabase-intensive; prevent query flooding

How Do You Validate Input and Prevent Mass Assignment Vulnerabilities?

Broken Object Property Level Authorization (API3) and Mass Assignment (related to API6) occur when APIs accept fields users should not modify. Laravel’s Form Requests and explicit allowlists are your primary defenses. Never pass $request->all() directly to model creation or updates.

Use Dedicated Form Requests with Explicit Rules

Define separate request classes for create and update operations. Specify exactly which fields are permitted and validate types, lengths, and formats:

<?php
// app/Http/Requests/Api/UpdateProfileRequest.php
class UpdateProfileRequest extends FormRequest
{
    public function rules(): array
    {
        return [
            'name' => ['required', 'string', 'max:255'],
            'phone' => ['nullable', 'string', 'regex:/^9[78][0-9]{8}$/'],
            // email, role, is_admin intentionally excluded
        ];
    }
    
    public function validated($key = null, $default = null): array
    {
        // Only returns fields defined in rules()
        return parent::validated($key, $default);
    }
}

// Controller receives only safe fields
public function update(UpdateProfileRequest $request): JsonResource
{
    $request->user()->update($request->validated());
    return new UserResource($request->user());
}

This pattern prevents mass assignment even if the model’s $fillable array is misconfigured. Defense in depth matters: validate at the request level AND restrict at the model level. For APIs accepting nested objects or arrays, validate each nested structure explicitly. Laravel’s array.* validation syntax handles this, but test edge cases where attackers send unexpected nesting depths or type confusion payloads.

Sanitize Output to Prevent Excessive Data Exposure

API6 (Unrestricted Access to Sensitive Business Flows) and API3 overlap when responses include fields clients should not see. Use API Resources to transform models before serialization. Never return Eloquent models directly from controllers. Define explicit field lists in resources and conditionally include sensitive attributes based on authorization context.

Request → Validation → Safe Processing → Sanitized ResponseRaw Request{name, role, is_admin,password, ...}Form Requestrules() allowlistRejects: role, is_admin422 if invalidController$request->validated()Safe fields onlyAPI ResourcetoArray() explicitNo hidden fieldsVulnerability Path (Without Controls)Raw Input → $request->all() → Model::create() → Full Model JSON → Attacker Gains AdminSecure Pipeline Checklist✓ Form Request with explicit rules ✓ validated() only ✓ Model $guarded/$fillable ✓ API Resource ✓ No direct model returns✓ Nested validation for arrays ✓ Type coercion disabled ✓ File upload MIME + size checks ✓ SQL injection safe (Eloquent/parameterized)
Layered input validation and output transformation prevents mass assignment and excessive data exposure in Laravel APIs.

How Do You Audit and Maintain API Security Continuously?

Security is not a one-time checklist completion; it requires ongoing verification as code changes. Integrate automated scanning into your CI pipeline using tools like ZAP API Scan or OWASP crAPI against staging environments. Complement automation with manual testing focused on business logic flaws that scanners miss—authorization bypasses through parameter manipulation, race conditions in concurrent operations, and workflow violations.

Maintain a living security document alongside your API documentation. Map each endpoint to its corresponding OWASP controls, note known limitations, and track remediation status. When onboarding new developers or handing off projects to clients in Nepal or internationally, this documentation transfers security context that code comments cannot convey. Review it quarterly and after any significant feature release.

Monitor production for anomalies: sudden spikes in 401/403 responses indicate probing; unusual payload sizes suggest injection attempts; geographic anomalies may signal credential compromise. Laravel’s logging combined with external monitoring services provides visibility without excessive overhead. For server-level security, ensure your infrastructure complements application-layer controls with WAF rules, TLS enforcement, and network segmentation.

Implementing the API Security OWASP API Top 10 Checklist in Production

The API Security OWASP API Top 10 Checklist becomes actionable when embedded in your development workflow rather than treated as a compliance exercise. Start by auditing existing endpoints against BOLA and authentication controls—the highest-impact items. Then systematically address rate limiting, input validation, and data exposure. For new projects, make the checklist part of your definition of done for every API feature.

If you are building or auditing an API and need hands-on implementation support, reach out to discuss your specific requirements. Whether you are securing a legal portal, eCommerce platform, or SaaS product, practical security guidance grounded in real production experience beats generic advice every time.

Frequently Asked Questions

It is a standardized list of the ten most critical security risks specific to REST and GraphQL APIs, updated for 2023. Unlike general web app lists, it targets API-specific vectors like broken object-level authorization, unrestricted resource consumption, and unsafe direct object references that traditional WAFs often miss.

Broken Object Level Authorization (BOLA) specifically describes when an API endpoint exposes object IDs without validating if the authenticated user owns or has permission to access that specific resource. While similar to IDOR, BOLA emphasizes the API contract failure where sequential or predictable IDs allow attackers to enumerate and modify other users' data simply by changing parameters in GET, PUT, or DELETE requests.

API authentication mechanisms are often weaker than browser-based sessions because they rely on static tokens, API keys passed in headers, or JWTs without proper expiration. Attackers exploit credential stuffing, weak token generation, or missing rate limiting on login endpoints. In my experience integrating payment gateways like eSewa or Khalti, improper webhook signature verification also falls under this category, allowing forged transaction confirmations.

This occurs when APIs expose sensitive object properties through mass assignment or excessive data exposure without field-level permission checks. For example, a user profile update endpoint might accept a role or isAdmin parameter because the backend model allows mass assignment. I prevent this in Laravel using explicit Form Request validation rules and DTOs rather than passing raw request arrays directly to Eloquent models.

Implement strict rate limiting, pagination caps, and payload size validation at both the application and infrastructure levels. In Laravel 12, use the throttle middleware with Redis backing to enforce per-user or per-IP limits. Configure Nginx or Apache to reject oversized JSON bodies before they reach PHP-FPM. Without these controls, a single malicious script can exhaust server memory or database connections through unbounded queries or file uploads.

SSRF in APIs happens when endpoints accept URLs or hostnames as input and make backend requests without validation. Attackers target internal metadata services, cloud provider credentials, or private network resources. On AWS EC2 instances I manage, I block outbound traffic to 169.254.169.254 except for specific trusted processes. Always validate and whitelist destination hosts, never pass user-supplied URLs directly to HTTP clients like Guzzle.

Disable verbose error responses, remove default credentials, enforce HTTPS-only transport, and set restrictive CORS policies. Ensure debug mode is false in production .env files and that stack traces never leak via JSON responses. During Deployer 7 releases for client projects, I verify opcache invalidation and PHP-FPM reloads so stale configurations don't persist. Regular automated scans catch drift between intended and actual security posture.

Organizations often lose track of deprecated, shadow, or versioned API endpoints that remain accessible but unpatched. An old v1/users endpoint might lack authentication added in v2. Maintain an OpenAPI specification as the single source of truth and automate route discovery against deployed code. In Laravel, audit registered routes regularly and remove unused controllers. Unmanaged endpoints are frequent entry points because defenders forget they exist.

This risk focuses on your API trusting data from third-party services without validation. When integrating external providers for SMS, payments, or identity verification, assume their responses could be tampered with or malformed. Validate schemas, verify signatures, and handle unexpected fields defensively. I've seen production issues where a payment callback returned altered amounts that were accepted blindly, causing financial discrepancies until we added strict response validation.

Implementation costs vary from Rs 50,000 to Rs 300,000 (USD 375–2,250) depending on existing codebase maturity and team expertise. Most mitigations involve configuration changes, middleware additions, and validation logic rather than expensive tooling. Budget primarily for developer time auditing endpoints and writing tests, not for premium security products.

No. Traditional WAFs struggle with API-specific attacks like BOLA or business logic abuse because they inspect payloads, not authorization context. A WAF helps with SQL injection or XSS but cannot determine if User A should access Resource B. Defense requires application-layer authorization checks, proper input validation, and API-aware security testing alongside infrastructure protections.

Use Postman or Insomnia for manual authorization testing, ZAP or Burp Suite Professional for automated scanning, and schemathesis for property-based fuzzing against OpenAPI specs. For Laravel applications, packages like laravel-api-tester help validate endpoint behavior. Combine automated tools with manual review of authorization logic, since scanners frequently miss context-dependent BOLA flaws that require understanding your domain model.

Audit during every major release, after significant dependency upgrades, and quarterly for stable systems. The OWASP list evolves; the 2023 edition replaced several 2019 entries. Integrate lightweight checks into CI pipelines using tools like spectral for OpenAPI linting. Full penetration testing annually catches accumulated drift. Treat the checklist as a living development standard, not a one-time compliance checkbox.

No. Sanctum handles token issuance and session authentication but does not enforce object-level authorization. You must still implement policies or explicit ownership checks in controllers and services. Sanctum confirms who the user is; your application logic must verify what they can access. Relying solely on authentication middleware while skipping policy gates is a common BOLA source in Laravel APIs I've reviewed.

Treating the checklist as a compliance exercise rather than integrating it into development workflows. Teams scan once, fix findings, then introduce new vulnerabilities in subsequent sprints. Embed authorization tests in feature branches, require OpenAPI spec updates with code changes, and make security review part of merge criteria. Sustainable API security comes from habitual practices, not periodic audits.

Share this article

Quick Contact Options
Choose how you want to connect me: