Skip to content

[FEATURE][AUTH]: Per-user personal credential store for gateways β€” encrypted API keys, bearer tokens, basic authΒ #4006

@ecthelion77

Description

@ecthelion77

🎯 Feature Request: Per-User Personal Credential Store for Gateways

Summary

Allow users to store personal credentials (API keys, bearer tokens, basic auth) for specific gateways via the Admin UI and REST API. These credentials are encrypted at rest and used automatically during tool invocation when available, falling back to the shared gateway auth if not.

Problem

Some upstream APIs behind MCP gateways require per-user credentials that cannot be shared:

  • APIs that only support API key auth (no OAuth2), e.g. Freshservice PM endpoints
  • APIs where each user has their own license-bound API key
  • Services where OAuth2 is available for some endpoints but not all

Currently, the gateway supports:

  1. Shared auth (auth_value on the gateway): one credential for all users β€” not viable when credentials are personal
  2. OAuth2 per-user tokens: works well for OAuth-capable services, but not all APIs support OAuth2

There is no mechanism for a user to store a personal, non-OAuth credential that is automatically used during tool invocation.

Proposed Solution

DB Model: UserGatewayCredential

A new table storing per-user credentials with:

  • gateway_id (FK β†’ gateways)
  • app_user_email (FK β†’ email_users)
  • credential_type: api_key | bearer_token | basic_auth
  • credential_value: encrypted using existing EncryptedText (Argon2id + Fernet)
  • label: optional description
  • Unique constraint on (gateway_id, app_user_email)

REST API (/credentials/)

  • POST /credentials/{gateway_id} β€” store/update credential (upsert)
  • GET /credentials/{gateway_id} β€” check credential status (no secret exposed)
  • DELETE /credentials/{gateway_id} β€” revoke credential
  • GET /credentials β€” list all credentials for current user

ToolService Integration

During tool invocation, the auth resolution order becomes:

  1. Per-user OAuth token (existing OAuthToken) β€” if gateway has OAuth configured
  2. Per-user personal credential (UserGatewayCredential) β€” NEW
  3. Shared gateway auth (gateway.auth_value) β€” existing fallback

This applies to both the Rust execution plan path and the Python MCP tool invocation path.

Admin UI

A "πŸ”‘ Credential" button on each gateway card opens a modal where users can:

  • Select credential type (API key, Bearer token, Basic auth)
  • Enter and store their credential (encrypted)
  • View status and revoke

Benefits

  • Zero code change for API consumers β€” credentials are used transparently during tool invocation
  • Reuses existing encryption infrastructure (EncryptedText, EncryptionService)
  • Consistent with existing OAuth token pattern β€” same per-user concept, different auth mechanism
  • Solves real-world gap β€” many enterprise APIs still use API key auth alongside or instead of OAuth2

Relationship to Other Issues

Implementation Reference

We have a working implementation on our fork that can serve as a basis for an upstream PR:

  • forterro/mcp-context-forge branch feature/personal-credential-store

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions