YUI Preview Token
YUI Preview Token solves the authentication problem in decoupled (headless) WordPress architectures. Application Passwords are a great built-in WordPress feature for this purpose, but they require managing long-lived secrets on the frontend side. This plugin instead issues per-post tokens that grant read access for a configurable period — no persistent secrets required.
The frontend (Astro, Next.js, Nuxt, etc.) receives a preview URL and can fetch the draft content directly via the REST API.
How it works
- An authorized WordPress user generates a token from the Gutenberg sidebar, Quick Edit panel, or Classic Editor meta box.
- The token is embedded in a preview URL pointing to your external frontend.
- The frontend calls
/wp-json/yui-preview-token/v1/preview?token=…to retrieve the draft content. - The token expires automatically; no manual cleanup needed.
Key Features
Token Management
- Generate tokens with expiry presets: 1 hour, 24 hours, 30 days, custom date/time, or no expiry.
- One token per post — issuing a new token invalidates the previous one.
- Tokens are generated with
bin2hex(random_bytes(32))(256-bit CSPRNG). The lookup key stored inwp_optionsis the SHA-256 hash of the raw token, not the token itself — so a database leak does not expose usable tokens directly. - Automatic cleanup of expired tokens via WP Cron (daily).
Editor Integration
- Gutenberg: dedicated panel in the Document Settings sidebar.
- Quick Edit: token controls directly in the post list.
- Classic Editor: meta box in the editor sidebar.
- Copy preview URL to clipboard with one click.
- Update expiry without invalidating the current token.
Admin Settings
- Set the external frontend URL (clicking «Open external preview» navigates directly to this URL).
- Configure allowed CORS origins (multiple, with wildcard support —
https://*.example.com). - Choose the minimum WordPress role required to issue tokens (Subscriber → Administrator).
- Tune rate limiting (requests per time window).
- Optionally permit no-expiry tokens.
Issued Tokens List
- View all active and expired tokens with post title, status, expiry, and issuer.
- Revoke individual tokens or bulk-delete expired ones — all from the Settings screen.
Security
- HTTPS required for the preview endpoint (overridable for local development).
- Per-IP rate limiting with configurable thresholds (default: 30 req / 60 s).
- Role-based access control for token issuance.
- CORS headers only sent for explicitly configured origins; WP core’s permissive echo-back is suppressed.
Referrer-Policy: no-referrerprevents token leakage via referer headers.- Tokens are only valid for
draft,pending, andfuturepost statuses. - Admin-only settings page with defence-in-depth capability checks.
- CSRF protection on all admin actions (nonce verification).
Audit Logging
- Logs token issuance and usage events (post ID, user ID, client IP).
- Logs security events: invalid token attempts, rate-limit violations, capability denials.
- Output goes to
WP_DEBUG_LOGby default; point to a dedicated file withPVT_LOG_FILE.
Internationalisation
- Ships with Japanese (ja) and Simplified Chinese (zh_CN) translations.
- All admin UI strings are translation-ready.
Developer Hooks
Filter
yuipt_preview_response_data— Modify the REST API response data before it is sent.
Actions
yuipt_token_issued( int $post_id, int $user_id )— Fires after a token is issued.yuipt_token_used( int $post_id, int $user_id )— Fires when a token is used successfully.yuipt_invalid_token( string $ip )— Fires on an invalid/expired token attempt.yuipt_rate_limit_exceeded( string $ip, string $endpoint )— Fires when rate limit is hit.yuipt_capability_denied( int $user_id, int $post_id )— Fires on a capability denial.
Constants (wp-config.php)
PVT_SKIP_HTTPS_CHECK— Set totrueto disable the HTTPS requirement (development only).PVT_LOG_FILE— Absolute path to a dedicated audit log file.
Use Case
This plugin is designed for headless WordPress setups where a decoupled frontend (e.g. Astro, Next.js, Nuxt, SvelteKit) renders content from the WordPress REST API. It gives content editors a simple, secure way to share draft previews with stakeholders without granting them WordPress accounts or exposing long-lived API credentials.
