feat(auth): add optional single-owner OIDC sign-in by idkwhodatis · Pull Request #197 · TNT-Likely/PanWatch · GitHub
Skip to content

feat(auth): add optional single-owner OIDC sign-in - #197

Open
idkwhodatis wants to merge 4 commits into
TNT-Likely:mainfrom
idkwhodatis:feat/oidc-sso-upstream
Open

idkwhodatis wants to merge 4 commits into
TNT-Likely:mainfrom
idkwhodatis:feat/oidc-sso-upstream

Conversation

@idkwhodatis

Copy link
Copy Markdown
Contributor

English

Add opt-in single-owner OIDC with PKCE, issuer/subject allowlists, revocable sessions, CSRF/origin checks and cross-tab recovery. Password fallback is explicit; allowed identities receive owner access. Logout is local.

Local checks: 268 backend, 268 frontend, guards/build passed; 60 subpath-only cases skipped. No live IdP/browser or formal security audit. Shares only static-containment/public-URL prerequisites with the subpath PR.

中文

新增默认关闭的单所有者 OIDC,支持 PKCE、issuer/subject 白名单、可撤销会话、CSRF/来源校验和跨标签页恢复。密码回退需显式开启;获准身份拥有所有者权限,退出仅在本地生效。

本地后端 268 项、前端 268 项、规范检查及构建通过;60 项子路径专用用例跳过。未执行真实 IdP/浏览器或正式安全审计。与子路径 PR 仅共享静态文件隔离和公共 URL 基础提交。

@idkwhodatis
idkwhodatis marked this pull request as ready for review October 11, 2026 19:25
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 11, 2026 •

Copy link
Copy Markdown

Copy link
Copy Markdown
Contributor Author

Additional review detail (English)

Implementation and scope

Head 1000ab7 includes upstream 575b27a. OIDC_ENABLED opts into single-owner SSO. Exact issuer/subject allowlisting, PKCE/state/nonce and signed-token validation precede local SQLite sessions storing hashed credentials. Every allowed subject gets owner access. Canonical callbacks use OIDC_PUBLIC_URL; password fallback requires OIDC_ALLOW_PASSWORD_LOGIN.

Cookie mutations require canonical Origin plus CSRF. Session generations prevent delayed callbacks/logout responses reviving or overwriting newer logins; private SSE rechecks session validity. Upstream onboarding remains protected, including its reads, mutations and post-logout denial. Existing sessions require fresh sign-in.

Local verification

Portable equivalents of recorded scopes:

  • Backend: python -m pytest -q tests/test_oidc*.py tests/test_selfcheck.py tests/test_recommendations_readonly.py tests/test_assistant_exports.py tests/test_static_assets_security.py tests/test_pats_api.py tests/test_architecture_boundaries.py tests/test_onboarding.py tests/test_etf_support.py tests/test_server_lifespan.py tests/test_template_import.py packages/marketdata/tests/test_kline_vendors.py: 268 passed, 60 subpath-only skips.
  • FastAPI 0.110.1 / Starlette 0.37.2: python -m pytest -q tests/test_oidc*.py tests/test_static_assets_security.py tests/test_onboarding.py: 157 passed, 60 skips. Final onboarding assertions were rerun via tests/test_oidc_subpath_integration.py: one passed/four prefixed-only skips on each routing version.
  • From frontend: pnpm run test --run --maxWorkers=1 tests/auth tests/api/oidcAuth.test.ts tests/api/passwordLogout.test.ts tests/api/unauthorizedSession.test.ts tests/api/crossTabPasswordFallback.test.ts tests/api/oidc-public-path.test.ts tests/api/public-url.test.ts tests/api/health.test.ts tests/api/recommendations.test.ts tests/i18n/Login.test.tsx tests/onboarding tests/portfolio/Stocks-etf.test.tsx tests/routing/page-loaders.test.ts: 268 passed; guards/build passed.

Boundaries and integration

Logout is local. No real-IdP/browser acceptance, formal security audit, Docker or Python 3.11 validation is claimed. Subpath skips require #198. Only 10590ef (static containment) and 97c5aac (neutral public URLs) are shared with #198; neither depends on #193–196. Prefer merge commits; after squashing either, refresh its sibling. At the 2026-10-11 19:26 UTC check, upstream Actions was action_required with no jobs executed.

补充审阅说明(中文)

实现与范围

提交 1000ab7 已包含上游 575b27a。通过 OIDC_ENABLED 显式启用单所有者 SSO。先校验精确 issuer/subject 白名单、PKCE/state/nonce 和签名令牌,再建立仅保存凭据哈希的本地 SQLite 会话。所有获准 subject 都获得所有者权限。规范回调地址来自 OIDC_PUBLIC_URL;密码回退需要 OIDC_ALLOW_PASSWORD_LOGIN。

Cookie 鉴权的修改请求需要规范 Origin 和 CSRF。会话代际保护避免延迟回调/退出响应复活旧登录或覆盖新登录;私有 SSE 持续复查会话有效性。上游引导接口保持受保护,包括读取、修改和退出后的拒绝访问。已有会话需要重新登录。

本地验证

