Diffinery

codician/diffinerypublic

Open-source, agent-first GitHub and GitHub Actions alternative that runs on your own Cloudflare account: git hosting, pull requests, code review and drop-in GitHub Actions YAML on Workers, Durable Objects, R2 and Containers.

57 lines · 2.6 KBRaw History
1-- OAuth 2.1 sign-in for MCP clients (auth/oauth.ts): claude.ai connectors, Claude Code, Codex,
2-- Cursor and other apps connect to /mcp by sending the person through /oauth/authorize instead of
3-- asking for a pasted token. Only hashes of codes, refresh tokens and client secrets are stored.
4
5-- Apps that registered themselves (RFC 7591 dynamic registration, client_id "dfc_…") or that
6-- identify by a client metadata document (client_id is the document's https URL, cached here).
7CREATE TABLE IF NOT EXISTS oauth_clients (
8 id TEXT PRIMARY KEY,
9 kind TEXT NOT NULL CHECK (kind IN ('registered', 'metadata')),
10 name TEXT NOT NULL,
11 client_uri TEXT,
12 redirect_uris TEXT NOT NULL, -- JSON array
13 auth_method TEXT NOT NULL DEFAULT 'none' CHECK (auth_method IN ('none', 'client_secret_basic', 'client_secret_post')),
14 secret_hash TEXT,
15 software TEXT, -- software_id and software_version as the app sent them
16 created_at TEXT NOT NULL,
17 fetched_at TEXT, -- metadata documents: when the document was last read
18 used_at TEXT
19);
20
21-- One connection: a person allowed an app to act as them or as one of their agents. Its access
22-- tokens are ordinary tokens (tokens.oauth_grant_id); revoking the connection revokes them.
23CREATE TABLE IF NOT EXISTS oauth_grants (
24 id TEXT PRIMARY KEY,
25 client_id TEXT NOT NULL,
26 client_name TEXT NOT NULL, -- as shown when the person approved it
27 redirect_host TEXT NOT NULL,
28 person_id TEXT NOT NULL, -- who approved it
29 account_id TEXT NOT NULL, -- whom its tokens act as: the person or one of their agents
30 scope TEXT NOT NULL,
31 refresh_hash TEXT UNIQUE,
32 prev_refresh_hash TEXT, -- the refresh token it replaced, to spot a stolen one being reused
33 refreshed_at TEXT,
34 refresh_expires_at TEXT NOT NULL,
35 created_at TEXT NOT NULL,
36 used_at TEXT,
37 revoked_at TEXT
38);
39CREATE INDEX IF NOT EXISTS oauth_grants_person ON oauth_grants(person_id, revoked_at);
40CREATE INDEX IF NOT EXISTS oauth_grants_prev ON oauth_grants(prev_refresh_hash);
41
42-- Authorization codes: one use, a few minutes, bound to the PKCE challenge and redirect URI.
43CREATE TABLE IF NOT EXISTS oauth_codes (
44 code_hash TEXT PRIMARY KEY,
45 client_id TEXT NOT NULL,
46 redirect_uri TEXT NOT NULL,
47 code_challenge TEXT NOT NULL,
48 person_id TEXT NOT NULL,
49 account_id TEXT NOT NULL,
50 scope TEXT NOT NULL,
51 created_at TEXT NOT NULL,
52 expires_at TEXT NOT NULL,
53 used_at TEXT
54);
55
56ALTER TABLE tokens ADD COLUMN oauth_grant_id TEXT;
57CREATE INDEX IF NOT EXISTS tokens_oauth_grant ON tokens(oauth_grant_id);