Skip to main content
Laravel, shipping fast.

Here's what happens when a request arrives:

Client sends: GET /api/licenses
              Header: Authorization: Bearer abc123


Router matches route, checks middleware


EnsureTokenIsValidMiddleware:
    - Extract token "abc123"
    - Cache key: "bearer:abc123"
    - Cache hit? Return cached Bearer model
    - Cache miss? Query database, cache, return
    - Valid? Not expired? Domain matches?
    → If yes, continue
    → If no, return 401


throttle:api-token:
    - Check rate limit for token
    - 60 per minute, 45 remaining?
    → If under limit, continue
    → If over limit, return 429


AddRateLimitHeadersMiddleware:
    - Calculate remaining quota
    - Add headers: X-RateLimit-*


LogApiRequestsMiddleware:
    - Set defer callback to log this request
    - Continue to controller


LicenseServiceProvider::boot():
    - Inspect token settings
    - Set Config to use correct driver
    - Set driver credentials from token


LicenseController::show():
    - Call LicenseFacade::licenses()
    - Facade uses configuration from token
    - Returns LicenseDTO[]
    - Maps to LicenseResource
    - Wraps in CollectionResponse


Response flows back through middleware (bottom to top)


LogApiRequestsMiddleware:
    - Execute deferred callback
    - Queue SendToLogsJob
    - (Happens asynchronously, doesn't block response)


Response sent to client with:
    - Status 200
    - Rate limit headers
    - JSON body


SendToLogsJob executes in queue:
    - Write log entry with request details
    - Token hashed, not exposed
    - Audit trail complete

All of this happens automatically. No controller code has to think about authentication, rate limiting, logging, or configuration. It's all enforced by middleware, all consistent, all proven.

Testing Authentication

Security patterns are only valuable if they're tested. Test everything:

test('valid bearer token is accepted', function () {
    $bearer = Bearer::factory()->create();

    $response = $this->withHeader('Authorization', "Bearer {$bearer->token}")
        ->get('/api/licenses');

    expect($response->status())->toBe(200);
});

test('missing token is rejected', function () {
    $response = $this->get('/api/licenses');
    expect($response->status())->toBe(401);
});

test('expired token is rejected', function () {
    $bearer = Bearer::factory()->expired()->create();

    $response = $this->withHeader('Authorization', "Bearer {$bearer->token}")
        ->get('/api/licenses');

    expect($response->status())->toBe(401);
});

test('token is rejected if domain does not match', function () {
    $bearer = Bearer::factory()
        ->withDomains(['https://allowed-domain.com'])
        ->create();

    $response = $this->withHeader('Authorization', "Bearer {$bearer->token}")
        ->get('/api/licenses');

    expect($response->status())->toBe(401);
});

test('rate limit is enforced', function () {
    $bearer = Bearer::factory()->create();
    $token = $bearer->token;

    for ($i = 0; $i < 60; $i++) {
        $this->withHeader('Authorization', "Bearer $token")
            ->get('/api/licenses');
    }

    $response = $this->withHeader('Authorization', "Bearer $token")
        ->get('/api/licenses');

    expect($response->status())->toBe(429);
});

Each test verifies one security guarantee. Collectively, they ensure your authentication layer is solid.