diff --git a/roles/opnform/templates/docker-compose.yml.j2 b/roles/opnform/templates/docker-compose.yml.j2 index 6b5866c..24ef00c 100644 --- a/roles/opnform/templates/docker-compose.yml.j2 +++ b/roles/opnform/templates/docker-compose.yml.j2 @@ -60,6 +60,14 @@ services: JWT_TTL: "1440" JWT_SECRET: "{{ opnform_jwt_secret }}" + # Shared secret for trusted SSR requests from the Nuxt UI. The UI + # forwards JWTs server-side with its own user agent; without this + # secret the API's AuthenticateJWT middleware would reject those + # requests (UA mismatch -> token blacklisted -> the next genuine + # browser request 401s). Must match FRONT_API_SECRET on the ui + # service. + FRONT_API_SECRET: "{{ opnform_front_api_secret }}" + PHP_MEMORY_LIMIT: "{{ opnform_php_memory_limit }}" PHP_MAX_EXECUTION_TIME: "{{ opnform_php_max_execution_time }}" PHP_UPLOAD_MAX_FILESIZE: "{{ opnform_php_upload_max_filesize }}" @@ -114,7 +122,13 @@ services: NUXT_PUBLIC_API_BASE: "/api" NUXT_PRIVATE_API_BASE: "http://ingress/api" NUXT_PUBLIC_ENV: production - FRONT_API_SECRET: "{{ opnform_front_api_secret }}" + # Nuxt runtimeConfig.apiSecret is fed by NUXT_API_SECRET (Nuxt + # convention: NUXT_ populates runtimeConfig.). The UI + # injects this as `x-api-secret` on SSR-side forwards to Laravel, + # which then short-circuits the UA-fingerprint check in + # AuthenticateJWT — without it every reload would invalidate the + # JWT (UA `node` vs UA at issue time) and 401. + NUXT_API_SECRET: "{{ opnform_front_api_secret }}" depends_on: api: condition: service_healthy