Jak jsem vytvořil Supabase driver pro Keboola Connection

supabase php oauth webdev

Poslední týdny jsem dělal na integraci Supabase do Keboola Connection. Vznikl z toho kompletní driver s OAuth 2.0, automatickým discovery schémat a napojením na Supabase Marketplace. A cestou jsem narazil na pár bugů, ze kterých jsem málem šedivěl.

Supabase + Keboola

Supabase je open-source alternativa k Firebase postavená nad PostgreSQL -- autentizace, real-time, storage a hlavně plnohodnotná PostgreSQL databáze. Keboola je platforma pro datové pipeline a ETL procesy nad různými datovými zdroji.

Cíl byl jednoduchý: uživatel připojí svůj Supabase projekt jako externí datový zdroj v Keboola a data se automaticky začnou stahovat do pipeline.

Z CLI na webový controller

Původně jsem chtěl CLI příkaz na registraci OAuth credentials. Jenže testovat OAuth flow z terminálu je utrpení -- kopírujete URL tam a zpátky, ručně řešíte přesměrování, žádná vizuální zpětná vazba.

Takže jsem brzo otočil: místo CLI jsem postavil webový test harness na /supabase/connect. Jednoduchý formulář, zadáte client_id a client_secret, vygeneruje redirect URL, pošle vás na Supabase a obslouží callback. Tohle rozhodnutí se ukázalo jako klíčové -- iterativní debugging, který následoval, by z terminálu prostě nešel.

Stateless OAuth hlavolam

První pořádná výzva přišla ze Symfony. Routy s #[AsPublicAction] běží na stateless firewallu -- žádná session. Jenže OAuth flow typicky potřebuje uložit PKCE verifier mezi autorizací a callbackem. Symfony vyhodilo: "Session was used while the request was declared stateless."

No a co s tím? Zakódovat všechno -- client credentials, PKCE verifier, redirect URI -- přímo do OAuth state parametru, podepsaného HMAC-SHA256 přes kernel.secret. Callback stav dekóduje, ověří podpis a vytáhne PKCE verifier. Žádná session, žádná databáze, HMAC brání manipulaci a state parametr z principu chrání proti CSRF. Elegantní.

Záludnosti OAuth API

Pak přišly dvě menší překážky:

Záhada approval_prompt. League OAuth2 knihovna přidává approval_prompt do autorizačních požadavků automaticky (konvence Google OAuth). Supabase to odmítlo: "Unrecognized key(s) in object: 'approval_prompt'." Stačilo přepsat getAuthorizationParameters() a parametr odfiltrovat.

Projektové vs. účtové OAuth aplikace. Vytvořil jsem OAuth aplikaci na úrovni projektu (/project/{ref}/auth/oauth-apps) a dostával "Unrecognized client_id." Supabase má totiž dva odlišné scopy -- projektové aplikace a integrační aplikace na úrovni účtu (/account/integrations). Pro marketplace integraci přes projekty potřebujete to druhé. Tohle v dokumentaci snadno přehlédnete.

PKCE Double-Handling Bug

Tohle byl nejtěžší bug celého projektu. Po vyřešení stateless flow a API záludností pořád selhávala výměna kódu za tokeny: "Invalid or expired OAuth authorization."

Zkoušel jsem systematicky:

  1. Detailní error logging -- stejná chyba
  2. HTTP Basic Auth pro token endpoint -- pořád nic
  3. Accept: application/json header -- pořád nic
  4. Kompletně vlastní exchangeCodeForTokens() obcházející knihovnu -- pořád nic

Autorizace fungovala. Callback dostal kód. Ale výměna za tokeny konzistentně vracela tu samou kryptickou chybu. Šílel jsem z toho.

Průlom: League OAuth2 knihovna má vestavěnou PKCE podporu. Můj kód PKCE taky řešil manuálně kvůli stateless flow. Dvě korektní PKCE implementace běžely současně -- knihovna poslala jeden code_verifier, můj kód jiný. Supabase vidělo nesoulad a výměnu odmítlo.

Fix? Jeden řádek:

protected $pkceMethod = null; // Vypnout vestavěné PKCE knihovny

Klasický integrační bug -- dva systémy, každý sám o sobě správný, v kombinaci nefungují. Debugging zabral hodiny, protože každý dílek zvlášť vypadal v pohodě.

Dva režimy připojení

Driver podporuje dva způsoby přístupu k datům:

Přímé PostgreSQL připojení -- klasika přes connection pooler (port 6543). Plný přístup k SQL, vhodné pro větší objemy dat.

REST API (PostgREST) -- přes Supabase REST endpoint s service_role klíčem. Jednodušší setup bez sdílení databázového hesla.

Obě varianty podporují šifrované ukládání credentials s oddělenými klíči pro hesla, API klíče a OAuth tokeny.

Automatické schema discovery

Po úspěšném OAuth propojení se na pozadí spustí SupabaseProjectSetupJob:

  1. Přes protobuf zavolá ListSchemasCommand na Supabase driver
  2. Objeví dostupná schémata
  3. Pro každé vytvoří externí bucket v Keboola
  4. Nastaví auto-refresh každých 6 hodin

Protobuf komunikace je architektonicky fajn -- příkazy se definují ve sdíleném storage-driver-common monorepu a implementují v storage-driver-postgres driveru. Čisté hranice, žádné přímé provázání.

Uživatel po připojení okamžitě vidí svá data bez jakékoli ruční konfigurace.

Supabase Management API

Součástí je klient pro Supabase Management API:

  • Detaily projektu (region, konfigurace)
  • API klíče (anon, service_role)
  • Konfigurace connection pooleru
  • Seznam projektů a organizací

Tahle data se využívají při automatickém nastavení credentials po OAuth flow.

Celý user flow

Jak to vypadá end-to-end:

  1. Uživatel klikne "Připojit Supabase" a autorizuje přes OAuth
  2. Callback uloží tokeny, přesměruje na setup stránku
  3. Uživatel vybere svůj Supabase projekt, volitelně zadá PostgreSQL DSN
  4. Keboola vytvoří organizaci a projekt se Supabase backendem
  5. Background job objeví tabulky, zaregistruje buckety, nastaví auto-refresh
  6. Uživatel přistane na dashboardu s daty, která už tečou

Rozsah

Celý driver vznikl za týden v asi 60 hodinách intenzivní práce s Claude Code. Výsledek je kolem 25 000 změn -- třídy, controllery, migrace, testy, CLI příkazy, dokumentace. Od nuly ke kompletní integraci.

Vývoj probíhal vysoce iterativně: definovat co je potřeba, implementovat, hned otestovat v prohlížeči, debugovat z reálných chybovek. Rychlé feedback smyčky umožnily vyřešit i PKCE double-handling v řádu hodin místo dnů.

AI agent výrazně zrychlil opakující se vzory (controllery, DTO, testy), generování boilerplate a navigaci v rozsáhlém Keboola codebase. Klíčová architektonická rozhodnutí a bezpečnostní model ale samozřejmě vyžadovaly lidský úsudek.

Co jsem se naučil

  • Stateless OAuth jde udělat -- zakódovat vše do HMAC-podepsaného state parametru, žádná session
  • Knihovny si hlídej -- PKCE double-handling mě naučil vždy zkontrolovat, co knihovna dělá automaticky za mě
  • OAuth API se liší provider od providera -- approval_prompt, auth metody, scopy aplikací, nic není standard
  • PKCE je nutnost pro flow, kde nelze plně zabezpečit client secret
  • Webový test harness poráží CLI testování OAuth flow o řád
  • AI agenti mění rychlost vývoje -- 25 000 změn za týden by bez nich nešlo

Integrace je momentálně v pull requestu a prochází code review. Těším se, až to poběží v produkci.

Předchozí příspěvek Následující příspěvek

Related Posts