## Getting Started
### Minimal Setup
1. **Installation**
```bash
composer require jimtools/basic-auth
Add the middleware to your Laravel HTTP kernel (app/Http/Kernel.php):
protected $routeMiddleware = [
// ...
'basic.auth' => \Jimtools\BasicAuth\Middleware\BasicAuth::class,
];
First Use Case
Protect a route in routes/web.php:
Route::get('/admin', function () {
return response()->json(['message' => 'Admin Dashboard']);
})->middleware('basic.auth');
Authorization header (Basic <base64-encoded-username:password>).users table for validation (username = email, password = hashed).Where to Look First
BasicAuth (core logic).Jimtools\BasicAuth\Contracts\UserProvider interface for custom user resolution (introduced in v1.0.0).Illuminate\Http\Request).Basic Route Protection
Route::group(['middleware' => 'basic.auth'], function () {
Route::get('/secure', 'SecureController@index');
});
auth middleware for hybrid auth:
->middleware(['basic.auth', 'auth:sanctum']);
Custom User Providers Override the default user resolver via a service provider (new in v1.0.0):
// app/Providers/BasicAuthServiceProvider.php
public function register()
{
$this->app->bind(\Jimtools\BasicAuth\Contracts\UserProvider::class, function ($app) {
return new CustomUserProvider();
});
}
Jimtools\BasicAuth\Contracts\UserProvider:
use Jimtools\BasicAuth\Contracts\UserProvider;
class CustomUserProvider implements UserProvider {
public function retrieveByCredentials($username, $password) {
// Custom logic here
}
}
PSR-15 Middleware Integration Use with frameworks like Slim or Lumen by wrapping the middleware:
$app->middleware(BasicAuth::class);
API Token Fallback (New Pattern)
Extend the middleware to support hybrid auth (e.g., Bearer tokens):
public function handle($request, Closure $next)
{
if ($request->bearerToken()) {
return $next($request->withHeader('Authorization', 'Bearer ' . $request->bearerToken()));
}
return parent::handle($request, $next);
}
auth:sanctum for token-based auth while keeping Basic Auth for legacy clients.throttle middleware:
->middleware(['basic.auth', 'throttle:60,1']);
auth.failed event:
Auth::failed(function ($request, $credentials) {
\Log::warning("Basic Auth failed for IP: {$request->ip()}", $credentials);
});
UserProvider contract to add tenant-aware authentication out of the box.Case-Sensitive Usernames
users table treats email (username) as case-insensitive, but Basic Auth sends raw credentials. Fix: Normalize the username in your UserProvider:
$user = User::where('email', strtolower($username))->first();
Base64 Decoding Issues
Authorization headers (e.g., missing Basic prefix) will throw exceptions. Fix: Add validation in the middleware:
if (!str_starts_with($header, 'Basic ')) {
return response()->json(['error' => 'Invalid Authorization header'], 401);
}
Caching Headers
Cache-Control: no-store in responses to prevent accidental caching of sensitive pages.CSRF Token Conflicts
Route::middleware('web')->group(function () {
// CSRF protected routes
});
Route::middleware('api.basic.auth')->group(function () {
// Basic Auth only (no CSRF)
});
dd($request->header('Authorization')) to inspect the raw header.UserProvider:
public function retrieveByCredentials($username, $password)
{
\Log::debug("Auth attempt for user: $username");
return User::where('email', $username)->first();
}
basic.auth runs before other middleware that might modify the request (e.g., trimStrings, convertEmptyStringsToNull).Custom Responses
Override the unauthorized() method in the middleware:
protected function unauthorized()
{
return response()->json([
'error' => 'Unauthorized',
'message' => 'Invalid credentials or missing Authorization header'
], 401);
}
Multi-Tenant Support (New in v1.0.0)
Extend the UserProvider to support tenant-aware authentication:
public function retrieveByCredentials($username, $password, $tenantId = null)
{
return User::where('email', $username)
->where('tenant_id', $tenantId)
->first();
}
Two-Factor Fallback Integrate with Laravel’s 2FA:
if (!$user->hasVerifiedEmail()) {
return redirect()->route('verification.notice');
}
Performance
UserProvider for repeated requests:
$user = cache()->remember("basic-auth-user-{$username}", now()->addMinutes(10), function () use ($username) {
return User::where('email', $username)->first();
});
UserProvider eager-loads relationships if needed.UserProvider interface is now stable and optimized for performance.
NO_UPDATE_NEEDED was incorrect—here’s the **updated assessment** reflecting the v1.0.0 release (minor clarifications, emphasis on new patterns like `UserProvider` contract, and multi-tenant support). Key additions:
1. Highlighted the `UserProvider` contract as a new extension point.
2. Added multi-tenant support as a new pattern.
3. Clarified that v1.0.0 is the initial stable release (no breaking changes).
4. Updated debugging/extension sections to reflect the new contract-based architecture.
How can I help you explore Laravel packages today?