Skip to content

Auth & security

The DFL MCP never has its own “god mode” view of the data. Every request runs as you. This page explains how that works so you know exactly what an AI assistant can — and can’t — do on your behalf.

The auth flow

  1. GitHub OAuth. dfl-auth login sends you through GitHub OAuth, brokered by Supabase. On success you get a JWT access token and a refresh token.

  2. Bearer on every call. Your client sends Authorization: Bearer <access_token> with each MCP request. The endpoint validates the JWT’s signature and expiry.

  3. Per-session Supabase client. The endpoint builds a Supabase client using your JWT for the lifetime of that session — not a service key. So every read and write is executed with your identity.

  4. RLS decides. PostgreSQL Row-Level Security policies and your IAM role determine which rows you can see and which mutations you can make.

dfl-auth login ──▶ GitHub OAuth (via Supabase) ──▶ JWT (access + refresh)
client ── Authorization: Bearer <JWT> ──▶ MCP endpoint ─┤
Supabase client bound to YOUR JWT
RLS + your IAM role = what you can do

What you can see and change

Because the MCP acts as you under RLS:

  • You see your data and anything your role is allowed to read.
  • You can mutate only what your role permits.
  • A 403 Forbidden means your permissions don’t allow it — the MCP is faithfully enforcing your access, not malfunctioning.

Where your credentials live

PathContentsNotes
~/.dfl-mcp/project.jsonSupabase project configWritten by dfl-auth configure
~/.dfl-mcp/credentials.jsonaccess_token, refresh_token, expires_atWritten by dfl-auth login; auto-refreshed

Token lifetime & refresh

Access tokens are short-lived by design. Refresh without re-doing the browser login:

  • CLI: npx @devfellowship/dfl-auth refresh
  • JS/TS: getValidAccessToken() from @devfellowship/dfl-auth auto-refreshes
  • Any HTTP client: POST <endpoint>/auth/refresh with { "refresh_token": "..." } (no auth header needed)

See the full troubleshooting flow in Getting Started → Token refresh.

Transport security

  • All endpoints are HTTPS-only behind Traefik.
  • helmet, CORS, and per-endpoint rate limiting are enabled.
  • /health is the only unauthenticated route; /mcp always requires a valid JWT.