feat(spa): opt-in 'https' nx serve config for dev-server TLS #263

Merged
julien merged 1 commits from feat/spa-dev-server-tls into main 2026-06-01 16:15:38 +02:00
Owner

Summary

Add an opt-in https configuration to the SPA dev-servers so the ADR-0030 dockerised dev mode can be reached over a hostname registered in Entra. Entra refuses http: redirect URIs for anything other than localhost, which made the hostname-based access pattern (apf-portal.dev-jg.local, apf-portal.dev.local, …) — the only stable way to share a VM-based dev stack with another developer — impossible to wire to OIDC. This PR closes that gap without touching the WSL-native + localhost flow.

What lands

File Change
apps/portal-shell/project.json, apps/portal-admin/project.json New https Nx serve configuration: inherits the development build, sets ssl: true + sslKey: .secrets/dev-tls.key + sslCert: .secrets/dev-tls.pem. defaultConfiguration stays development; the https config is purely opt-in.
infra/local/dev.compose.yml The portal-shell and portal-admin commands now end with --configuration=${NX_SERVE_CONFIGURATION:-development}. Compose interpolates the value at YAML parse time from infra/local/.env. Default is development (no SSL), so behaviour is unchanged for anyone who doesn't opt in.
infra/local/.env.example New commented-out NX_SERVE_CONFIGURATION=https block with the rationale + pointer to the mkcert setup.
apps/portal-bff/.env.example Comment block above the ENTRA_*_REDIRECT_URI defaults shows the HTTPS hostname-based override pattern (the four URIs that go with the apps profile when accessing via a hostname) and reminds that each override must be registered Entra-side.
infra/README.md New "HTTPS dev-server setup — remote-browser access via a hostname" subsection: mkcert install / mkcert -install, cert generation, .secrets/dev-tls.{key,pem} convention, Entra registration reminder, NX_SERVE_CONFIGURATION=https opt-in. Notes that WSL-native is unaffected and that the cert path stays the same when the corp CA eventually replaces mkcert.

Design notes

  • Convention .secrets/dev-tls.{key,pem} at repo root. Matches the existing apps/portal-bff/.secrets/jwks.pem pattern (gitignored via *.pem + *.key). Workspace-relative path means project.json can hardcode it and each dev drops their per-host cert there.
  • Hardcoded path, per-dev cert content. Each developer generates a cert for their own hostname; the cert sits at the same fixed path on every machine. Nothing dev-specific in project.json.
  • https is opt-in, not default. Native nx serve keeps booting on HTTP (localhost:4200) without SSL key files, exactly as before. Compose default is also development — only setting NX_SERVE_CONFIGURATION=https in infra/local/.env switches it on, gated by the dev having actually run the mkcert step.
  • BFF stays plain HTTP. Only the SPA dev-server terminates TLS — the proxy then hits http://portal-bff:3000 on the internal Compose network. Entra still gets HTTPS at the browser-facing origin, which is what its policy enforces.

What this PR deliberately does NOT do

  • It does not force-enable HTTPS. Devs who don't care about hostname access continue working as before.
  • It does not touch the BFF code, the Entra config helpers, or the auth flow itself. The whole change is config (project.json + compose + env-examples) + docs.
  • It does not ship the shared VM cert story. That needs a corp-CA-signed cert (or a shared mkcert CA distributed across workstations); flagged in the README section as a follow-up.

Test plan

  • Both project.json files parse as JSON; nx show project exposes the new https configuration with the expected SSL options.
  • docker compose -f dev.compose.yml --profile apps config validates with NX_SERVE_CONFIGURATION=https (resolves to --configuration=https) and without it (resolves to --configuration=development).
  • On vm-jg: mkcert -install on the workstation, mkcert against apf-portal.dev-jg.local, copy .secrets/dev-tls.{key,pem} to the VM, set NX_SERVE_CONFIGURATION=https in infra/local/.env, register the four https://apf-portal.dev-jg.local:* URIs in Entra, restart dev.sh up apps, then open https://apf-portal.dev-jg.local:4200/ from the workstation → SPA loads, no cert warning, sign-in completes and returns to the SPA via the OIDC callback.
  • Native WSL flow unchanged: nx serve portal-shell still boots on http://localhost:4200/, OIDC against the existing http://localhost:3000/... Entra URIs still works.

