Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Super Basic Auth Laravel Package

sven/super-basic-auth

A super simple Laravel package for HTTP Basic authentication. Protect routes with middleware and validate against configurable credentials—no database, no login forms, just lightweight basic auth.

View on GitHub
Deep Wiki
Context7

Getting Started

What it is: a single-middleware package that puts an HTTP Basic Auth prompt in front of your Laravel routes, checking credentials against config/env values instead of a users table. It is for gating access to an environment, not for authenticating real users.

Install and wire up (5 minutes):

composer require sven/super-basic-auth
php artisan vendor:publish --tag=config   # publishes config/super-basic-auth.php

Set credentials in .env (never in the repo):

SUPER_BASIC_AUTH_USERNAME=preview
SUPER_BASIC_AUTH_PASSWORD='a-long-random-string'

Where to look first, in order:

  1. config/super-basic-auth.php — confirm the exact key names and whether it supports multiple users or a single credential pair.
  2. The service provider — check how the middleware alias is registered (super-basic-auth, basic.auth, etc.) and whether it auto-applies to anything.
  3. vendor/sven/super-basic-auth/src/ — the middleware is ~30 lines; read it once so you know exactly what it compares and what it returns on failure.

First real use case: protect a staging site. Add the middleware to the web group in bootstrap/app.php (Laravel 11+) or app/Http/Kernel.php (10 and below):

// Laravel 11: bootstrap/app.php
->withMiddleware(function (Middleware $middleware) {
    $middleware->web(append: [\Sven\SuperBasicAuth\Middleware\SuperBasicAuth::class]);
})
// Laravel 10: app/Http/Kernel.php
protected $middlewareGroups = [
    'web' => [
        // ...
        \Sven\SuperBasicAuth\Middleware\SuperBasicAuth::class,
    ],
];

Load the site, get a browser prompt, enter the credentials, done. If you get a 401 with no prompt, the config isn't being read — check config:cache.

Implementation Patterns

Environment-scoped gating (the intended pattern). Only set the env vars on environments that need protection — staging, UAT, client preview, demo boxes. Leave them unset locally and in production so the middleware no-ops (verify this behaviour in the source; if it hard-fails when unset, guard it with an if in your middleware registration instead of relying on the package).

Route-group scoping. Instead of the whole app, apply it to specific groups — admin panels, prototypes, a /docs route — so public marketing pages stay untouched:

Route::middleware('super-basic-auth')->group(function () {
    Route::get('/preview', PreviewController::class);
});

Layering with real auth. Basic auth is a cheap outer wall; the app's own auth middleware still runs inside it. Order matters: list basic auth before auth so unauthenticated requests are stopped at the door rather than hitting session/DB work. This is a useful pattern for "internal tools behind a shared password, per-user logins inside."

Uptime monitors and health checks. Your monitoring service won't send credentials. Exclude the health endpoint:

Route::get('/up', fn () => response('ok'))->withoutMiddleware(SuperBasicAuth::class);

Or scope the middleware to a route group that excludes /up and /livewire/* (Livewire's endpoint also breaks under basic auth if hit from a page the browser cached credentials for — usually fine, but worth testing).

Preview deployments in CI. Inject the credentials at deploy time rather than committing them: Forge/Envoyer/Vapor env vars, GitHub Actions secrets written into .env, or a php artisan tinker --execute step. Pair with php artisan config:cache in the deploy script so the values are baked in and the config file read is skipped per-request.

API testing convenience. Because it's plain Authorization: Basic ..., curl/Postman/HTTP clients work with no extra setup:

curl -u "$SUPER_BASIC_AUTH_USERNAME:$SUPER_BASIC_AUTH_PASSWORD" https://staging.example.com/api/thing

That also makes it easy to script smoke tests against a protected environment.

Combining with throttle. Basic auth does no rate limiting or lockout. If the host is publicly reachable, add throttle:30,1 next to it, otherwise credential guessing is unlimited (albeit slow over the network).

Gotchas and Tips

Config caching will bite you. Change SUPER_BASIC_AUTH_PASSWORD in .env, forget php artisan config:cache, and nothing changes. On any environment with cached config, make the cache rebuild part of the deploy — and remember config:clear locally after editing env values.

Special characters in .env. # starts a comment, spaces need quoting, and $ is interpolated. Always single-quote passwords: SUPER_BASIC_AUTH_PASSWORD='p@ss$word#1'. A silently truncated password is the #1 cause of "the credentials are right but it 401s."

HTTPS only. Basic auth sends base64-encoded credentials on every request — trivially decodable on the wire. Never apply this middleware to an HTTP-only host, and never reuse a password that matters elsewhere.

No logout. Browsers cache Basic credentials for the session/realm. Users can't "log out" without closing the browser or using a private window, and some browsers keep sending the header after a 401. If you need revocation, you can't have it — rotate the password in env and redeploy. Tell stakeholders this up front; it's the most common complaint with preview links shared to clients.

401 vs. redirect. Laravel's auth middleware returns a redirect to a login page; this one returns a bare 401 with a WWW-Authenticate header. If a feature test expects a redirect, it will fail — assert assertUnauthorized() / check the WWW-Authenticate: Basic header instead.

Middleware ordering. If basic auth is appended to the web group after StartSession/ShareErrorsFromSession, sessions and CSRF run before the gate — wasteful and occasionally confusing (you'll see sessions created for rejected requests). Prefer prepend or a route-group-level assignment over append when you care.

Laravel version compatibility. v2.6.0 exists purely to restore Laravel 9 & 10 support — there are no new features or behaviour changes, so nothing in the usage patterns above shifts. Note what it does not claim: the release notes say nothing about Laravel 11/12, so the earlier advice still holds — check composer.json constraints before installing there. The middleware itself is trivial; the risk is the service provider using APIs that moved. If the alias isn't picked up on Laravel 11, register it manually in bootstrap/app.php:

->withMiddleware(fn (Middleware $m) => $m->alias('super-basic-auth', SuperBasicAuth::class))

Because this release only re-widens the version floor, treat the constraint as something to pin deliberately. If you're on Laravel 10 and already running an older 2.x, bumping to ^2.6 is a safe patch-level move; if you're on 11/12, the release gives you no new information and you're still relying on the middleware being framework-agnostic enough to work unaliased.

Single credential pair only. Don't try to model teams, roles, or per-user auditing on top of this — there is no user identity beyond the username string. If requirements grow even slightly ("each client gets their own login"), replace it with Laravel's built-in auth.basic against a users table or a proper package; the migration is one middleware swap because the HTTP contract is identical.

Extension points are thin, by design. If you need to trim the password, look up credentials from a database, or log failed attempts, don't fork — wrap it. Write a three-line middleware that checks your own condition and either returns abort(401, headers: ['WWW-Authenticate' => 'Basic realm="..."']) or calls $next($request). That keeps the package as a reference implementation rather than a dependency you're stuck with.

Testing. In feature tests, pass the header explicitly rather than fighting the browser prompt:

$this->withHeaders([
    'Authorization' => 'Basic '.base64_encode(config('super-basic-auth.username').':'.config('super-basic-auth.password')),
])->get('/preview')->assertOk();

And add one test asserting the unauthenticated case returns 401 — that's the behaviour you actually care about preserving when you refactor middleware registration.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core
nodisrupt/laravel-agent
sierratecnologia/media-manager