BLOCKING: Switch Woo auth from consumer keys to WordPress Application Passwords #5

Closed
opened 2026-09-01 20:45:03 +00:00 by Ty · 4 comments
Owner

Status

Blocking for POC. This architectural decision must follow the well-supported path before any POC implementation or UAT proceeds.

Summary

The current docs (CONTENT-WOO.md, OPENAPI.md, Architecture) lock the server into authenticating to WooCommerce REST v3 using WooCommerce consumer keys (ck_/cs_ pair, generated under WooCommerce → Settings → Advanced → REST API) sent as HTTP Basic Auth.

Research shows the well-supported, lower-friction path for a self-hosted single-store deployment like Whidbey Wood Store is WordPress Application Passwords: a dedicated low-privilege WordPress user, an application password generated under Users → Profile, and the same Basic Auth shape (username:application_password). This is the method the official WooCommerce mobile app uses for store-credentials login, and it is the method WooCommerce's own MCP integration docs explicitly prescribe — "Do not use your account password or a WooCommerce REST API key."

Consumer keys are not wrong, but they are the heavier path: extra admin UI step, key tied to a specific user with an explicit read/write scope, and no benefit over application passwords for a first-party, self-hosted integration.

Required change

  • Replace consumer-key auth with application-password auth throughout the docs and the planned implementation.
  • Create a dedicated low-privilege WordPress user (e.g. shop-manager or a custom role with product create/edit + media upload) rather than reusing an admin account.
  • Generate the application password under Users → Profile → Application Passwords.
  • Store it encrypted at rest in the SQLite settings table via AES-GCM (same SLAB_AES_KEY from .env as today); the browser never holds it.
  • All Woo calls remain server-side only (FastAPI is the sole caller).
  • Rotation = revoke in the user's profile and re-enter in Settings UI.

Documentation references (must be updated)

  1. CONTENT-WOO.md — currently describes consumer-key auth, taxonomy sync, payload, and media upload. Rewrite the auth section to application passwords; keep the payload and media-upload sequence.
  2. OPENAPI.md — currently documents the client-to-server contract and the 409 duplicate_sku error. Update any auth-related notes and the Settings endpoint that accepts credentials.
  3. Architecture.md — reinforces "browser never touches Woo; FastAPI is the only caller." Update the auth boundary description.
  4. DEPLOYMENT.md / README — any setup steps that mention generating keys under WooCommerce → Settings → Advanced → REST API must be replaced with the Users → Profile → Application Passwords flow, plus the HTTPS prerequisite (WordPress requires HTTPS to generate application passwords).
  5. AGENTS.md / tech spec — any mention of "consumer key," "consumer secret," or "REST API key" must be replaced so agents do not rebuild the old path.

Acceptance criteria

  • No doc or code path references WooCommerce consumer keys or the REST API key generation UI.
  • Docs instruct creating a dedicated low-privilege WP user and generating an application password under Users → Profile.
  • Docs state HTTPS is required (already covered by Caddy TLS, but called out at the auth step).
  • Encrypted-at-rest storage, server-side-only calls, and rotation semantics are preserved.
  • A smoke test against a real store using an application password succeeds end-to-end (capture → Woo draft).
  • Issue is closed only after the docs on docs/refactor-v2 (or its successor) reflect the change.

Notes

  • This does not change the REST v3 endpoint surface (/wp-json/wc/v3/) — only the credential type.
  • Application passwords are a WordPress core feature since 5.6; no plugin required. They are stored hashed and shown once at creation.
  • Related: issue #3 (stale "already published" wording on duplicate SKU) should be resolved in the same doc pass.
## Status **Blocking for POC.** This architectural decision must follow the well-supported path before any POC implementation or UAT proceeds. ## Summary The current docs (CONTENT-WOO.md, OPENAPI.md, Architecture) lock the server into authenticating to WooCommerce REST v3 using **WooCommerce consumer keys** (ck_/cs_ pair, generated under WooCommerce → Settings → Advanced → REST API) sent as HTTP Basic Auth. Research shows the well-supported, lower-friction path for a self-hosted single-store deployment like Whidbey Wood Store is **WordPress Application Passwords**: a dedicated low-privilege WordPress user, an application password generated under Users → Profile, and the same Basic Auth shape (`username:application_password`). This is the method the official WooCommerce mobile app uses for store-credentials login, and it is the method WooCommerce's own MCP integration docs explicitly prescribe — "Do not use your account password or a WooCommerce REST API key." Consumer keys are not wrong, but they are the heavier path: extra admin UI step, key tied to a specific user with an explicit read/write scope, and no benefit over application passwords for a first-party, self-hosted integration. ## Required change - Replace consumer-key auth with application-password auth throughout the docs and the planned implementation. - Create a dedicated low-privilege WordPress user (e.g. shop-manager or a custom role with product create/edit + media upload) rather than reusing an admin account. - Generate the application password under Users → Profile → Application Passwords. - Store it encrypted at rest in the SQLite settings table via AES-GCM (same `SLAB_AES_KEY` from `.env` as today); the browser never holds it. - All Woo calls remain server-side only (FastAPI is the sole caller). - Rotation = revoke in the user's profile and re-enter in Settings UI. ## Documentation references (must be updated) 1. **CONTENT-WOO.md** — currently describes consumer-key auth, taxonomy sync, payload, and media upload. Rewrite the auth section to application passwords; keep the payload and media-upload sequence. 2. **OPENAPI.md** — currently documents the client-to-server contract and the `409 duplicate_sku` error. Update any auth-related notes and the Settings endpoint that accepts credentials. 3. **Architecture.md** — reinforces "browser never touches Woo; FastAPI is the only caller." Update the auth boundary description. 4. **DEPLOYMENT.md / README** — any setup steps that mention generating keys under WooCommerce → Settings → Advanced → REST API must be replaced with the Users → Profile → Application Passwords flow, plus the HTTPS prerequisite (WordPress requires HTTPS to generate application passwords). 5. **AGENTS.md / tech spec** — any mention of "consumer key," "consumer secret," or "REST API key" must be replaced so agents do not rebuild the old path. ## Acceptance criteria - [ ] No doc or code path references WooCommerce consumer keys or the REST API key generation UI. - [ ] Docs instruct creating a dedicated low-privilege WP user and generating an application password under Users → Profile. - [ ] Docs state HTTPS is required (already covered by Caddy TLS, but called out at the auth step). - [ ] Encrypted-at-rest storage, server-side-only calls, and rotation semantics are preserved. - [ ] A smoke test against a real store using an application password succeeds end-to-end (capture → Woo draft). - [ ] Issue is closed only after the docs on `docs/refactor-v2` (or its successor) reflect the change. ## Notes - This does not change the REST v3 endpoint surface (`/wp-json/wc/v3/`) — only the credential type. - Application passwords are a WordPress core feature since 5.6; no plugin required. They are stored hashed and shown once at creation. - Related: issue #3 (stale "already published" wording on duplicate SKU) should be resolved in the same doc pass.
Ty added this to the POC milestone 2026-09-01 23:49:49 +00:00
Owner

Issue #5 docs on docs/refactor-v2:

  • 7bfba9f Application Passwords (DEPLOYMENT setup: dedicated WP user, HTTPS, Users → Profile, AES-GCM, FastAPI-only)
  • 3921a9d deploy compose files; no consumer-key leftover in deploy docs

Still open: live smoke “capture → Woo draft” is POC implementation, not this docs pass. Do not close until that smoke exists.

Issue #5 docs on `docs/refactor-v2`: - `7bfba9f` Application Passwords (DEPLOYMENT setup: dedicated WP user, HTTPS, Users → Profile, AES-GCM, FastAPI-only) - `3921a9d` deploy compose files; no consumer-key leftover in **deploy** docs Still open: live smoke “capture → Woo draft” is POC implementation, not this docs pass. Do not close until that smoke exists.
Author
Owner

The docs on refactor-v2 correctly switch to Application Passwords but leave negative framing throughout ("not consumer keys", "not the account login password", etc.). These need a cleanup pass to remove all references to consumer keys. The clean docs should only state what the system does, not what it replaced. The issue cannot close until the slop is removed from CONTENT-WOO, OPENAPI, ARCHITECTURE, DEPLOYMENT, DATA-MODEL, AGENTS, UX, and IMPL-PLAN. One note in the AGENTS precedence section acknowledging the archived PRD lines are stale is acceptable.

The docs on refactor-v2 correctly switch to Application Passwords but leave negative framing throughout ("not consumer keys", "not the account login password", etc.). These need a cleanup pass to remove all references to consumer keys. The clean docs should only state what the system does, not what it replaced. The issue cannot close until the slop is removed from CONTENT-WOO, OPENAPI, ARCHITECTURE, DEPLOYMENT, DATA-MODEL, AGENTS, UX, and IMPL-PLAN. One note in the AGENTS precedence section acknowledging the archived PRD lines are stale is acceptable.
Author
Owner

Negative framing removed from all normative docs:

  • AGENTS §4: "(not consumer keys)" removed from secrets list; "Do not implement WooCommerce consumer keys" removed from Server section
  • ARCHITECTURE §5: "Not Woo consumer keys. Not the account login password." removed
  • CONTENT-WOO §2.1: "not WooCommerce consumer keys (ck_/cs_) and not the user's login password" replaced with positive statement
  • DATA-MODEL settings keys: "not WooCommerce consumer keys" removed
  • DEPLOYMENT §5 table: "not consumer keys" removed
  • IMPL-PLAN Phase 4: "No WooCommerce consumer keys" removed
  • OPENAPI SettingsView: "not consumer keys" removed

All consumer-key references removed from normative docs. Archive PRD note preserved (known stale). Server rejection of old woo_consumer_key/woo_consumer_secret field names kept as functional requirement.

Test cases needed once implementation exists:

  1. GET settings — never returns application password or consumer key. Only woo_credentials_configured: true.
  2. PUT settings — stores AES-GCM encrypted credentials only. woo_app_password write-only.
  3. test-woo — uses HTTP Basic Auth with username + application password. No consumer key headers.
  4. Browser never calls Woo REST — no CORS, no direct Woo API calls from client.
  5. Old field rejection — PUT settings with woo_consumer_key/woo_consumer_secret returns 422 or is ignored.
Negative framing removed from all normative docs: - AGENTS §4: "(not consumer keys)" removed from secrets list; "Do not implement WooCommerce consumer keys" removed from Server section - ARCHITECTURE §5: "Not Woo consumer keys. Not the account login password." removed - CONTENT-WOO §2.1: "not WooCommerce consumer keys (ck_/cs_) and not the user's login password" replaced with positive statement - DATA-MODEL settings keys: "not WooCommerce consumer keys" removed - DEPLOYMENT §5 table: "not consumer keys" removed - IMPL-PLAN Phase 4: "No WooCommerce consumer keys" removed - OPENAPI SettingsView: "not consumer keys" removed All consumer-key references removed from normative docs. Archive PRD note preserved (known stale). Server rejection of old `woo_consumer_key`/`woo_consumer_secret` field names kept as functional requirement. Test cases needed once implementation exists: 1. **GET settings** — never returns application password or consumer key. Only `woo_credentials_configured: true`. 2. **PUT settings** — stores AES-GCM encrypted credentials only. `woo_app_password` write-only. 3. **test-woo** — uses HTTP Basic Auth with username + application password. No consumer key headers. 4. **Browser never calls Woo REST** — no CORS, no direct Woo API calls from client. 5. **Old field rejection** — PUT settings with `woo_consumer_key`/`woo_consumer_secret` returns 422 or is ignored.
Owner

Verified in main @ 0c00d25: woo.py uses wp_username + app_password (AES-GCM), no consumer keys. SETTINGS-15 enforced. Done.

Verified in main @ 0c00d25: woo.py uses wp_username + app_password (AES-GCM), no consumer keys. SETTINGS-15 enforced. Done.
Sign in to join this conversation.
No Label
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Ty_Tech/SlabUploader#5