Related

  • ADR-0030 — the dockerised dev mode this completes for the hostname-access case.
  • ADR-0018 — per-environment SPA config strategy; https is a new Nx serve configuration, not a new environment.ts sibling, so 0018's build-time replacement story is unchanged.
  • ADR-0009 — OIDC flow; no behaviour change, only the redirect-URI strings.
## Summary Add an opt-in `https` configuration to the SPA dev-servers so the ADR-0030 dockerised dev mode can be reached over a hostname registered in Entra. Entra refuses `http:` redirect URIs for anything other than `localhost`, which made the hostname-based access pattern (`apf-portal.dev-jg.local`, `apf-portal.dev.local`, …) — the only stable way to share a VM-based dev stack with another developer — impossible to wire to OIDC. This PR closes that gap without touching the WSL-native + localhost flow. ## What lands | File | Change | | --- | --- | | `apps/portal-shell/project.json`, `apps/portal-admin/project.json` | New `https` Nx serve configuration: inherits the `development` build, sets `ssl: true` + `sslKey: .secrets/dev-tls.key` + `sslCert: .secrets/dev-tls.pem`. `defaultConfiguration` stays `development`; the `https` config is purely opt-in. | | `infra/local/dev.compose.yml` | The `portal-shell` and `portal-admin` commands now end with `--configuration=${NX_SERVE_CONFIGURATION:-development}`. Compose interpolates the value at YAML parse time from `infra/local/.env`. Default is `development` (no SSL), so behaviour is unchanged for anyone who doesn't opt in. | | `infra/local/.env.example` | New commented-out `NX_SERVE_CONFIGURATION=https` block with the rationale + pointer to the mkcert setup. | | `apps/portal-bff/.env.example` | Comment block above the `ENTRA_*_REDIRECT_URI` defaults shows the HTTPS hostname-based override pattern (the four URIs that go with the `apps` profile when accessing via a hostname) and reminds that each override must be registered Entra-side. | | `infra/README.md` | New "HTTPS dev-server setup — remote-browser access via a hostname" subsection: mkcert install / `mkcert -install`, cert generation, `.secrets/dev-tls.{key,pem}` convention, Entra registration reminder, `NX_SERVE_CONFIGURATION=https` opt-in. Notes that WSL-native is unaffected and that the cert path stays the same when the corp CA eventually replaces mkcert. | ## Design notes - **Convention `.secrets/dev-tls.{key,pem}` at repo root.** Matches the existing `apps/portal-bff/.secrets/jwks.pem` pattern (gitignored via `*.pem` + `*.key`). Workspace-relative path means project.json can hardcode it and each dev drops their per-host cert there. - **Hardcoded path, per-dev cert content.** Each developer generates a cert for **their own** hostname; the cert sits at the same fixed path on every machine. Nothing dev-specific in `project.json`. - **`https` is opt-in, not default.** Native `nx serve` keeps booting on HTTP (`localhost:4200`) without SSL key files, exactly as before. Compose default is also `development` — only setting `NX_SERVE_CONFIGURATION=https` in `infra/local/.env` switches it on, gated by the dev having actually run the mkcert step. - **BFF stays plain HTTP.** Only the SPA dev-server terminates TLS — the proxy then hits `http://portal-bff:3000` on the internal Compose network. Entra still gets HTTPS at the browser-facing origin, which is what its policy enforces. ## What this PR deliberately does NOT do - It does **not** force-enable HTTPS. Devs who don't care about hostname access continue working as before. - It does **not** touch the BFF code, the Entra config helpers, or the auth flow itself. The whole change is config (project.json + compose + env-examples) + docs. - It does **not** ship the shared VM cert story. That needs a corp-CA-signed cert (or a shared mkcert CA distributed across workstations); flagged in the README section as a follow-up. ## Test plan - [x] Both `project.json` files parse as JSON; `nx show project` exposes the new `https` configuration with the expected SSL options. - [x] `docker compose -f dev.compose.yml --profile apps config` validates with `NX_SERVE_CONFIGURATION=https` (resolves to `--configuration=https`) and without it (resolves to `--configuration=development`). - [ ] **On vm-jg**: `mkcert -install` on the workstation, `mkcert` against `apf-portal.dev-jg.local`, copy `.secrets/dev-tls.{key,pem}` to the VM, set `NX_SERVE_CONFIGURATION=https` in `infra/local/.env`, register the four `https://apf-portal.dev-jg.local:*` URIs in Entra, restart `dev.sh up apps`, then open `https://apf-portal.dev-jg.local:4200/` from the workstation → SPA loads, no cert warning, sign-in completes and returns to the SPA via the OIDC callback. - [ ] Native WSL flow unchanged: `nx serve portal-shell` still boots on `http://localhost:4200/`, OIDC against the existing `http://localhost:3000/...` Entra URIs still works. ## Related - [ADR-0030](docs/decisions/0030-dockerised-dev-mode.md) — the dockerised dev mode this completes for the hostname-access case. - [ADR-0018](docs/decisions/0018-environment-configuration-strategy.md) — per-environment SPA config strategy; `https` is a new Nx serve _configuration_, not a new `environment.ts` sibling, so 0018's build-time replacement story is unchanged. - [ADR-0009](docs/decisions/0009-auth-flow-oidc-pkce-msal-node.md) — OIDC flow; no behaviour change, only the redirect-URI strings.
julien added 1 commit 2026-06-01 16:15:03 +02:00
feat(spa): opt-in 'https' nx serve config for dev-server TLS
CI / scan (pull_request) Successful in 4m36s
CI / commits (pull_request) Successful in 5m43s
CI / a11y (pull_request) Successful in 5m26s
CI / check (pull_request) Successful in 7m35s
CI / perf (pull_request) Successful in 23m38s
82d8c6972f
Entra refuses http: redirect URIs for any host other than localhost,
which blocked the ADR-0030 dockerised dev mode the moment a developer
tried to share the stack with another teammate via a hostname (e.g.
apf-portal.dev.local). Add an opt-in 'https' Nx serve configuration
on both SPAs so the dev-server can terminate TLS using a mkcert cert,
and let the apps Compose profile pick the configuration via an env
var so behaviour stays unchanged by default.

- apps/portal-{shell,admin}/project.json: new https configuration
  inheriting development + ssl/sslKey/sslCert at .secrets/dev-tls.*.
- infra/local/dev.compose.yml: shell + admin commands gain
  --configuration=${NX_SERVE_CONFIGURATION:-development}, interpolated
  from infra/local/.env at parse time.
- infra/local/.env.example: NX_SERVE_CONFIGURATION block + rationale.
- apps/portal-bff/.env.example: comment block above the ENTRA_*_
  REDIRECT_URI defaults shows the https hostname override pattern and
  reminds that each URI must be registered Entra-side.
- infra/README.md: new HTTPS dev-server setup subsection covering
  mkcert install, cert generation, the .secrets/ convention, the
  Entra step, and how to flip NX_SERVE_CONFIGURATION on.

Native WSL / localhost is unaffected: defaultConfiguration stays
development, no SSL files required, existing Entra localhost URIs
work as before. BFF stays plain HTTP behind the SPA proxy.
julien merged commit db7e479dde into main 2026-06-01 16:15:38 +02:00
julien deleted branch feat/spa-dev-server-tls 2026-06-01 16:15:39 +02:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: julien/apf_portal#263