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,NonEmptyStrings 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[].messageposkytujte 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_INPUTv 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
OriginaReferer. - Bezpečnostné hlavičky: Konfigurujte
Content-Security-Policy,Referrer-Policy,X-Content-Type-OptionsaStrict-Transport-Securitynajmä 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.