以下为已记录测试范围的可移植等价命令:

  • 后端:python -m pytest -q tests/test_oidc*.py tests/test_selfcheck.py tests/test_recommendations_readonly.py tests/test_assistant_exports.py tests/test_static_assets_security.py tests/test_pats_api.py tests/test_architecture_boundaries.py tests/test_onboarding.py tests/test_etf_support.py tests/test_server_lifespan.py tests/test_template_import.py packages/marketdata/tests/test_kline_vendors.py:268 项通过,60 项仅适用于子路径的测试跳过。
  • FastAPI 0.110.1 / Starlette 0.37.2:python -m pytest -q tests/test_oidc*.py tests/test_static_assets_security.py tests/test_onboarding.py:157 项通过、60 项跳过。最终引导鉴权断言通过 tests/test_oidc_subpath_integration.py 单独重跑:两组路由版本各 1 项通过、4 项带前缀用例跳过。
  • 在 frontend 中执行 pnpm run test --run --maxWorkers=1 tests/auth tests/api/oidcAuth.test.ts tests/api/passwordLogout.test.ts tests/api/unauthorizedSession.test.ts tests/api/crossTabPasswordFallback.test.ts tests/api/oidc-public-path.test.ts tests/api/public-url.test.ts tests/api/health.test.ts tests/api/recommendations.test.ts tests/i18n/Login.test.tsx tests/onboarding tests/portfolio/Stocks-etf.test.tsx tests/routing/page-loaders.test.ts:268 项通过;规范检查/构建通过。

边界与集成

退出仅在本地生效。未声称真实 IdP/浏览器验收、正式安全审计、Docker 或 Python 3.11 验证。跳过的子路径用例需要 #198。与 #198 仅共享 10590ef(静态文件路径隔离)和 97c5aac(中立公共 URL);两者都不依赖 #193–196。建议保留 merge commit;若 squash 合并任一 PR,先更新另一个分支。2026-10-11 19:26 UTC 检查时,上游 Actions 为 action_required,尚无 job 执行。

@TNT-Likely

Copy link
Copy Markdown
Owner

我们已上线PR 范围与验收规范:一个 PR 完成一个可独立使用的行为,初始规模门槛为20个生产文件/800行新增加删除(排除测试、Markdown文档与已知lockfile),并提供关联当前head的验收报告。现有PR从机器人首次整改提示起获得完整14天窗口,第7天提醒;需要更多时间可以申请暂停。

可选的单所有者SSO场景成立,计划作为后续高级部署能力推进。获准身份使用同一个owner权限与资产空间,需要在文档和用户流程中明确。

请先明确最小完整登录流程与支持范围,并将有独立价值的公共URL/会话等基础调整拆出;不扩展多人资产隔离或权限系统。我们希望先完成一条SSO接入路径,再根据部署需求评估另一条网关认证路径。

后续验收需绑定当前head,提供真实IdP、浏览器登录/退出/过期会话和本地登录兼容证据,以及实际测试命令。若在等待产品排期,可暂停自动整改计时;功能不要求现在一次完成所有认证扩展。

@TNT-Likely TNT-Likely added the pr:needs-split PanWatch contribution policy; see docs/pr-policy.md label Oct 13, 2026
@github-actions

github-actions Bot commented Oct 13, 2026 •

Copy link
Copy Markdown

PanWatch contribution check

This PR needs changes before review.

Scope: 32 production files, 1632 added + deleted production lines. Tests, Markdown docs and known lockfiles are excluded.

  • Fill the "Background" section; comments/placeholders do not count.

  • Fill the "Changes" section; comments/placeholders do not count.

  • Fill the "Scope" section; comments/placeholders do not count.

  • Fill the "Validation" section; comments/placeholders do not count.

  • Fill the "Acceptance evidence" section; comments/placeholders do not count.

  • Fill the "Boundaries and risks" section; comments/placeholders do not count.

  • Fill the "Follow-up" section; comments/placeholders do not count.

  • Validation must name the current PR head in "Tested commit:" (7–40 hexadecimal characters).

  • Validation needs "Commands and results:" with actual outcomes, or a justified non-applicability statement.

  • Acceptance evidence needs "Steps:"; link evidence or include sanitized output where appropriate.

  • Acceptance evidence needs "Expected:"; link evidence or include sanitized output where appropriate.

  • Acceptance evidence needs "Observed:"; link evidence or include sanitized output where appropriate.

  • Acceptance evidence needs "Evidence:"; link evidence or include sanitized output where appropriate.

  • Scope exceeds the budget: 32 production files / 1632 added+deleted lines; split into independently usable PRs or request a maintainer scope exception.

  • A maintainer requested a scope split (pr:needs-split); ask for re-review after narrowing the PR.

Reminder: Please resolve the items by 2026-10-27T10:12:10.863Z (14 days from the first notice). Comments and pushes do not extend this deadline. A maintainer may apply pr:hold when more time is justified; removing it grants a fresh window.

If unresolved, this PR will be closed on a daily sweep. The branch is preserved; reopen or submit smaller PRs when ready. Existing PRs receive the same full notice period.

Contribution policy

本检查只核对材料与改动规模,不代表产品或实现已经验收。首次提示后有14天整改窗口;第7天提醒,逾期仍未达标自动关闭。维护者可用 pr:hold 暂停;关闭后仍可重开或提交拆分版本。

@github-actions

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

pr:needs-split PanWatch contribution policy; see docs/pr-policy.md pr:needs-work PanWatch contribution policy; see docs/pr-policy.md

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants