feat(credential-groups): add seventeen OAuth providers

Merged
TH
2mo ago
+1491-44

Summary

  • Adds 17 OAuth providers to Credential Groups: Airtable, Asana, Attio, Box, Cal.com, ClickUp, DocuSign, Dropbox, HubSpot, Linear, LinkedIn, monday.com, Notion, Pipedrive, Salesforce, WordPress.com, Zoom
  • Adds createUserInfoManagedOAuthConnector, so a provider contributes a parse rather than its own connector factory
  • Fixes tokenType being compared against exactly Bearer — RFC 6749 §7.1 makes it case-insensitive, and several providers send lowercase bearer, which was rejected as an incomplete authorization
  • Adds ManagedOAuthScopeResolution for providers that report granted scopes somewhere other than the token response. Better Auth derives tokens.scopes from the token response's scope field, so a provider that omits it yields an empty list and the scope check rejects a grant the user actually approved
  • Adds scopeless for Notion, ClickUp and Cal.com, which authorize with an empty scope list and previously tripped the "no scope policy" guard before the flow could start
  • Surfaces which providers this deployment has an OAuth client for, so the picker no longer offers an account type that fails on click
  • Adds a search field to the account-type picker, now that the list is 21 rows

Every verifyIdentity is written fresh rather than reusing the connector layer's getUserInfo: that one exists to satisfy Better Auth's email_is_missing guard, so it substitutes a synthetic address when the provider returns none and asserts emailVerified: true in places the provider never verified. Managed enrollment binds a credential to an invited person, so it reports only what the provider proves. LinkedIn now reads the real email_verified claim.

Two deliberate omissions:

  • Spotify — its user profile endpoint returns an email the provider documents as unverified, so it cannot satisfy the invitation binding
  • Zoho Desk — its data-center Desk base is persisted as a marker inside the credential's scope string, and managed credentials store granted scopes as an array. Adding it now would silently fall back to the default host for every non-US data center; that marker needs plumbing through the managed-credential path first

Type of Change

  • New feature

Testing

Tested manually. bun run type-check, bun run lint, and all 37 audits pass; 2202 tests across the credential-group, connector, contract and hook suites pass.

Per-provider OAuth walkthroughs still need a live run — the empty granted-scope case in particular only reproduces against a real provider.

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)