A comprehensive WordPress plugin that extends WPGraphQL functionality with JWT authentication, SEO integration, enhanced pagination, and debugging capabilities. Perfect for headless WordPress setups using frameworks like Nuxt.js.
-
🔐 JWT Authentication
- Configurable token expiration
- Refresh token support
- Test endpoints for token generation and validation
- CORS support for cross-origin requests
-
🎯 SEO Integration
- Full The SEO Framework integration
- Meta tags (title, description)
- Open Graph support
- Twitter Cards
- Robots meta directives
- Canonical URLs
- Schema.org markup
-
📄 Enhanced Pagination
- Offset-based pagination
- Total count support
- Improved page info
- Performance optimized queries
-
🐛 Debug Tools
- Detailed query logging
- Performance monitoring
- Request/response tracking
- SQL query logging
- WordPress 5.6 or higher
- PHP 7.4 or higher
- WPGraphQL plugin
- The SEO Framework plugin (for SEO features)
- Composer
- Add the repository to your
composer.json:
{
"repositories": [
{
"type": "vcs",
"url": "https://github.com/istogram/wp-graphql-extended"
}
]
}- Require the package:
composer require istogram/wp-graphql-extended- Download the latest release
- Upload to your WordPress plugins directory
- Run
composer installin the plugin directory - Activate the plugin through WordPress admin
Add these to your .env file:
# Required
GRAPHQL_JWT_AUTH_SECRET_KEY="your-secret-key-here"
# Optional
GRAPHQL_JWT_AUTH_CORS_ENABLE=true
GRAPHQL_JWT_AUTH_ALLOWED_ORIGINS="https://your-frontend.com,https://another-domain.com"These can be defined in your wp-config.php:
define('GRAPHQL_DEBUG', true); // Enable GraphQL debugging
define('WP_DEBUG', true); // Required for detailed loggingQuery SEO data for any post:
query GetPostWithSEO {
post(id: "1", idType: DATABASE_ID) {
title
seo {
title
description
canonicalUrl
robots
openGraph {
title
description
image {
url
}
type
modifiedTime
}
twitter {
title
description
image {
url
}
cardType
}
schema {
articleType
pageType
}
}
}
}Example response:
{
"data": {
"post": {
"title": "Sample Post",
"seo": {
"title": "SEO Title | Site Name",
"description": "Meta description for search engines",
"canonicalUrl": "https://example.com/sample-post",
"robots": "index,follow",
"openGraph": {
"title": "Open Graph Title",
"description": "Description for social sharing",
"image": {
"url": "https://example.com/og-image.jpg"
}
}
}
}
}
}- Generate a token:
mutation LoginUser {
login(input: {
username: "user",
password: "pass"
}) {
authToken
refreshToken
}
}The plugin includes REST API security configuration that:
- Requires authentication for all REST API endpoints except specific test routes
- Allows unauthenticated access to JWT authentication test endpoints
- Returns proper error responses for unauthorized requests
Example of protected endpoint access:
# This will fail with 401 if not authenticated
curl http://your-site/wp-json/wp/v1/posts
# This will work with a valid auth token
curl -H "Authorization: Bearer your-jwt-token" http://your-site/wp-json/wp/v1/posts
# Auth test endpoints are publicly accessible
curl http://your-site/wp-json/wp-graphql-extended/v1/auth-test/infoAvailable test endpoints:
GET /wp-json/wp-graphql-extended/v1/auth-test/info- Get JWT configuration infoPOST /wp-json/wp-graphql-extended/v1/auth-test/generate- Generate a test tokenPOST /wp-json/wp-graphql-extended/v1/auth-test/decode- Decode and validate a token
Configure custom endpoint access by extending the RestConfiguration class:
add_filter('wp-graphql-extended/rest/allowed_routes', function($routes) {
$routes[] = 'my-namespace/v1/public-endpoint';
return $routes;
});- Use the token in your requests:
curl -H "Authorization: Bearer your-token" http://your-site/graphqlUse offset pagination in your queries:
query GetPosts {
posts(
where: {
offsetPagination: [0, 10] # [offset, per_page]
}
) {
pageInfo {
total
hasNextPage
}
nodes {
id
title
seo {
title
description
}
}
}
}Available when WP_DEBUG is true:
- Token Info:
GET /wp-json/wp-graphql-extended/v1/auth-test/info - Generate Test Token:
POST /wp-json/wp-graphql-extended/v1/auth-test/generate - Decode Token:
POST /wp-json/wp-graphql-extended/v1/auth-test/decode
// nuxt.config.js
export default {
publicRuntimeConfig: {
graphql: {
url: 'http://your-wordpress/graphql',
}
},
modules: [
'@nuxtjs/apollo',
],
apollo: {
clientConfigs: {
default: {
httpEndpoint: 'http://your-wordpress/graphql',
httpLinkOptions: {
credentials: 'include',
headers: {
'Access-Control-Allow-Origin': '*'
}
}
}
}
}
}// plugins/apollo-auth.js
export default (context) => {
context.app.apolloProvider.defaultClient.wsClient = null
context.app.apolloProvider.defaultClient.setOnError(({ graphQLErrors, networkError }) => {
if (graphQLErrors) {
graphQLErrors.forEach(({ message, locations, path }) => {
console.log(`[GraphQL error]: Message: ${message}, Location: ${locations}, Path: ${path}`)
})
}
if (networkError) {
console.log(`[Network error]: ${networkError}`)
}
})
}<!-- components/PostHead.vue -->
<template>
<div v-if="post">
<Head>
<title>{{ post.seo.title }}</title>
<meta name="description" :content="post.seo.description" />
<link rel="canonical" :href="post.seo.canonicalUrl" />
<!-- Open Graph -->
<meta property="og:title" :content="post.seo.openGraph.title" />
<meta property="og:description" :content="post.seo.openGraph.description" />
<meta property="og:image" :content="post.seo.openGraph.image.url" />
<meta property="og:type" :content="post.seo.openGraph.type" />
<!-- Twitter -->
<meta name="twitter:card" :content="post.seo.twitter.cardType" />
<meta name="twitter:title" :content="post.seo.twitter.title" />
<meta name="twitter:description" :content="post.seo.twitter.description" />
<meta name="twitter:image" :content="post.seo.twitter.image.url" />
</Head>
</div>
</template>When WP_DEBUG is enabled, the plugin logs detailed information about:
- GraphQL queries and responses
- JWT token generation and validation
- SQL queries for pagination
- SEO data resolution
- CORS requests and headers
Logs are written to your WordPress debug log (typically wp-content/debug.log).
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
MIT License - see the LICENSE file for details.
- 📫 For bugs and feature requests, please create an issue
- 💬 For general questions, please start a discussion