Skip to content

Comments

feat(oauth): add CIMD support for client metadata discovery#3285

Merged
waleedlatif1 merged 5 commits intostagingfrom
feat/access-page
Feb 21, 2026
Merged

feat(oauth): add CIMD support for client metadata discovery#3285
waleedlatif1 merged 5 commits intostagingfrom
feat/access-page

Conversation

@waleedlatif1
Copy link
Collaborator

Summary

  • Add CIMD (Client ID Metadata Document) support so clients like Claude Desktop can register via metadata URL instead of DCR
  • Fetch, validate, and cache CIMD documents with SSRF protection
  • Upsert CIMD clients as public OAuth apps (no secret, PKCE-only)
  • Advertise client_id_metadata_document_supported in OIDC discovery
  • Fix consent page to handle URL-formatted client_ids (encodeURIComponent) and arbitrary logo domains (<img>)

Type of Change

  • New feature

Testing

Tested manually

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • Tests added/updated and passing
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)

@vercel
Copy link

vercel bot commented Feb 21, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
docs Skipped Skipped Feb 21, 2026 10:21pm

Request Review

@greptile-apps
Copy link
Contributor

greptile-apps bot commented Feb 21, 2026

Greptile Summary

Adds CIMD (Client ID Metadata Document) support to enable OAuth clients like Claude Desktop to register dynamically via metadata URL instead of manual Dynamic Client Registration. The implementation fetches and validates CIMD documents with SSRF protection using DNS-pinned IP resolution, caches metadata with a 5-minute TTL and deduplicates concurrent requests, and upserts clients as public PKCE-only apps with userId: null.

Key changes:

  • New cimd.ts module handles metadata fetching with secureFetchWithValidation for SSRF protection, validates redirect_uris (blocks dangerous schemes, commas), and sanitizes logo_uri to HTTPS-only
  • OAuth flow hook in auth.ts resolves CIMD URLs before authorize/token endpoints, evicts cache on upsert failure to allow retry
  • Consent page encodes URL-formatted client_ids and switches to native <img> to support arbitrary logo domains
  • OIDC discovery advertises client_id_metadata_document_supported: true

Issue found: onConflictDoUpdate missing userId: null - on re-registration, userId won't be explicitly reset

Confidence Score: 4/5

  • Safe to merge with one minor data consistency fix needed
  • Strong security implementation with proper SSRF protection via DNS-pinned IP resolution, comprehensive validation of metadata documents, and efficient caching. The missing userId: null in conflict update could cause inconsistency if a CIMD client is re-registered, but this is unlikely to occur in practice and doesn't pose a security risk
  • apps/sim/lib/auth/cimd.ts needs userId field added to conflict update

Important Files Changed

Filename Overview
apps/sim/lib/auth/cimd.ts New CIMD implementation with SSRF protection, caching, validation - missing userId: null in conflict update
apps/sim/lib/auth/auth.ts Added CIMD resolution hook in OAuth flow with proper error handling and cache eviction on upsert failure
apps/sim/app/(auth)/oauth/consent/page.tsx URL-encoded client_id for CIMD URLs, switched to native <img> for arbitrary logo domains

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    Start[OAuth Request with URL clientId] --> Check{isMetadataUrl?}
    Check -->|No| Normal[Normal OAuth Flow]
    Check -->|Yes| CacheCheck{In Cache?}
    
    CacheCheck -->|Yes| UseCache[Use Cached Metadata]
    CacheCheck -->|No| Fetch[Fetch CIMD Document]
    
    Fetch --> DNS[DNS Lookup]
    DNS --> ValidateIP{IP Private?}
    ValidateIP -->|Yes| Block[Block Request]
    ValidateIP -->|No| PinnedFetch[Fetch with Pinned IP]
    
    PinnedFetch --> Validate[Validate Document]
    Validate --> ValidateClient{clientId matches URL?}
    ValidateClient -->|No| Error1[Reject - Mismatch]
    ValidateClient -->|Yes| ValidateRedirects{redirectUris valid?}
    
    ValidateRedirects -->|No| Error2[Reject - Invalid URIs]
    ValidateRedirects -->|Yes| Cache[Cache Metadata 5min]
    
    Cache --> UseCache
    UseCache --> Upsert[Upsert to DB]
    
    Upsert --> UpsertOK{Success?}
    UpsertOK -->|No| Evict[Evict Cache]
    UpsertOK -->|Yes| Continue[Continue OAuth]
    
    Evict --> Fail[Fail Request]
Loading

Last reviewed commit: f61ff70

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3 files reviewed, 7 comments

Edit Code Review Agent Settings | Greptile

@waleedlatif1
Copy link
Collaborator Author

@greptile

@waleedlatif1
Copy link
Collaborator Author

@cursor review

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3 files reviewed, 4 comments

Edit Code Review Agent Settings | Greptile

@waleedlatif1
Copy link
Collaborator Author

@cursor review

@waleedlatif1
Copy link
Collaborator Author

@greptile

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3 files reviewed, 2 comments

Edit Code Review Agent Settings | Greptile

…tion to CIMD

- Add maxResponseBytes (256KB) to prevent oversized responses
- Validate redirect_uri schemes (https/http only) and reject commas
- Validate logo_uri requires HTTPS, silently drop invalid logos
@waleedlatif1
Copy link
Collaborator Author

@greptile

@waleedlatif1
Copy link
Collaborator Author

@curosr review

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3 files reviewed, 3 comments

Edit Code Review Agent Settings | Greptile

@waleedlatif1
Copy link
Collaborator Author

@cursor review

@waleedlatif1
Copy link
Collaborator Author

@greptile

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

@greptile-apps
Copy link
Contributor

greptile-apps bot commented Feb 21, 2026

Additional Comments (1)

apps/sim/app/(auth)/oauth/consent/page.tsx
unused import - Image is imported but no longer used after switching to native <img> tag

import { useCallback, useEffect, useState } from 'react'

- Move scheme check outside try/catch so specific error isn't swallowed
- Return fromCache flag from resolveClientMetadata to skip redundant DB writes
@waleedlatif1
Copy link
Collaborator Author

@greptile

@waleedlatif1
Copy link
Collaborator Author

@cursor review

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

@waleedlatif1
Copy link
Collaborator Author

@cursor review

@waleedlatif1
Copy link
Collaborator Author

@greptile

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.

@waleedlatif1 waleedlatif1 merged commit 4913799 into staging Feb 21, 2026
12 checks passed
@waleedlatif1 waleedlatif1 deleted the feat/access-page branch February 21, 2026 22:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant