n8n/docs/generated/sqlite-schema/oauth_authorization_codes.md
Ricardo Espinoza 0432bc926c
feat(core): Support Client ID Metadata Documents on the MCP OAuth server
Recognize an HTTPS-URL client_id as a Client ID Metadata Document (CIMD): the
server fetches the client's OAuth metadata from that URL and uses it as the
verifiable client identity, instead of requiring Dynamic Client Registration.
DCR stays available and unchanged for clients that don't support CIMD.

Backend:
- New CimdMetadataHttpClient fetches the document. The client_id URL is
  attacker-influenced and fetched pre-auth, so the request is always routed
  through the SSRF filter regardless of N8N_SSRF_PROTECTION_ENABLED; the
  document is validated (HTTPS, redirect_uris present, client_id matches the
  URL) and cached.
- The clients store resolves a URL client_id from its cached document, which
  stays the source of truth; a row is persisted only to satisfy the
  consent/token foreign keys, marked isCimd and excluded from the
  registered-client cap (which bounds anonymous DCR).
- Per the CIMD trust model the requested redirect_uri is validated against the
  document's declared redirect_uris (by the SDK) rather than the instance
  redirect-URI allowlist.
- Gated behind N8N_OAUTH_SERVER_CIMD_ENABLED (default on).

Frontend:
- CIMD clients get a dedicated trust card on the consent screen: the verifiable
  domain, where the authorization code is sent (green check for loopback, a
  neutral host line otherwise), and an honest caveat that the name/icon are
  self-reported and unreviewed, with a link to the raw metadata document. They
  skip the manual redirect-trust acknowledgement DCR clients still require.
- The connected-clients settings show a "Verified" badge for CIMD clients.

Adds an isCimd column to oauth_clients (migration) and exposes isCimd on the
OAuth client and consent-details payloads.
2026-08-04 11:05:09 -04:00

3.7 KiB

oauth_authorization_codes

Description

Table Definition
CREATE TABLE "oauth_authorization_codes" ("code" varchar(255) PRIMARY KEY NOT NULL, "clientId" varchar NOT NULL, "userId" varchar NOT NULL, "redirectUri" varchar NOT NULL, "codeChallenge" varchar NOT NULL, "codeChallengeMethod" varchar(255) NOT NULL, "expiresAt" bigint NOT NULL, "state" varchar, "used" boolean NOT NULL DEFAULT (false), "createdAt" datetime(3) NOT NULL DEFAULT (STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW')), "updatedAt" datetime(3) NOT NULL DEFAULT (STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW')), "resource" varchar, "scope" text NOT NULL DEFAULT ('["tool:listWorkflows","tool:getWorkflowDetails"]'), CONSTRAINT "FK_e829ca1240b877f73fd5fab14a2" FOREIGN KEY ("userId") REFERENCES "user" ("id") ON DELETE CASCADE ON UPDATE NO ACTION, CONSTRAINT "FK_81de58036895ccabf2214c6d99e" FOREIGN KEY ("clientId") REFERENCES "oauth_clients" ("id") ON DELETE CASCADE ON UPDATE NO ACTION)

Columns

Name Type Default Nullable Children Parents Comment
clientId varchar false oauth_clients
code varchar(255) false
codeChallenge varchar false
codeChallengeMethod varchar(255) false
createdAt datetime(3) STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') false
expiresAt bigint false
redirectUri varchar false
resource varchar true
scope TEXT '["tool:listWorkflows","tool:getWorkflowDetails"]' false
state varchar true
updatedAt datetime(3) STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') false
used boolean false false
userId varchar false user

Constraints

Name Type Definition
- (Foreign key ID: 0) FOREIGN KEY FOREIGN KEY (clientId) REFERENCES oauth_clients (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE
- (Foreign key ID: 1) FOREIGN KEY FOREIGN KEY (userId) REFERENCES user (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE
code PRIMARY KEY PRIMARY KEY (code)
sqlite_autoindex_oauth_authorization_codes_1 PRIMARY KEY PRIMARY KEY (code)

Indexes

Name Definition
sqlite_autoindex_oauth_authorization_codes_1 PRIMARY KEY (code)

Relations

erDiagram

"oauth_authorization_codes" }o--|| "oauth_clients" : "FOREIGN KEY (clientId) REFERENCES oauth_clients (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE"
"oauth_authorization_codes" }o--|| "user" : "FOREIGN KEY (userId) REFERENCES user (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE"

"oauth_authorization_codes" {
  varchar clientId FK
  varchar_255_ code PK
  varchar codeChallenge
  varchar_255_ codeChallengeMethod
  datetime_3_ createdAt
  bigint expiresAt
  varchar redirectUri
  varchar resource
  TEXT scope
  varchar state
  datetime_3_ updatedAt
  boolean used
  varchar userId FK
}
"oauth_clients" {
  varchar_255_ clientSecret
  bigint clientSecretExpiresAt
  datetime_3_ createdAt
  TEXT grantTypes
  varchar id PK
  boolean isCimd
  boolean isFirstParty
  varchar_255_ name
  TEXT redirectUris
  varchar_255_ tokenEndpointAuthMethod
  datetime_3_ updatedAt
}
"user" {
  datetime_3_ createdAt
  boolean disabled
  varchar_255_ email
  varchar_32_ firstName
  varchar id PK
  date lastActiveAt
  varchar_32_ lastName
  boolean mfaEnabled
  TEXT mfaRecoveryCodes
  TEXT mfaSecret
  varchar password
  TEXT personalizationAnswers
  varchar_128_ roleSlug FK
  TEXT settings
  datetime_3_ updatedAt
}

Generated by tbls