Skip to content

feat(auth): replace JWT-as-API-key with hashed PATs + per-space API access gate#1524

Merged
MODSetter merged 31 commits into
MODSetter:devfrom
AnishSarkar22:feat/api-key
Jun 23, 2026
Merged

feat(auth): replace JWT-as-API-key with hashed PATs + per-space API access gate#1524
MODSetter merged 31 commits into
MODSetter:devfrom
AnishSarkar22:feat/api-key

Conversation

@AnishSarkar22

@AnishSarkar22 AnishSarkar22 commented Jun 19, 2026

Copy link
Copy Markdown
Collaborator

Description

  • Add hashed Personal Access Tokens (PATs) with storage, CRUD API routes, and a settings UI (copy-once).
  • Wire PAT auth into web client, browser extension, and Obsidian connector setup (replaces daily-expiry JWT).
  • Add per-space api_access_enabled toggle + API_ACCESS_MANAGE permission; PATs gated at the RBAC chokepoint (sessions bypass).
  • Unify authorization behind a single AuthContext (session or PAT); retire fail-open current_active_user.
  • Route chat, integration, knowledge, automation, and snapshot/document routes through AuthContext.
  • Enforce fail-closed model: PATs reach space resources only via the chokepoint; everything else needs a session.
  • Add bootstrap allowlist (allow_any_principal) for spaceless probes (/verify-token, /obsidian/health, GET /searchspaces).
  • Require sessions for identity-only routes and personal model-connection writes.
  • Gate connector folder/channel listings (Slack, Discord, Google Drive, Composio, Dropbox, OneDrive) behind space access.
  • Add tests for PAT fail-closed authorization.
  • Simplify error screen layout; remove unused components.

Motivation and Context

FIX #

Screenshots

API Changes

  • This PR includes API changes

Change Type

  • Bug fix
  • New feature
  • Performance improvement
  • Refactoring
  • Documentation
  • Dependency/Build system
  • Breaking change
  • Other (specify):

Testing Performed

  • Tested locally
  • Manual/QA verification

Checklist

  • Follows project coding standards and conventions
  • Documentation updated as needed
  • Dependencies updated as needed
  • No lint/build errors or new warnings
  • All relevant tests are passing

High-level PR Summary

This PR replaces short-lived JWT tokens with personal access tokens (PATs) for programmatic API access. The implementation introduces a fail-closed authorization model where PATs are scoped to search spaces with an api_access_enabled toggle, ensuring that API access requires explicit opt-in per workspace. The backend adds a new AuthContext abstraction that unifies session-based and PAT-based authentication, replaces all current_active_user dependencies with get_auth_context, and implements RBAC gates that enforce the API access policy. The frontend now features a PAT management UI in user settings, updates the Obsidian connector flow to create tokens on demand, and adds search-space-level API access controls. Migration 166 creates the personal_access_tokens table and adds the api_access_enabled column to search spaces, with existing spaces defaulting to enabled for backward compatibility.

⏱️ Estimated Review Time: 3+ hours

💡 Review Order Suggestion
Order File Path
1 surfsense_backend/.env.example
2 surfsense_backend/app/config/__init__.py
3 surfsense_backend/app/db.py
4 surfsense_backend/alembic/versions/166_add_pat_and_api_access.py
5 surfsense_backend/app/auth/__init__.py
6 surfsense_backend/app/auth/context.py
7 surfsense_backend/app/utils/pat.py
8 surfsense_backend/app/users.py
9 surfsense_backend/app/schemas/pat.py
10 surfsense_backend/app/routes/personal_access_tokens_routes.py
11 surfsense_backend/app/routes/__init__.py
12 surfsense_backend/app/utils/rbac.py
13 surfsense_backend/app/routes/search_spaces_routes.py
14 surfsense_backend/app/schemas/__init__.py
15 surfsense_backend/app/schemas/search_space.py
16 surfsense_backend/app/app.py
17 surfsense_backend/app/routes/obsidian_plugin_routes.py
18 surfsense_backend/app/automations/services/automation.py
19 surfsense_backend/app/automations/services/run.py
20 surfsense_backend/app/automations/services/trigger.py
21 surfsense_backend/app/agents/chat/multi_agent_chat/main_agent/runtime/factory.py
22 surfsense_backend/app/agents/chat/multi_agent_chat/main_agent/tools/automation/create.py
23 surfsense_backend/app/agents/chat/multi_agent_chat/main_agent/tools/registry.py
24 surfsense_backend/app/automations/actions/builtin/agent_task/invoke.py
25 surfsense_backend/app/tasks/chat/streaming/agent/builder.py
26 surfsense_backend/app/tasks/chat/streaming/flows/new_chat/orchestrator.py
27 surfsense_backend/app/tasks/chat/streaming/flows/resume_chat/orchestrator.py
28 surfsense_backend/app/gateway/agent_invoke.py
29 surfsense_backend/app/gateway/auth_invariant.py
30 surfsense_backend/app/services/chat_comments_service.py
31 surfsense_backend/app/services/public_chat_service.py
32 surfsense_backend/tests/integration/test_pat_fail_closed_authz.py
33 surfsense_backend/tests/unit/test_pat_fail_closed_static.py
34 surfsense_web/contracts/types/pat.types.ts
35 surfsense_web/lib/apis/pats-api.service.ts
36 surfsense_web/hooks/use-pats.ts
37 surfsense_web/app/dashboard/[search_space_id]/user-settings/components/ApiKeyContent.tsx
38 surfsense_web/components/assistant-ui/connector-popup/connect-forms/components/obsidian-connect-form.tsx
39 surfsense_web/components/settings/general-settings-manager.tsx
40 surfsense_web/contracts/types/search-space.types.ts
41 surfsense_web/lib/apis/search-spaces-api.service.ts
42 surfsense_web/atoms/search-spaces/search-space-mutation.atoms.ts

Need help? Join our Discord

- Removed the Alert component and its related imports to streamline the error display.
- Adjusted the layout of the error screen for better responsiveness and visual clarity.
- Updated button styles and structure for improved user interaction.
@vercel

vercel Bot commented Jun 19, 2026

Copy link
Copy Markdown

@AnishSarkar22 is attempting to deploy a commit to the Rohan Verma's projects Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai

coderabbitai Bot commented Jun 19, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: d9bd5910-b8b0-442c-808b-5e05a022e73f

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@AnishSarkar22 AnishSarkar22 changed the title Feat/api key feat(auth): replace JWT-as-API-key with hashed PATs + per-space API access gate Jun 19, 2026
@MODSetter MODSetter merged commit a0f44b2 into MODSetter:dev Jun 23, 2026
6 of 12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants