Bird
Raised Fist0
GraphQLquery~10 mins

GraphQL security best practices - Interactive Code Practice

Choose your learning style10 modes available

Start learning this pattern below

Jump into concepts and practice - no test required

or
Recommended
Test this pattern10 questions across easy, medium, and hard to know if this pattern is strong
Practice - 5 Tasks
Answer the questions below
1fill in blank
easy

Complete the code to limit the maximum query depth in a GraphQL server.

GraphQL
const depthLimit = require('graphql-depth-limit');
const server = new ApolloServer({
  schema,
  validationRules: [[1](5)]
});
Drag options to blanks, or click blank then click option'
AdepthLimit
BmaxDepth
ClimitDepth
DdepthCheck
Attempts:
3 left
💡 Hint
Common Mistakes
Using a non-existent function name like maxDepth.
Forgetting to wrap the function call with parentheses.
2fill in blank
medium

Complete the code to enable query complexity analysis in a GraphQL server.

GraphQL
const queryComplexity = require('graphql-query-complexity');
const server = new ApolloServer({
  schema,
  validationRules: [queryComplexity({
    maximumComplexity: [1],
    onComplete: (complexity) => console.log('Query Complexity:', complexity)
  })]
});
Drag options to blanks, or click blank then click option'
A10
B10000
C1000
D100
Attempts:
3 left
💡 Hint
Common Mistakes
Setting the complexity too high, which defeats the purpose.
Setting the complexity too low, which may block valid queries.
3fill in blank
hard

Fix the error in the code to properly disable introspection in a GraphQL server.

GraphQL
const { ApolloServerPluginLandingPageDisabled } = require('apollo-server-core');
const server = new ApolloServer({
  schema,
  plugins: [[1]()]
});
Drag options to blanks, or click blank then click option'
AApolloServerPluginIntrospectionDisabled
BApolloServerPluginLandingPageDisabled
CDisableIntrospectionPlugin
DIntrospectionOffPlugin
Attempts:
3 left
💡 Hint
Common Mistakes
Using a non-existent plugin name.
Forgetting to call the plugin as a function.
4fill in blank
hard

Fill both blanks to implement rate limiting middleware for a GraphQL server.

GraphQL
const rateLimit = require('express-rate-limit');
const limiter = rateLimit({
  windowMs: [1],
  max: [2]
});
app.use('/graphql', limiter);
Drag options to blanks, or click blank then click option'
A15 * 60 * 1000
B100
C1000
D60 * 1000
Attempts:
3 left
💡 Hint
Common Mistakes
Setting windowMs to seconds instead of milliseconds.
Setting max too high or too low.
5fill in blank
hard

Fill all three blanks to add authentication and authorization checks in a GraphQL resolver.

GraphQL
const resolvers = {
  Query: {
    user: (parent, args, context) => {
      if (!context.[1]) {
        throw new Error('Not authenticated');
      }
      if (!context.user.[2].includes('admin')) {
        throw new Error('Not authorized');
      }
      return getUserById(args.id);
    }
  }
};
Drag options to blanks, or click blank then click option'
AisAuthenticated
Broles
Cpermissions
Dauth
Attempts:
3 left
💡 Hint
Common Mistakes
Checking authorization before authentication.
Using incorrect property names in context.

Practice

(1/5)
1. What is the main purpose of authentication in GraphQL security?
easy
A. To encrypt the data sent between client and server
B. To limit the number of queries a user can make
C. To verify the identity of the user making the request
D. To format the GraphQL schema correctly

Solution

  1. Step 1: Understand authentication role

    Authentication checks who the user is before allowing access.
  2. Step 2: Differentiate from other security measures

    Limiting queries and encryption are different security aspects, not authentication.
  3. Final Answer:

    To verify the identity of the user making the request -> Option C
  4. Quick Check:

    Authentication = Verify user identity [OK]
Hint: Authentication means checking who you are [OK]
Common Mistakes:
  • Confusing authentication with authorization
  • Thinking authentication limits query size
  • Mixing authentication with encryption
2. Which of the following is the correct way to limit query complexity in a GraphQL server?
easy
A. Allow unlimited queries and rely on client honesty
B. Use SQL injection to filter queries
C. Disable authentication to speed up queries
D. Use a middleware that calculates query depth and rejects too deep queries

Solution

  1. Step 1: Identify query complexity control

    Middleware can analyze query depth and reject overly complex queries to protect the server.
  2. Step 2: Eliminate incorrect options

    Allowing unlimited queries or disabling authentication weakens security; SQL injection is an attack, not a defense.
  3. Final Answer:

    Use a middleware that calculates query depth and rejects too deep queries -> Option D
  4. Quick Check:

    Limit query complexity = Middleware checks depth [OK]
Hint: Middleware can block too complex queries [OK]
Common Mistakes:
  • Ignoring query complexity limits
  • Confusing SQL injection with security measure
  • Disabling authentication to improve speed
3. Given this GraphQL resolver snippet, what will happen if a user without proper role tries to access the data?
const resolver = (parent, args, context) => {
  if (!context.user.roles.includes('admin')) {
    throw new Error('Access denied');
  }
  return getData();
};
medium
A. An error 'Access denied' will be thrown for non-admin users
B. The data will be returned regardless of user role
C. The server will crash due to missing roles
D. The resolver will ignore the role check and return null

Solution

  1. Step 1: Analyze role check in resolver

    The code checks if the user roles include 'admin'. If not, it throws an error.
  2. Step 2: Understand error handling

    Throwing an error stops execution and returns 'Access denied' to the client.
  3. Final Answer:

    An error 'Access denied' will be thrown for non-admin users -> Option A
  4. Quick Check:

    Role check fails = Error thrown [OK]
Hint: Throw error if user lacks role [OK]
Common Mistakes:
  • Assuming data returns without role check
  • Thinking server crashes on missing role
  • Believing null is returned instead of error
4. Identify the security issue in this GraphQL server setup:
const server = new ApolloServer({
  typeDefs,
  resolvers,
  context: ({ req }) => ({ user: req.user })
});

// No rate limiting or query complexity checks applied
medium
A. Missing authentication in context setup
B. No rate limiting or query complexity protection
C. Resolvers are not defined
D. Using ApolloServer is insecure

Solution

  1. Step 1: Review context and security features

    Context passes user info, so authentication may exist, but no rate limiting or complexity checks are shown.
  2. Step 2: Identify missing protections

    Without rate limiting and query complexity checks, server is vulnerable to overload and abuse.
  3. Final Answer:

    No rate limiting or query complexity protection -> Option B
  4. Quick Check:

    Missing limits = Vulnerable server [OK]
Hint: Always add rate limits and complexity checks [OK]
Common Mistakes:
  • Assuming ApolloServer is insecure by default
  • Confusing missing resolvers with security issue
  • Ignoring rate limiting importance
5. You want to protect your GraphQL API from abuse by limiting both query complexity and request rate. Which combination of methods is best practice?
hard
A. Implement query depth analysis middleware and use a rate limiter like Redis to track requests
B. Only use authentication tokens without any query or rate limits
C. Disable introspection to prevent all queries
D. Allow unlimited queries but log all requests for later review

Solution

  1. Step 1: Understand query complexity protection

    Middleware that analyzes query depth helps prevent expensive queries that overload the server.
  2. Step 2: Understand rate limiting

    Using a rate limiter like Redis tracks and limits how many requests a user can make in a time window.
  3. Step 3: Evaluate other options

    Authentication alone doesn't limit abuse; disabling introspection breaks development; logging alone doesn't prevent abuse.
  4. Final Answer:

    Implement query depth analysis middleware and use a rate limiter like Redis to track requests -> Option A
  5. Quick Check:

    Combine depth check + rate limiter = Best protection [OK]
Hint: Use middleware plus rate limiter for best security [OK]
Common Mistakes:
  • Relying only on authentication
  • Disabling introspection breaks tools
  • Logging without limiting requests