Shopware 6 Hidden Gems #8: Customer impersonation — the Store API route nobody talks about
Fabian Blechschmidt
„Can you check why customer X doesn’t see their special prices?“ — every agency developer knows this ticket. And the workflow it triggers: ask the customer for… no wait, you can’t ask for their password. Create a test account? It won’t have their customer group, their rules, their cart. Stare at the rule builder and simulate the context in your head? That’s usually where it ends.
Shopware’s admin has had a „log in as customer“ button for a while. What I didn’t know until I grepped PlatformRequest.php for this series: the machinery behind it is a complete, token-secured impersonation API — two routes, an HMAC token generator, its own session attribute. You can build proper support tooling on it. The word „imitate“ appears exactly zero times in the entire documentation repo.
The flow
Impersonation is a two-step handshake between Admin API and Store API.
Step 1 — the admin side mints a token:
POST /api/_proxy/generate-imitate-customer-token
{
"salesChannelId": "...",
"customerId": "..."
}
This route (Framework/Api/Controller/SalesChannelProxyController.php:148-170) is protected by its own ACL privilege, api_proxy_imitate-customer — so you can grant support staff impersonation rights without giving them anything else.
ImitateCustomerRoute (Checkout/Customer/SalesChannel/ImitateCustomerRoute.php:51-80) validates the token, logs out whoever is currently logged in on that context, performs a passwordless loginById() for the target customer and returns a fresh context token. From that moment the session is the customer’s session: their rules, their prices, their cart behavior.
The security design is worth reading
For once, „hidden“ doesn’t mean „hacky“. The token generator (Checkout/Customer/ImitateCustomerTokenGenerator.php) does it properly:
The token is an HMAC-SHA256 over salesChannelId + customerId + userId, signed with the shop’s APP_SECRET.
It carries a timestamp and expires after 3600 seconds (TOKEN_LIFETIME, line 12).
Validation compares with hash_equals() — no timing side channels.
The token is bound to one customer in one sales channel, requested by one admin user. You can’t mint a wildcard.
And the part I like most: the imitating admin’s user ID travels along. $context->setImitatingUserId($userId) stores it in the sales channel context, and PlatformRequest::ATTRIBUTE_IMITATING_USER_ID (sw-imitating-user-id) keeps it in the session. It survives cart restoration (CartRestorer.php) and is cleaned from the session when no customer is logged in anymore (SalesChannelRequestContextResolver.php:68).
Why does that matter? Auditability. An order placed during impersonation has a session that knows which admin was behind it. If you build support tooling, you can (and should) surface that — „this order was placed by support on behalf of the customer“ is exactly the line you want in the order comments when the customer disputes it later.
What you can build with it
The admin button covers the basic case. The API makes the interesting ones possible:
A „view as customer“ button in your ERP/CRM integration — support sees the shop exactly as the caller does, one click from the ticket.
Automated price-rule testing: impersonate a matrix of representative customers in CI and snapshot listing prices via Store API. Rule regressions caught before deployment — this pairs beautifully with the max_rule_prices cutoff from the previous post, which is otherwise nearly impossible to test.
Debugging session: reproduce „works for me, breaks for customer X“ as customer X, with Symfony profiler open.
One practical warning: impersonation triggers a real login. Events fire, lastLogin updates, and anything you put in the cart is in the customer’s cart. Look, don’t touch — or clean up after yourself.
TL;DR
Shopware ships a full impersonation API: POST /api/_proxy/generate-imitate-customer-token (ACL: api_proxy_imitate-customer) mints an HMAC-signed, single-purpose token valid for one hour; POST /store-api/account/login/imitate-customer turns it into a passwordless customer session, with the admin’s user ID tracked via sw-imitating-user-id for auditability. Great for support tooling and price-rule regression tests. Documented: nowhere.
Next up: pagination performance — the total-count mode that skips COUNT(*) entirely, and the iterator that switches to keyset pagination behind your back.
Built something on top of this? Drop me an email, I’m curious!
Found in Shopware 6.7.0.0: token minting in Framework/Api/Controller/SalesChannelProxyController.php:148-170, login route in Checkout/Customer/SalesChannel/ImitateCustomerRoute.php:51-80, HMAC + 1h lifetime in Checkout/Customer/ImitateCustomerTokenGenerator.php:10-73, session attribute sw-imitating-user-id in PlatformRequest.php:43 and Framework/Routing/SalesChannelRequestContextResolver.php:68.