Skip to content

MCP Permission and Authorization Flow

This page explains, at a technical level, how basebox ensures that each user can only see and access data they are already permitted to see in a connected system — such as Roxtra, YouTrack, DokuWiki, or any other MCP connector.

The short answer: basebox is transparent. It never manages or replicates the connected system's access rights. Instead, it passes each user's own credentials to the connected system on every single request, so the connected system's own permission model always applies.

The Core Principle

When the assistant calls a tool on a connected system, it does so as that user, using that user's own token or credentials. basebox never uses a shared admin token to retrieve data and then filter it. The connected system receives a request that is indistinguishable from that user logging in directly — and it enforces its own permissions accordingly.

This means:

  • A user in Roxtra with read-only access to project A can only retrieve documents from project A through basebox. Roxtra enforces this, not basebox.
  • A user who has no access to a Confluence space will get the same "not found" or "access denied" response through basebox as they would when opening Confluence in a browser.
  • basebox adds no new rights, and it removes no existing ones (except that write tools are disabled by default).

Sequence: A Tool Call from Chat to Connected System

The following diagram shows the full lifecycle of a single tool call — from the moment a user sends a chat message to the moment the connected system's response is returned.

sequenceDiagram
    autonumber
    actor User as User (Browser)
    participant Frontend as basebox Frontend
    participant basebox as basebox (MCP Gateway)
    participant DB as basebox DB
    participant MCP as MCP Server
    participant Ext as Connected System (e.g. Roxtra)

    User->>Frontend: sends chat message
    Frontend->>basebox: POST /v1/chat (bearer)
    basebox->>basebox: validate bearer (Keycloak), extract user_id

    basebox->>DB: load user settings for user_id
    DB-->>basebox: per-user credentials (tokens) + enabled flags

    basebox->>DB: load tool settings (which tools this AI app exposes)
    DB-->>basebox: allowed tool list for this app

    basebox->>basebox: build ToolAccessControl<br/>(intersection: user enabled AND app enabled)

    basebox->>basebox: send tools + prompt to LLM
    basebox-->>Frontend: stream: LLM decides to call a tool

    basebox->>basebox: merge user credentials into connection_config<br/>(produces Authorization header for this user)

    basebox->>MCP: POST /mcp  with Authorization: Bearer <user_token>
    MCP->>Ext: API call with Authorization: Bearer <user_token>
    Ext-->>MCP: data the user is permitted to see
    MCP-->>basebox: tool result (framed as data, not instructions)
    basebox-->>Frontend: stream: tool result + LLM final answer
    Frontend-->>User: assistant response
BIG PICTURE

Step-by-Step Explanation

Steps 1–3 — User authentication in basebox. The user's browser sends a Keycloak JWT with every request. basebox validates this token and extracts the user_id. This is how basebox knows who is asking.

Steps 4–5 — Load per-user credentials. basebox queries the settings table for this specific user_id. Each row stores the credentials that user entered for a connector. For all connectors that require authentication, basebox asks for a dedicated API token (a revocable, scoped access token generated by the connected system) — not the user's login password. This means the user's primary password is never stored in basebox at any point. The token is stored as entered and is never shared with other users.

Steps 6–7 — Load app tool settings. A basebox AI app (chat assistant) can be configured to expose only a subset of tools. basebox loads this list and computes the intersection: a tool is available in this chat session only if both the user has that connector enabled (with credentials) and the AI app exposes that tool.

Step 8 — Tool access control. This is the gate. A tool is presented to the LLM only when the user has provided their own credentials for that connector. If the user has never configured the connector, no tools from it appear. If the user's credentials are invalid or revoked, the downstream system will reject the call.

Steps 9–10 — LLM selects a tool. The LLM is given the permitted tool list. It decides to call a tool. basebox intercepts this before execution.

Step 11 — Credential injection. basebox takes the user's stored credentials and merges them into the connection configuration for this tool call, producing an Authorization header (Bearer token or HTTP Basic) scoped to this user. No other user's credentials are ever in scope here.

Steps 12–13 — Call reaches the connected system as that user. The MCP server forwards the Authorization header verbatim to the connected system. From the connected system's point of view, this is a normal API request from that user. The connected system applies its own access controls — ACLs, roles, spaces, project memberships — exactly as it would for any other request from that user.

Steps 14–16 — Only permitted data returns. The connected system responds with whatever that user is allowed to see. basebox frames the result as data (not instructions) to prevent prompt injection, and streams it back to the user.

Key Security Properties

Property How it is implemented
Per-user isolation Each user's credentials are stored separately in settings; they are loaded by user_id at the start of every chat request
No shared admin token basebox never holds a single elevated token that it uses on behalf of all users; each call is authenticated with the requesting user's own credentials
No credential caching across users Credentials are resolved fresh from the database for each request; they are never stored in process memory across requests or shared between concurrent sessions
Connected system enforces its own permissions basebox passes credentials through and returns whatever the system returns; it adds no filtering layer and removes no access checks
Write access is off by default All write-capable tools (create, update, delete) are disabled by default at the AI app level; an administrator must explicitly enable them
Credential confidentiality Credentials never appear in production logs; they are present only at DEBUG log level and only as part of intentional diagnostic runs

What Basebox Does NOT Do

  • It does not maintain its own copy of the connected system's permission model.
  • It does not map basebox roles to connected-system roles.
  • It does not cache or aggregate responses across users.
  • It does not grant any access beyond what the user already has in the connected system.

If a user's account in the connected system is deprovisioned or their token is revoked, basebox loses access on the very next request — there is no session or cache to invalidate.

Administrator Configuration

Administrators enable connectors and provide a base endpoint URL (and optionally a shared read-only service account for connectors that support it). Each individual user then enters their own credentials when they activate a connector under their own profile. The administrator cannot see or use another user's credentials.

For connectors like Roxtra, YouTrack, or DokuWiki that use personal API tokens, the flow is:

  1. The administrator enables the connector and sets the endpoint URL.
  2. Each user opens Settings → Connectors, enters their personal token, and clicks Test connection.
  3. From that point on, all tool calls made by that user go to the connected system authenticated as that user.