Bezpečnostné aspekty a ochrana GraphQL API

Prečo sú GraphQL API bezpečnostne špecifické

GraphQL predstavuje flexibilný dotazovací jazyk, ktorý umožňuje klientom presne určiť tvar a rozsah požadovaných dát. Tento princíp výrazne mení tradičný bezpečnostný model známy z REST API. Kľúčové rozdiely spočívajú v:

  • Granularite – autorizácia sa vykonáva až na úrovni jednotlivých polí, nie len endpointov.
  • Kompozícii – podpora fragmentov, aliasov a unijných typov zvyšuje komplexnosť spracovania dotazov.
  • Resource amplifikácii – dotazy môžu mať premenlivú hĺbku a šírku, čo ovplyvňuje záťaž servera.
  • Transportu – využívanie dlhotrvajúcich spojení pri subscriptions, ktoré majú špecifické nároky na bezpečnosť.

Cieľom tohto článku je predstaviť overené postupy na návrh, implementáciu a prevádzku GraphQL API s robustnými kontrolami, ktoré chránia pred zneužitím a únikom citlivých dát.

Model hrozieb a bezpečnostné ciele pri GraphQL

  • Dôvernosť údajov: Zabrániť neautorizovanému úniku dát prostredníctvom dynamických štruktúr dotazov a introspekcie schémy.
  • Integrita dát: Zabezpečiť, že mutácie rešpektujú obchodné pravidlá, sú transakčne konzistentné a vykonávajú sa s primeranými oprávneniami.
  • Dostupnosť služby: Prevencia DoS útokov spôsobených náročnými dotazmi, problémom n+1, masívnym aliasovaním či nadmerným množstvom subscription eventov.
  • Odpovednosť a auditovateľnosť: Transparentné sledovanie aktivít, korelácia dotazov s identitou používateľa a identifikácia operácie pomocou operationName.

