Skip to content

feat(gateway): add per-user personal credential store#4024

Open
ecthelion77 wants to merge 3 commits intoIBM:mainfrom
forterro:feat/personal-credential-store-upstream
Open

feat(gateway): add per-user personal credential store#4024
ecthelion77 wants to merge 3 commits intoIBM:mainfrom
forterro:feat/personal-credential-store-upstream

Conversation

@ecthelion77
Copy link
Copy Markdown
Contributor

@ecthelion77 ecthelion77 commented Apr 3, 2026

✨ Feature / Enhancement PR

🔗 Epic / Issue

Closes #4006


🚀 Summary (1-2 sentences)

Add a personal credential storage system enabling individual users to store their own API keys/tokens for specific gateways, with automatic per-user auth on non-OAuth tool invocations.


🧪 Checks

  • make lint passes (ruff + black)
  • make test passes
  • CHANGELOG updated (if user-facing)

📓 Notes

Use case

Some MCP backends require per-user authentication via API keys rather than OAuth. This feature lets each user store their own credentials for a gateway, which are automatically used during tool invocations.

Authentication flow (non-OAuth gateways)

Tool invocation
  └─ Is gateway OAuth? → Yes → existing OAuth flow
  └─ No → Check personal credential for (gateway_id, user_email)
       └─ Found → Build auth header from credential type
       └─ Not found → Fall back to shared gateway auth_value

Supported credential types

  • api_key: Authorization: Basic base64(key:X)
  • bearer_token: Authorization: Bearer <token>
  • basic_auth: Authorization: Basic base64(value)

Changes

File Change
db.py user_gateway_credentials table
credential_storage_service.py CRUD + encryption + auth header builder
credential_router.py REST API (GET/PUT/DELETE per gateway)
tool_service.py Personal credential lookup before shared auth
main.py Router registration
Admin UI (admin.js, gateways.js, admin.html, gateways_partial.html) Credential modal
Alembic migration New table
Unit tests Router + service tests

Security

  • Credentials are encrypted at rest using the existing EncryptionService
  • Each user can only access their own credentials
  • Unique constraint on (gateway_id, user_email) prevents duplicates

@jonpspri jonpspri added the COULD P3: Nice-to-have features with minimal impact if left out; included if time permits label Apr 9, 2026
@ecthelion77 ecthelion77 force-pushed the feat/personal-credential-store-upstream branch from 22aee4a to 0fb03ad Compare April 13, 2026 10:28
@ecthelion77
Copy link
Copy Markdown
Contributor Author

Suggested labels: enhancement, python, security, rbac

@ecthelion77 ecthelion77 force-pushed the feat/personal-credential-store-upstream branch from 0fb03ad to 1e47984 Compare April 14, 2026 12:46
@ecthelion77 ecthelion77 force-pushed the feat/personal-credential-store-upstream branch 6 times, most recently from fdef2a5 to 85e520b Compare April 20, 2026 10:49
@ecthelion77 ecthelion77 force-pushed the feat/personal-credential-store-upstream branch 2 times, most recently from 759ed04 to 51f376c Compare April 27, 2026 09:37
Olivier Gintrand added 2 commits April 27, 2026 12:04
…tion

Signed-off-by: Olivier Gintrand <olivier.gintrand@forterro.com>
Per-user personal credentials (API keys, basic auth) stored in
user_gateway_credentials were only checked when the gateway did NOT
have OAuth configured. For OAuth-enabled gateways (like Freshservice),
the OAuth token was always used even when a per-user API key existed.

Move the per-user credential lookup BEFORE the OAuth branch so that
personal credentials take priority. This fixes write operations on
APIs where OAuth tokens lack sufficient permissions but API keys work
(e.g. Freshservice PM task updates).

Affects both invoke_tool_direct and invoke_tool MCP code paths.

Signed-off-by: Olivier Gintrand <olivier.gintrand@forterro.com>
@ecthelion77 ecthelion77 force-pushed the feat/personal-credential-store-upstream branch from 51f376c to 8c98fe0 Compare April 27, 2026 10:05
…inity

- mcp_session_pool module was removed in upstream; replaced with
  get_session_affinity() from session_affinity module
- settings.mcp_session_pool_enabled replaced with
  settings.mcpgateway_session_affinity_enabled

Signed-off-by: Olivier Gintrand <olivier.gintrand@forterro.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

COULD P3: Nice-to-have features with minimal impact if left out; included if time permits

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEATURE][AUTH]: Per-user personal credential store for gateways — encrypted API keys, bearer tokens, basic auth

2 participants