fix(oauth): allow generic RFC 7591 DCR + expand install snippets
All checks were successful
Deploy to Production / deploy (push) Successful in 1m28s
All checks were successful
Deploy to Production / deploy (push) Successful in 1m28s
- /oauth/register: drop resource_required check, accept generic registrations (Claude Desktop omits resource in DCR body per spec). serverId stored as NULL; /authorize still enforces org-ownership + access-token aud claim still pinned to resource. Fixes Claude Desktop DCR failure (ofid_d7e39530c109fa7f). - /oauth/authorize: skip strict server.id check when client.serverId is NULL (generic client); org check remains the security boundary. - schema: oauth_clients.server_id no longer NOT NULL. - migration 0002: ALTER COLUMN server_id DROP NOT NULL (already applied on prod). - install-snippets: add Claude Code (CLI), VS Code, Codex, raw URL tabs. Claude Desktop now shows form-field values (Name / Remote MCP Server URL / OAuth Client ID / Secret) matching the new Custom Connector UI instead of the obsolete JSON config. - types: InstallTarget enum extended. - hero-video: clicking the audio toggle restarts the video from frame 0 so unmute aligns with the spoken opening. - marketing: drop em-dashes from rendered copy.
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
-- Allow generic RFC 7591 Dynamic Client Registration:
|
||||
-- a client may register without binding to a specific MCP server.
|
||||
-- /oauth/authorize still enforces the org-ownership check on every
|
||||
-- authorization, and the access-token `aud` claim is pinned to the
|
||||
-- resource declared at /token, so a generic client cannot mint a
|
||||
-- token usable against a server outside the user's org.
|
||||
ALTER TABLE oauth_clients
|
||||
ALTER COLUMN server_id DROP NOT NULL;
|
||||
@@ -260,9 +260,13 @@ export const secrets = pgTable('secrets', {
|
||||
|
||||
export const oauthClients = pgTable('oauth_clients', {
|
||||
id: uuid('id').defaultRandom().primaryKey(),
|
||||
serverId: uuid('server_id')
|
||||
.references(() => mcpServers.id, { onDelete: 'cascade' })
|
||||
.notNull(),
|
||||
// Nullable: RFC 7591 Dynamic Client Registration treats the `resource`
|
||||
// claim as optional, so a client may register generically and only bind
|
||||
// to a specific server at /oauth/authorize. /authorize enforces the
|
||||
// org-ownership check on every authorization either way.
|
||||
serverId: uuid('server_id').references(() => mcpServers.id, {
|
||||
onDelete: 'cascade',
|
||||
}),
|
||||
clientId: varchar('client_id', { length: 128 }).notNull().unique(),
|
||||
clientSecretHash: text('client_secret_hash'),
|
||||
redirectUris: jsonb('redirect_uris').notNull(),
|
||||
|
||||
@@ -175,5 +175,13 @@ export type IterateServerInput = z.infer<typeof IterateServerInput>;
|
||||
|
||||
// ---- Install snippets ----
|
||||
|
||||
export const InstallTarget = z.enum(['claude-desktop', 'cursor', 'chatgpt']);
|
||||
export const InstallTarget = z.enum([
|
||||
'claude-desktop',
|
||||
'claude-code',
|
||||
'cursor',
|
||||
'vscode',
|
||||
'chatgpt',
|
||||
'codex',
|
||||
'raw-url',
|
||||
]);
|
||||
export type InstallTarget = z.infer<typeof InstallTarget>;
|
||||
|
||||
Reference in New Issue
Block a user