Draft: feat: Introduce the authentication and security model for headless draft preview
Closes #3591775. First building block of the Canvas Headless milestone.
Adds the canvas_headless sub-module: it embeds a headless frontend in the
Canvas editor frame and gives it draft content access through user-bound
preview tokens, minted via the standard OAuth 2.0 JWT assertion grant
(RFC 7523). The token is
bound to the editing user and capped to a view-only permission ceiling;
sessions renew from the live Drupal session, so logging out ends the
preview. No secrets in the frontend; the only site configuration is the
frontend URL.
The design and its alternatives are recorded in the diff itself: ADRs
0014–0016 (docs/adr/), a concept-level walkthrough of the auth design
(docs/headless-preview-auth.md), and the module README (setup, operations,
browser support, known limitations). Reviewers may want to start there.
Where to start in the diff
modules/canvas_headless— the module: assertion factory, thejwt_bearergrant, the view-only scope granularity, the minting endpoints, kernel tests.packages/headless-host— framework-agnostic host side of the postMessage renewal/recovery protocol.ui/src/features/layout/preview— the editor frame embeds the frontend and drives its draft session; the same-origin overlay is disabled for the cross-origin iframe.modules/canvas_headless/examples/nextjs-app— reference frontend: draft SDK, host-protocol client, CE-API-rendered pages.
How to test
- Install
canvas_headless(requiressimple_oauth>= 6 with its keypair configured). - Run the example app:
cd modules/canvas_headless/examples/nextjs-app && cp .env.example .env.local && npm install && npm run dev. - Grant
access canvas headless previewto an editorial role. The shippedfrontend_urldefault already points at the example app's dev server. - Open an entity in the Canvas editor: the frontend loads in the editor frame with an active draft session, and unpublished content renders. Use a Chromium-based browser for the embedded flow on plain-http localhost.
Authored with an AI coding agent.