T10.6 - deployment docs and env var reference describe Okta, not the never-shipped LDAP config
D13 never shipped, so DEPLOYMENT.md, server/.env.example and server/README.md
still described the original local-password system as of this task starting -
POST /api/auth/login, bcrypt password_hash, create-admin with a prompted
password, self-service reset-password email flow, AUTH_RESET_MINUTES /
AUTH_RESET_COOLDOWN_SECONDS. All of that is gone as of T10.4; these three files
now describe what actually runs.
server/.env.example and DEPLOYMENT.md's env block both gain the five OKTA_*
variables (ISSUER, CLIENT_ID, CLIENT_SECRET, REDIRECT_URI, IDENTITY_CLAIM),
explained the same way AUTH_SECRET_KEY already was - what it does, where to
get it, what happens if it's missing.
Also updated, not originally named in T10.6's bullet but required for the
documented vars to actually reach a running container: docker-compose.yml's
api service sets environment: as an explicit allowlist, not env_file, so the
four new OKTA_* entries had to be added there too or .env would document
something that silently does nothing. OKTA_IDENTITY_CLAIM specifically is NOT
${OKTA_IDENTITY_CLAIM:-} - compose setting an env var to an empty string is
not the same as leaving it unset, and server/okta_auth.py's own default
(preferred_username) only kicks in when the var is truly unset. Mirrored the
same default in the compose file instead, or every deployment that leaves the
optional line commented out in .env would 503 on every sign-in looking for a
claim literally named "".
server/README.md: replaced the login-portal section with the Okta flow
(access gating is Okta's job, not this app's - roles/authorization stay
local), replaced "create the first admin" with the promote-not-create
bootstrap path (D16) and its no-break-glass posture, replaced the curl-based
login example in Quick Test with a pointer to smoketest.py's own
session-minting technique (there is nothing left to curl - Okta requires a
real browser).
DEPLOYMENT.md: same treatment for its own copies of the env block, the
Portainer var list, the users table's password_hash column, the auth
endpoints summary, the smoke-test walkthrough (WP_SMOKE_USER only, must run
inside the api container or local dev sharing AUTH_SECRET_KEY/DATABASE_URL -
no longer targetable from an arbitrary remote workstation), the entire
"Self-service password reset" section (replaced with "Sign-in and admin
bootstrap (Okta)"), and the project_super_user role description / exclusive-
scope bullet, both of which named "reset passwords" as something that no
longer exists.
Left alone, logged rather than fixed here per CLAUDE.md scope discipline:
- users.failed_attempts / locked_until columns are still in the schema and
still reset to 0/None on every Okta sign-in, but nothing increments them
anymore since local login() is gone - vestigial, not documented as active
lockout behavior in either doc now, but not migrated away either.
- server/README.md's "Production - Docker Compose" section (### 1-5) is a
self-contained alternate quickstart that already duplicated and diverged
from the real root docker-compose.yml before this task; it uses env_file
rather than an explicit allowlist so it isn't broken by this change, but
it's still a second source of truth nobody asked this task to reconcile.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -12,15 +12,49 @@ DATABASE_URL=postgresql+psycopg://wpsuite:CHANGE_ME@localhost:5432/wpsuite
|
||||
# CORS_ORIGINS=http://localhost:5500
|
||||
|
||||
# ── Authentication ────────────────────────────────────────────────────────────
|
||||
# Secret used to sign session cookies (JWTs). REQUIRED in production: if unset,
|
||||
# the API falls back to a random per-process key, so logins reset on every
|
||||
# restart and break across multiple gunicorn workers. Generate a strong one:
|
||||
# There is no local password (D15/D16) — Okta OIDC is the only way in. Sign-in
|
||||
# still ends the same way it always did: a signed JWT in an HttpOnly session
|
||||
# cookie, which is what the four vars right below this line are for. The five
|
||||
# OKTA_* vars after that are what makes the actual sign-in possible; without
|
||||
# them the API starts (this is not a hard failure like AUTH_SECRET_KEY), but
|
||||
# describe()'s startup log line says so and nobody can sign in.
|
||||
|
||||
# Secret used to sign session cookies (JWTs), AFTER Okta has confirmed who
|
||||
# someone is — this app still decides roles/authorization locally, unchanged
|
||||
# by Okta (see server/okta_auth.py). REQUIRED in production: if unset, the API
|
||||
# falls back to a random per-process key, so logins reset on every restart and
|
||||
# break across multiple gunicorn workers. Generate a strong one:
|
||||
# python -c "import secrets; print(secrets.token_urlsafe(48))"
|
||||
AUTH_SECRET_KEY=CHANGE_ME_run_the_command_above
|
||||
|
||||
# How long a login lasts before re-authentication (hours). Default 12.
|
||||
# AUTH_SESSION_HOURS=12
|
||||
|
||||
# ── Okta OIDC (required — this is the only sign-in path) ───────────────────────
|
||||
# The Okta *authorization server* issuer, e.g. https://yourorg.okta.com/oauth2/default
|
||||
# or a custom authorization server URL. The API discovers the authorize/token/
|
||||
# jwks endpoints from <OKTA_ISSUER>/.well-known/openid-configuration — nothing
|
||||
# else about Okta's endpoints is hand-entered.
|
||||
OKTA_ISSUER=https://your-org.okta.com/oauth2/default
|
||||
|
||||
# Client ID and secret from the Okta app integration (Sign-in method: OIDC -
|
||||
# Authorization Code, Application type: Web Application). The secret is exactly
|
||||
# that — treat it like AUTH_SECRET_KEY, never commit it.
|
||||
OKTA_CLIENT_ID=CHANGE_ME
|
||||
OKTA_CLIENT_SECRET=CHANGE_ME
|
||||
|
||||
# Must exactly match a "Sign-in redirect URI" registered on the Okta app
|
||||
# integration, scheme and path included, e.g.:
|
||||
# https://wp-suite.company.local/api/auth/okta/callback
|
||||
OKTA_REDIRECT_URI=CHANGE_ME
|
||||
|
||||
# Which ID token claim carries this person's directory identity, matched
|
||||
# against the local users.username column (server/app.py's okta_callback()).
|
||||
# preferred_username is Okta's usual default for an AD-imported user; override
|
||||
# it if your security team's Okta configuration uses a different claim (upn,
|
||||
# a custom claim, …) — no code change needed, just this value.
|
||||
# OKTA_IDENTITY_CLAIM=preferred_username
|
||||
|
||||
# ── Email notifications (optional) ─────────────────────────────────────────────
|
||||
# WP-assignment emails are OFF by default and are turned on from the Admin
|
||||
# console (Notifications & email card), where the SMTP host/port/from-address
|
||||
|
||||
Reference in New Issue
Block a user