Add authenticated login and SSO protection

This commit is contained in:
inman
2026-05-29 15:54:13 +08:00
parent e36f28a668
commit 0648874801
50 changed files with 1853 additions and 63 deletions

View File

@@ -141,3 +141,38 @@
- Jimeng image generation supports the current `scale` parameter, so UI presets should submit numeric text-influence values for that engine.
- EvoLink image generation does not use Jimeng `scale`; the per-request engine-aware control should submit EvoLink `quality` instead.
- Current local `/api/health` reports `image.generate` using EvoLink, so `/create` should show `生成质量` options rather than `文本影响`.
## 2026-05-29 Account Login / SSO Findings
- User requested account login before release so the project is safe to use.
- Provided SSO guide recommends OAuth2 Authorization Code for Web SSO: redirect to `${AUTH_BASE}/oauth2/authorize`, receive `code` and `state`, then exchange code server-side at `${AUTH_BASE}/oauth2/token`.
- OAuth client defaults in the guide use `client_id=customPC` and `scope=server`; `client_secret` must stay on the server.
- Access tokens are JWTs; resource services should verify locally with JWKS from `${AUTH_BASE}/oauth2/jwks` rather than calling auth on every request.
- Minimum JWT checks from the guide: RS256 signature, `exp`, `nbf`/`iat`, issuer `https://pig4cloud.com`, OAuth client id, scope/authority requirements.
- Logout endpoint is `DELETE ${AUTH_BASE}/token/logout`, but local session deletion remains required because existing JWTs may stay valid until `exp`.
- Current app has no login middleware or session helper; pages are client components under a global shell.
- Current local data store defaults all assets/jobs to `DEFAULT_OWNER_ID = "demo-merchant"`, so account login must also address per-user owner IDs for first-party UI APIs.
- Public API v1 already has separate API key auth through `ZHINIAN_API_KEYS`; SSO should preserve that server-to-server surface.
- First-party UI APIs that currently need session ownership include `/api/assets`, `/api/assets/upload`, `/api/assets/:id/*`, `/api/generations/image*`, `/api/generations/video*`, and `/api/settings`.
- Generation services already accept optional `ownerId`, so route handlers can pass the authenticated owner without rewriting provider dispatch or worker logic.
- Retry helpers currently preserve the original request payload; they need to override `ownerId` on retry so a user cannot retry another user's job if they know the id.
- `/uploads/*` and `/generated-results/*` serve local runtime files directly; middleware should protect these paths for cookie-authenticated browser sessions.
- `/api/v1/*` and `/api/internal/worker/tick` must remain outside browser SSO middleware because they use API keys and worker tokens.
- Implemented browser SSO with signed HttpOnly `zhinian_session` cookies; middleware validates the signed session instead of exposing JWTs to client JavaScript.
- JWT access tokens are verified in the callback using RS256 and configured JWKS, with issuer, client id, expiry, not-before, issued-at, and scope checks.
- Local file routes now resolve `storagePath` back to an asset record and require the current owner to match before serving bytes.
- Public API v1 remains API-key based and can still read/download its assets through public API routes even when browser SSO protects the Web UI.
## 2026-05-29 Password Captcha Login Findings
- User provided live auth configuration and a password grant sample; real secret values remain only in the ignored local environment file.
- `${AUTH_BASE}/code/image?randomStr=...` returns a PNG captcha image.
- The password grant sample successfully returns a JWT access token, refresh token, expected client/user claims, tenant id, and `server` scope.
- The local `/api/auth/password` endpoint verified the returned JWT with JWKS and created a signed browser session for the authenticated user.
- Browser form login with the displayed math captcha succeeded and redirected to `/create`; the topbar showed the authenticated username and logout button.
- Logout cleared the session and returned to `/auth/login?loggedOut=1`.
## 2026-05-29 Standalone Login Page Findings
- Login routes under `/auth/*` should not render the shared app topbar; the login page is a standalone entry surface.
- The login page now intentionally presents only the NIANXX logo, `智念AIGC平台`, and the account/password/captcha form.
- The visible `统一认证中心` OAuth entry was removed from the login page after user feedback.
- The standalone login page uses the existing GSAP motion helper layer (`runScopedMotion`, `revealChildren`, `pulseFeedback`) for consistent app motion.
- Browser viewport checks passed at 1280x800 and 390x844: no topbar, no SSO link text, logo and platform name present, login panel present, and no horizontal overflow.