bepo / sales-channel-basic-auth
HTTP Basic Auth gate for individual sales channels.
Package info
github.com/vanWittlaer/BepoSalesChannelBasicAuth
Type:shopware-platform-plugin
pkg:composer/bepo/sales-channel-basic-auth
Requires
- shopware/core: ~6.7.0
- shopware/storefront: ~6.7.0
Requires (Dev)
None
Suggests
None
Provides
None
Conflicts
None
Replaces
None
README
Protects an individual Shopware 6 sales channel with an HTTP Basic Auth prompt. Visitors without
credentials get a 401 and no content. Visitors with credentials get the real storefront —
same theme, same routes, same checkout — exactly as it will look once the channel goes public.
Protection is configured per sales channel, so a preview channel can be locked while every other channel on the same installation stays open.
This is not maintenance mode
Shopware already ships a per-channel gate, and it solves a different problem. Maintenance mode is
a public statement: it says "this shop is temporarily closed", answers 503 Service Unavailable
with a maintenance page, sets Retry-After, and lets exactly one group through — visitors whose
IP you put on the allowlist.
That is the right behaviour for taking a live shop down for an hour. It is the wrong behaviour for a channel that was never public in the first place.
| Maintenance mode | This plugin | |
|---|---|---|
| Says to the world | "temporarily closed, come back later" | "you are not authorised" |
| Response | 503 + rendered maintenance page |
401, no page rendered |
| Way through | IP allowlist only | a password (IP and path allowlists optional) |
| Configured in | Sales channel → Maintenance | Extensions → this plugin, per sales channel |
| Store API | rejected with an exception | 401 challenge |
The practical difference shows up the moment you want someone else to look at the channel. An IP allowlist means knowing, in advance, the address every reviewer will come from — which falls apart for a colleague on mobile data, a client at home, or an agency behind a rotating egress. A password travels in the same message as the link.
The two are independent and can be combined; this plugin runs before maintenance mode is evaluated.
What it is for
- Landing page previews. Build the page on a dedicated channel, hand a reviewer the URL and the password, and they see the finished page in a real storefront rather than in the admin preview.
- Shopping Experience (Erlebniswelten) previews. Same idea, for layouts that only look right once they render in the actual theme at real viewport widths.
- New product previews. Put products live on a gated channel to check listing tiles, variant and property display, cross-selling and pricing in the real storefront — before the products are visible to customers anywhere.
- A channel that has not launched. A second brand, a B2B channel, a redesign — public DNS, real SSL, nothing indexable.
- Client and stakeholder review on a staging channel, without maintaining an IP list.
A useful side effect for all of these: while a channel is gated, its pages are kept out of the HTTP cache entirely, so a reviewer always sees the current content instead of a page cached minutes ago.
Requirements
- Shopware ~6.7
- The storefront bundle (
shopware/storefront)
Installation
composer require bepo/sales-channel-basic-auth bin/console plugin:refresh bin/console plugin:install --activate BepoSalesChannelBasicAuth bin/console cache:clear:all
The package is published on Packagist, so no extra repository entry is needed.
Configuration
Extensions → My extensions → Sales channel access protection → Configure.
Pick a single sales channel in the switcher at the top before changing anything. Left on All sales channels, the settings apply to every channel at once.
| Setting | Meaning |
|---|---|
Require Basic Auth |
The gate. Off by default. |
Username / Password |
The credentials. Both must be set — see below. |
Realm |
Shown in the browser prompt. Browsers cache credentials per realm, so changing it re-prompts everyone. |
Path allowlist |
Path prefixes that skip the prompt, one per line. |
IP allowlist |
IPs or CIDR ranges that skip the prompt, one per line. |
Saving takes effect immediately and queues an HTTP cache invalidation for that channel. Pages cached before the gate went up are not served in the meantime either — a gated channel is excluded from HTTP cache lookups outright.
Set a path allowlist for payment callbacks
Payment providers cannot send credentials. If the gated channel is used for test orders, allowlist the return and webhook paths, e.g.:
/payment/
/paypal/
Shopware's own /payment/finalize-transaction is already exempt — it never resolves to a sales
channel — but provider-specific routes are not.
The IP allowlist needs trusted proxies
Behind a reverse proxy, Request::getClientIp() returns the proxy's address unless Symfony's
framework.trusted_proxies is configured. Without it the IP allowlist will not match real
visitors. This affects Shopware's own maintenance IP allowlist in exactly the same way. If trusted
proxies are not configured on your installation, use the password and leave this field empty.
What is and is not protected
Gated: storefront requests and Store API requests that resolve to the protected sales channel, including error pages.
Never gated, by design: /admin and /api. Those paths never resolve to a sales channel, so
a wrong password cannot lock you out of the administration — you can always get back in and switch
the gate off.
Also not gated: internal ESI fragment renders, which belong to a page whose own request already passed the gate. A direct request to an ESI URL is still challenged.
If the gate is on but the username or password is empty, the plugin denies everything and logs an error rather than falling open.
Known limits
- The password is stored unencrypted in
system_config, like any Shopware plugin setting. A database dump carries it. Do not reuse a password that protects anything else. /store-api/product-export/{accessKey}/{fileName}is not gated. It is the one Store API route that carries its own access key in the path and never resolves a sales channel the normal way. Reaching it requires knowing that key.- Basic Auth sends credentials on every request; serve gated channels over HTTPS only.
License
MIT — see LICENSE.