Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added assets/apps-app-url-verification-warning.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ This page lists all environment variables that can be used to configure Shopware
| `APP_LOG_DIR` | `{projectRoot}/var/log` | Path to a directory to store logs (since 6.6.8.0) |
| `APP_SECRET` | (empty) | Can be generated with `openssl rand -hex 32` |
| `APP_URL` | (empty) | Where Shopware will be accessible |
| `APP_URL_CHECK_DISABLED` | `false` | Disable URL validation checks |
| `APP_URL_CHECK_DISABLED` | `false` | Hides the Administration warning about an incorrect `APP_URL`. App installation and secret rotation still check `APP_URL`. |
| `BLUE_GREEN_DEPLOYMENT` | `0` | This needs super privilege to create trigger |
| `COMPOSER_HOME` | `/tmp/composer` | Caching for the Plugin Manager |
| `COMPOSER_PLUGIN_LOADER` | (empty) | When set to a non-empty value (e.g., `1` or `true`), enables the Composer plugin loader instead of the database plugin loader. All plugins defined in the root `composer.json` will be automatically active, regardless of database settings. |
Expand Down
4 changes: 3 additions & 1 deletion guides/hosting/installation-updates/cluster-setup.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,13 @@ To use the composer plugin loader, add the environment variable `COMPOSER_PLUGIN
We recommend setting up at least five Redis servers for the following resources:

1. [Session](../performance/session) + [cart](../performance/cart-storage#using-redis-as-storage)
2. [cache.object](../performance/caches#using-redis)
2. [cache.object](../performance/caches#using-redis) + `cache.app_url_verification`
3. [Lock](../performance/lock-store) + [Increment storage](../performance/increment)
4. [Number Ranges](../performance/number-ranges)
5. [Message Queue](../infrastructure/message-queue)

The `cache.app_url_verification` pool must be shared between all nodes, otherwise apps cannot be installed; see [APP_URL Verification](../../plugins/apps/lifecycle/app-url-verification.md#several-nodes).

The PHP Redis extension provides persistent Redis connections.
Persistent connections can help in high load scenarios as each request doesn't have to open and close connections.
Using non-persistent Redis connections can also hit the system's maximum open sockets.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,8 @@ Protect your staging environment from unauthorized access using password protect

The simplest method uses `.htaccess` for Apache or `auth_basic` for Nginx. You can also use a firewall to restrict access by IP address.

Shopware must still be able to reach itself under `APP_URL`, otherwise installing or reinstalling apps fails; see [APP_URL Verification](../../plugins/apps/lifecycle/app-url-verification.md#protected-installations).

**Apache example:**

```apache
Expand Down
5 changes: 0 additions & 5 deletions guides/hosting/performance/performance-tweaks.md
Original file line number Diff line number Diff line change
Expand Up @@ -251,11 +251,6 @@ monolog:
The `business_event_handler_buffer` handler logs flow.
Setting it to `error` will disable the logging of flow activities that succeed.

## Disable App URL external check

On any Administration load, Shopware tries to request itself to test that the configured `APP_URL` inside `.env` is correct.
If your `APP_URL` is correct, you can disable this behavior with an environment variable `APP_URL_CHECK_DISABLED=1`.

## Using zstd instead of gzip for compression

Shopware uses `gzip` for compressing the cache elements and the cart when enabled.
Expand Down
6 changes: 6 additions & 0 deletions guides/plugins/apps/lifecycle/app-registration-setup.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ If no SDK is available for your language, you can implement the registration pro

The registration request is made via a `GET` request to the URL you provide in your app's manifest file.

Before sending it, Shopware verifies that its `APP_URL` reaches this installation.
If the verification fails, the request is not sent; see [APP_URL Verification](app-url-verification.md).

<<< @/docs/snippets/config/app/setup.xml

The following query parameters will be sent with the request:
Expand Down Expand Up @@ -521,3 +524,6 @@ This means that this installation will get a new shopId, which is used during re
As the new installation will get a new shopId, the installed apps will continue working on the old installation as before, but, as a consequence, the data on the app's side associated with the old shopId cannot be accessed on the new installation.

* **UninstallApps**: This strategy will simply uninstall all apps on the new installation, thus keeping the old installation working like before.

Before MoveShopPermanently or ReinstallApps registers the apps again, Shopware verifies that `APP_URL` reaches this installation.
If the [verification](app-url-verification.md) fails, the strategy stops and the shop ID stays unchanged.
128 changes: 128 additions & 0 deletions guides/plugins/apps/lifecycle/app-url-verification.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
---
nav:
title: APP_URL Verification
position: 42

---

# APP_URL Verification

## Overview

Before Shopware registers the shop with an app server, it verifies that `APP_URL` leads back to this installation.
A wrong `APP_URL` would otherwise give the app server the address of another shop, for example the live shop on a staging copy, or of no shop at all.
If the verification fails, Shopware does not contact the app server.

::: info
This page is for shop operators.
For the registration protocol on the app side, see [App Registration & Backend Setup](app-registration-setup.md).
:::

## How the verification works

1. Shopware creates a random token and stores it in the `cache.app_url_verification` cache pool for two minutes.
2. Shopware sends a `GET` request to `{APP_URL}/api/app-system/shop/verify` with the token.
The request leaves the server and comes back in the same way as any visitor's request: through DNS, firewalls, proxies, and any load balancer.
3. The Shopware installation that receives the request looks up the token in the cache.
It answers `204 No Content` if the token matches, and `400 Bad Request` if it does not.

```mermaid
flowchart LR
A[Shop stores token] --> B[Request goes out to APP_URL]
B --> C{Where does it arrive?}
C -->|Back at this shop| D[Token found: pass]
C -->|Another server| E[Token not found: hard fail]
```

The request times out after two seconds and follows at most one redirect.

## When the verification runs

Shopware verifies `APP_URL` every time it registers with an app server, in every environment:

- when an app with a backend, or a Shopware service, is installed
- when an update adds a backend to an app that had none
- when an app secret is rotated with `bin/console app:secret:rotate`, or recovered by running `bin/console app:install` again
- when the `move-shop-permanently` or `reinstall-apps` strategy of `bin/console app:shop-id:change` runs, before the shop ID changes

If the verification fails, the installation, update, secret rotation, or strategy stops.
A shop ID change strategy then leaves the shop ID unchanged.

Apps without a backend do not register with an app server, so they are never verified.

## Results

| Result | When | Error during registration |
| :-------- | :------------------------------------------------------------------------------------------------------------------------------------------------------ | :------------------------------------------------------- |
| Pass | The request returned `204` | None, the registration continues |
| Soft fail | No connection, for example a DNS error or a timeout, or an HTTP `5xx` or `429` answer | `FRAMEWORK__APP_URL_VERIFICATION_UNAVAILABLE` (HTTP 503) |
| Hard fail | Any other answer, for example `400` from an installation that does not know the token, or `401`/`403` from a login or firewall, or an invalid `APP_URL` | `FRAMEWORK__APP_URL_FAILED_VERIFICATION` (HTTP 502) |

A soft fail is usually temporary, so try again later.
A hard fail means that `APP_URL` does not reach this installation, and it has to be fixed before apps can register.

## Requirements

### The shop must reach itself

The server or container that runs Shopware must be able to resolve and reach `APP_URL`.
This includes setups where `APP_URL` only works from outside, for example a Docker container whose `APP_URL` points to a port that is only mapped on the host.

### Protected installations

Staging instances are often protected by a login or an IP restriction.
The verification request has no login and comes from the server itself.

- With an IP restriction, add the public IP address the server sends requests from to the allowlist.
- With password protection or an authentication proxy, exclude `/api/app-system/shop/verify`, or all of `/api`.

See [Creating a staging instance](../../../hosting/installation-updates/creating-a-staging-instance.md#protecting-the-staging-environment) for an Apache example.

### Several nodes

The token is stored on the node that starts the verification, but the request can reach any node behind the load balancer.
The `cache.app_url_verification` pool must therefore be shared between all nodes.

The pool uses `cache.app`.
If `cache.app` is already shared, for example on Redis as described in [Cache](../../../hosting/performance/caches.md#using-redis), nothing else is needed.
Otherwise, point the pool to a shared adapter:

```yaml
# config/packages/cache.yaml
framework:
cache:
pools:
cache.app_url_verification:
adapter: cache.adapter.redis
provider: redis://localhost
```

### Rate limit

The verification endpoint accepts 60 failed requests per IP address per hour.
A successful verification resets the counter.
When the limit is reached, the endpoint answers `429`, which is a soft fail.

## Commands

- `bin/console app:url:status` shows the result of the last verification without running a new one: the checked URL, the result, the reason, the number of attempts, and the time of the check.
- `bin/console app:url:verify` runs a new verification, stores its result, and shows it in the same format.
If a shop ID change is pending, it shows a warning and still verifies `APP_URL`.

Run `bin/console app:url:verify` after fixing `APP_URL`, so that the stored result is up to date.

Check warning on line 112 in guides/plugins/apps/lifecycle/app-url-verification.md

View workflow job for this annotation

GitHub Actions / LanguageTool

[LanguageTool] guides/plugins/apps/lifecycle/app-url-verification.md#L112

It appears that hyphens are missing in the adjective “up-to-date”. (UP_TO_DATE_HYPHEN[1]) Suggestions: `up-to-date` URL: https://languagetool.org/insights/post/hyphen/#hyphenated-phrases-with-more-than-one-hyphen Rule: https://community.languagetool.org/rule/show/UP_TO_DATE_HYPHEN?lang=en-US&subId=1 Category: COMPOUNDING
Raw output
guides/plugins/apps/lifecycle/app-url-verification.md:112:86: It appears that hyphens are missing in the adjective “up-to-date”. (UP_TO_DATE_HYPHEN[1])
 Suggestions: `up-to-date`
 URL: https://languagetool.org/insights/post/hyphen/#hyphenated-phrases-with-more-than-one-hyphen 
 Rule: https://community.languagetool.org/rule/show/UP_TO_DATE_HYPHEN?lang=en-US&subId=1
 Category: COMPOUNDING

## Administration warning

In the `prod` environment, the Administration shows a warning when the stored result is a hard fail and apps with a backend are installed.
The warning shows the checked `APP_URL`, the HTTP status code, and the command to run.

![APP_URL verification warning in the Administration](../../../../assets/apps-app-url-verification-warning.png)

The Administration reuses the stored result:

- A pass is reused for 24 hours.
- After a soft fail, Shopware tries again with increasing pauses, from one minute up to one hour, and shows no warning.
- A hard fail is kept until the next verification, so the warning stays until `bin/console app:url:verify` runs or an app registers successfully.

Setting `APP_URL_CHECK_DISABLED=1` hides the warning.
It does not turn off the verification during app registration.
2 changes: 2 additions & 0 deletions resources/references/core-reference/commands-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ $ bin/console [command] [parameters]
| `app:secret:rotate` | Rotate the shared app secret and integration credentials for one or all apps |
| `app:shop-id:change` | \[app:url-change:resolve\] Change the shop ID by choosing a resolution strategy |
| `app:uninstall` | Uninstalls the app |
| `app:url:status` | Shows the result of the last `APP_URL` verification |
| `app:url:verify` | Verifies `APP_URL` and shows the result |
| `app:validate` | Checks manifests for errors |

### Assets
Expand Down
Loading