Autentizácia a zabezpečenie transportných vrstiev

  • Vynucovanie TLS: Dôsledne používať HTTPS pre všetky komunikácie vrátane WebSocket spojení (wss://). Chrániť pred downgrade útokmi a eliminovať slabé kryptografické algoritmy.
  • OAuth 2.0 a OIDC: Identity prenášať bezpečne ako Bearer tokeny (formáty JWT alebo PASETO) v hlavičke Authorization. Vyhnúť sa prenosu session tokenov v URL parametroch.
  • Krátkodobé tokeny a rotácia: Access tokeny by mali mať obmedzenú životnosť, refresh tokeny sa riadia politikami revokácie a blacklistingu podľa unikátnych identifikátorov (jti).
  • Mutuálne TLS a NULA: Pri B2B integráciách zvážiť použitie vzájomnej autentizácie na TLS vrstve a viazanie tokenov na konkrétny komunikačný kanál (napr. DPoP alebo mtls-bound tokeny).

Autorizácia: implementácia od schémy po resolver

Autorizáciu je potrebné navrhovať deklaratívne a konzistentne, ideálne už v definícii schémy.

  • Model oprávnení: Používať RBAC (role-based), ABAC (atribútové) alebo hybridné prístupy kombinujúce role a kontextové podmienky nad dátami.
  • Vynucovanie na úrovni polí: Autorizácia sa musí aplikovať priamo v resolverochoch jednotlivých polí, nielen na koreňových typoch Query alebo Mutation.
  • Direktívami riadené pravidlá: Využívať vlastné direktívy ako @auth(role: "admin") alebo knižnice typu GraphQL Shield a Envelop pre deklaratívne zabezpečenie schémy.
  • Bezpečnosť na úrovni riadkov a stĺpcov: Obmedziť prístup k záznamom napríklad s pomocou RLS (Row-Level Security) v databáze, a tiež zabezpečiť citlivé stĺpce, pretože autorizácia v aplikácii nestačí.
  • Nedištinktívne chybové správy: Nevypovedať o existencii či neexistencii objektov pomocou unikátnych chýb, čím sa minimalizuje informačný únik.

Introspekcia a schéma: riadenie zverejňovania informácií

  • Riadená introspekcia: V produkčnom prostredí odporúčame zakázať introspekciu pre anonymných používateľov alebo ju sprístupniť len privilegovaným rolám alebo neveřejným endpointom (napríklad build-time dump SDL namiesto runtime introspekcie).
  • Persistované dotazy (operation whitelisting): Používajte automatickú validáciu založenú na odosielaní hashov dotazov (APQ/whitelist), server odmietne neznáme operácie, čo znižuje riziko neželaných dopytov.
  • Verzovanie schémy: Zavádzajte stabilné API kontrakty s označením polí ako deprecated a telemetry na monitorovanie využívania a bezpečného odstraňovania.

Obmedzenie zložitosti dotazov ako prevencia DoS útokov

  • Limit hĺbky (depth limit): Nastavte maximálnu hĺbku AST stromu, typicky 8 až 12 úrovní, s možnosťou výnimiek pre bezpečné typy.
  • Scoring zložitosti (complexity scoring): Priraďujte poliam váhy na základe výpočtovej náročnosti (napr. O(1), O(n), O(n log n)) a nastavte limity zdrojov podľa rozpočtu na dotaz.
  • Limity aliasov a batchingu: Zamedzte nadmernej duplicite polí pomocou limitov počtu aliasov a detekcie vzorov vedúcich k amplifikácii záťaže.
  • Časové limity a maximálny počet tokenov: Ukladajte timeouty na úrovni resolverov, limitujte veľkosť payloadu a AST, a na gateway implementujte circuit-breakery pre ochranu proti preťaženiu.
  • Rate limiting a throttling: Zavádzajte limity na úrovni IP, klienta alebo používateľa, využívajte algoritmy token bucket alebo leaky bucket implementované na reverzných proxy.

Validácia vstupov a typová bezpečnosť

  • Custom scalars: Zavádzajte vlastné skalárne typy ako Email, URL, UUID, SafeInt, NonEmptyString s dôkladnou validačnou logikou na úrovni runtime aj schema-first prístupu.
  • Whitelisting hodnôt: Používajte enumy namiesto voľných textových hodnôt, zabezpečte normalizáciu Unicode, vylúčte neviditeľné znaky a nulové byty (NUL).
  • Bezpečné spracovanie vstupov: Nikdy neskladá SQL alebo NoSQL dotazy priamo z vstupných reťazcov od používateľov; vždy implementujte parametrizované dotazy alebo používajte query buildery.
  • Obmedzenie veľkosti vstupov: Kontrolujte maximálnu veľkosť premenných, počet prvkov v poliach a hĺbku zanorenia vstupných Input typov.

Správa chýb, logovanie a prevencia únikov informácií

  • Maskovanie chýb: V správe errors[].message poskytujte neutrálne texty; interné chyby a stacktrace ukladajte iba do serverových logov.
  • Kódy chýb v extensions: Vráťte strojovo čitateľné kódy ako FORBIDDEN, BAD_USER_INPUT v rámci rozšírení pre jednotnú interpretáciu klientom.
  • Hygiena osobných údajov (PII): Nelogujte kompletne dotazy s citlivými dátami; hodnoty ako heslá, tokeny či čísla kariet maskujte v logoch.
  • Traceability: Vyžadujte povinné operationName, poskytujte korelačné ID a zbierajte metriky ako dĺžku dotazu, hĺbku, skóre zložitosti a počet volaní resolverov.

Riešenie N+1 problému, cache a redukcia resource amplifikácie

  • Dataloader pattern: Implementujte batchovanie prístupov k dátovým zdrojom v rámci jedného request kontextu, čím zabránite exponenciálnemu nárastu počtu dotazov.
  • Cache vrstvy: Používajte per-request cache na úrovni resolverov, aplikačnú cache s TTL a bezpečnú CDN cache výhradne pre verejné dáta. Privátne odpovede nekacheujte bez znalosti identity používateľa.
  • Obmedzenia zobrazenia: Nasadzujte limity na veľkosť stránok, používajte kurzory (Relay cursor pagination) a nastavte tvrdé serverové maxima aj pri požiadavke klienta.

CORS, CSRF a bezpečnosť prehliadača

  • CORS allowlist: Používajte explicitný zoznam povolených domén (allowed origins); nikdy neumožňujte * v kombinácii s credentials.
  • Prevence CSRF: Pri cookie-based session autentizácii používajte anti-CSRF tokeny pre mutácie; u bearer tokenov v hlavičke je riziko nižšie, ale validujte hlavičky Origin a Referer.
  • Bezpečnostné hlavičky: Konfigurujte Content-Security-Policy, Referrer-Policy, X-Content-Type-Options a Strict-Transport-Security najmä pri rozhraní pre vývojárov (GraphiQL, Apollo Sandbox).

Spracovanie uploadov, súborov a binárnych dát

  • Multipart handling: Obmedzte počet súborov, ich maximálnu veľkosť a podporované MIME typy; kontrolujte nahrávaný obsah na malware a ukladanie realizujte mimo aplikačného servera.
  • Dočasné URL: Pre veľké súbory generujte krátkodobé podpísané URL (pre-signed URLs) a vyhýbajte sa streamovaniu veľkých objemov dát priamo cez GraphQL resolvery.

Bezpečnosť subscriptions a WebSocket spojení

  • Handshake autentizácia: Overujte autentizačné tokeny pri inicializácii spojenia (connection_init), pravidelne obnovujte autentifikáciu pri dlhodobých pripojeniach.
  • Ochrana pred neoprávneným prístupom: Implementujte autorizáciu na úrovni jednotlivých subscription kanálov, aby sa zabránilo odoberaniu citlivých dát neoprávnenými klientmi.
  • Limitácia počtu pripojení: Obmedzte maximálny počet súbežných WebSocket spojení na jedného používateľa alebo IP adresu, aby ste predišli DoS útokom.
  • Bezpečné spracovanie správ: Validujte všetky prijaté správy pred ich spracovaním a monitorujte anomálie v správaní klientov.

Bezpečnostné opatrenia pri práci s GraphQL API sú nevyhnutné pre ochranu dát a zamedzenie útokov. Kombináciou dobre navrhnutého limitovania, validácie vstupov, správnej konfigurácie bezpečnostných hlavičiek a monitoringu môžete výrazne znížiť riziká a zabezpečiť spoľahlivú prevádzku vašej služby. Priebežná aktualizácia znalostí o nových hrozbách a využívanie osvedčených bezpečnostných praktík sú kľúčom k udržaniu vysokej úrovne ochrany v dynamickom prostredí moderných API.