π Secure your Statamic GraphQL endpoint
A lightweight, production-ready addon that protects Statamicβs /graphql endpoint using a token-based middleware with optional IP allow-listing.
Perfect for headless setups (Next.js, Nuxt, mobile apps) where public GraphQL access must be locked down without changing existing queries.
π Statamic Marketplace:
https://statamic.com/addons/emran-alhaddad/statamic-graphql-protect
π¦ Package Information
π Features
- π Token-protected
/graphqlendpoint - π‘οΈ Optional IP allow-list
- π§© Works with Statamicβs GraphQL layer (Rebing GraphQL under the hood)
- βοΈ Fully configurable via
.env - ποΈ Middleware-based (no route overrides)
- π§Ό No Statamic core hacks or forks
π¦ Installation
Install via Composer:
composer require emran-alhaddad/statamic-graphql-protect
Publish the config file:
php artisan vendor:publish --tag=statamic-graphql-protect
βοΈ Configuration
Published config file:
config/statamic-graphql-protect.php
Example .env configuration:
STATAMIC_GRAPHQL_PROTECT_ENABLED=trueSTATAMIC_GRAPHQL_TOKEN=long-secreat-tokenSTATAMIC_GRAPHQL_TOKEN_HEADER=X-Statamic-GraphQL-TokenSTATAMIC_GRAPHQL_ALLOWED_IPS=127.0.0.1,1.2.3.4
Your frontend must send the header:
X-Statamic-GraphQL-Token: <your-token>
β οΈ REQUIRED: Register Middleware in Statamic GraphQL Config
This addon does not automatically inject itself into every Statamic install.
You must manually register the middleware.
Open:
config/statamic/graphql.php
Add the middleware to the middleware array:
return [ // ... 'middleware' => [ \Emran\StatamicGraphqlProtect\Http\Middleware\ProtectGraphql::class, // other GraphQL middleware (if any) ], // ...];
β Without this step,
/graphqlwill remain public.
π§ͺ Example Usage
β Request without token (blocked)
curl https://your-domain.com/graphql \ -H "Content-Type: application/json" \ -d '{"query":"{ ping }"}'
Response:
{ "message": "Invalid or missing GraphQL token." }
β Request with token (allowed)
curl https://your-domain.com/graphql \ -H "Content-Type: application/json" \ -H "X-Statamic-GraphQL-Token: your-token" \ -d '{"query":"{ ping }"}'
Response:
{ "data": { "ping": "pong" } }
π§ Postman Setup
- Headers
| Key | Value |
|---|---|
| X-Statamic-GraphQL-Token | your-token |
| Content-Type | application/json |
- Body β Raw β JSON
{ "query": "{ ping }" }
- Send β
β οΈ IMPORTANT: Disable Statamic GraphQL Cache
Statamicβs GraphQL cache does NOT respect request headers.
If enabled:
- First unauthenticated request β 401 cached β everyone gets 401
- First authenticated request β 200 cached β endpoint effectively public
β Disable it:
Edit:
config/statamic/graphql.php
'cache' => false,
or:
'cache' => [ 'expiry' => 0,],
Then clear caches:
php artisan config:clearphp artisan cache:clearphp artisan statamic:stache:clear
β Recommended: cache at Next.js / CDN / Edge level, not inside Statamic.
π Compatibility
- β Statamic v4 / v5
- β PHP 8.1+
- β Headless & traditional installs
- β Next.js / Nuxt / Mobile apps
π Directory Structure
statamic-graphql-protect/ββ src/β ββ Http/Middleware/ProtectGraphql.phpβ ββ ServiceProvider.phpββ config/statamic-graphql-protect.phpββ composer.jsonββ README.mdββ LICENSE
π©Ί Troubleshooting
βInvalid or missing GraphQL tokenβ
- Header name mismatch
- Token contains whitespace
- Middleware not registered in
config/statamic/graphql.php
Works in cURL but not Postman
- Use Body β Raw β JSON
- Ensure headers are manually added
Random 200 / 401 responses
- GraphQL cache still enabled
- Disable it and clear caches
π€ Author
Emran Alhaddad GitHub: https://github.com/emran-alhaddad Statamic Addons: https://statamic.com/addons/emran-alhaddad
π License
MIT License
See the LICENSE file for full details.