Back to Skills

graphql-security

verified

Secure GraphQL APIs - authentication, authorization, rate limiting, and validation

View on GitHub

Marketplace

pluginagentmarketplace-graphql

pluginagentmarketplace/custom-plugin-graphql

Plugin

developer-roadmap

Repository

pluginagentmarketplace/custom-plugin-graphql
1stars

skills/graphql-security/SKILL.md

Last Verified

January 20, 2026

Install Skill

Select agents to install to:

Scope:
npx add-skill https://github.com/pluginagentmarketplace/custom-plugin-graphql/blob/main/skills/graphql-security/SKILL.md -a claude-code --skill graphql-security

Installation paths:

Claude
.claude/skills/graphql-security/
Powered by add-skill CLI

Instructions

# GraphQL Security Skill

> Protect your GraphQL APIs from attacks

## Overview

Learn essential security patterns for GraphQL: JWT authentication, role-based authorization, rate limiting, query complexity limits, and input validation.

---

## Security Checklist

| Check | Priority | Implementation |
|-------|----------|----------------|
| Authentication | Critical | JWT with refresh tokens |
| Authorization | Critical | Field-level with graphql-shield |
| Rate Limiting | Critical | Per-user/IP with Redis |
| Query Depth | High | graphql-depth-limit |
| Query Complexity | High | graphql-query-complexity |
| Introspection | High | Disable in production |
| Input Validation | High | Validate all inputs |
| Error Masking | Medium | Hide internal errors |

---

## Core Patterns

### 1. JWT Authentication

```typescript
import jwt from 'jsonwebtoken';

// Token creation
function createTokens(user) {
  const accessToken = jwt.sign(
    { userId: user.id, roles: user.roles },
    process.env.JWT_SECRET,
    { expiresIn: '15m' }
  );

  const refreshToken = jwt.sign(
    { userId: user.id },
    process.env.JWT_REFRESH_SECRET,
    { expiresIn: '7d' }
  );

  return { accessToken, refreshToken };
}

// Context setup
const context = async ({ req }) => {
  const token = req.headers.authorization?.replace('Bearer ', '');

  let user = null;
  if (token) {
    try {
      const payload = jwt.verify(token, process.env.JWT_SECRET);
      user = await db.users.findById(payload.userId);
    } catch (e) {
      // Token invalid or expired
    }
  }

  return { user };
};

// Login resolver
const resolvers = {
  Mutation: {
    login: async (_, { email, password }) => {
      const user = await db.users.findByEmail(email);

      if (!user || !await bcrypt.compare(password, user.passwordHash)) {
        throw new GraphQLError('Invalid credentials', {
          extensions: { code: 'UNAUTHORIZED' }
        });
      }

      return { ...createTokens(user), user };
    },
  },
};
```

#

Validation Details

Front Matter
Required Fields
Valid Name Format
Valid Description
Has Sections
Allowed Tools
Instruction Length:
6217 chars