0
0
GraphqlHow-ToBeginner · 4 min read

How to Use Directive for Authentication in GraphQL

Use a custom @auth directive in your GraphQL schema to mark fields or types that require authentication. Implement the directive logic in your server to check user credentials before resolving those fields, returning errors if unauthorized.
📐

Syntax

The @auth directive is defined in the GraphQL schema and applied to fields or types that need authentication. It usually looks like this:

  • directive @auth on FIELD_DEFINITION | OBJECT declares the directive.
  • Apply @auth to fields or types to protect them.
  • The server code implements the logic to check authentication when the directive is encountered.
graphql
directive @auth on FIELD_DEFINITION | OBJECT

type Query {
  secretData: String @auth
  publicData: String
}
💻

Example

This example shows a simple GraphQL server using Apollo Server with a custom @auth directive that checks if a user is authenticated before allowing access to secretData.

javascript
const { ApolloServer, gql, SchemaDirectiveVisitor } = require('apollo-server');
const { defaultFieldResolver } = require('graphql');

// Define the @auth directive
class AuthDirective extends SchemaDirectiveVisitor {
  visitFieldDefinition(field) {
    const { resolve = defaultFieldResolver } = field;
    field.resolve = async function (...args) {
      const context = args[2];
      if (!context.user) {
        throw new Error('Not authenticated');
      }
      return resolve.apply(this, args);
    };
  }
}

// Schema with @auth directive
const typeDefs = gql`
  directive @auth on FIELD_DEFINITION

  type Query {
    secretData: String @auth
    publicData: String
  }
`;

// Resolvers
const resolvers = {
  Query: {
    secretData: () => 'Sensitive info',
    publicData: () => 'Everyone can see this'
  }
};

// Server setup
const server = new ApolloServer({
  typeDefs,
  resolvers,
  schemaDirectives: {
    auth: AuthDirective
  },
  context: ({ req }) => {
    // Simple auth: user present if header 'authorization' exists
    const token = req.headers.authorization || '';
    const user = token ? { id: 'user1' } : null;
    return { user };
  }
});

server.listen().then(({ url }) => {
  console.log(`Server ready at ${url}`);
});
Output
Server ready at http://localhost:4000/
⚠️

Common Pitfalls

Common mistakes when using authentication directives include:

  • Not implementing the directive logic on the server, so the directive does nothing.
  • Applying the directive only in the schema but forgetting to check authentication in resolvers.
  • Not passing user info in the context, so authentication always fails.
  • Using directives on types but not handling nested fields properly.
graphql
/* Wrong: Directive declared but no logic implemented */
directive @auth on FIELD_DEFINITION

type Query {
  secretData: String @auth
}

// No server-side directive logic, so @auth does nothing

/* Right: Implement directive logic in server */
// See example section for correct implementation
📊

Quick Reference

StepDescription
Define @auth directiveDeclare it in your schema with 'directive @auth on FIELD_DEFINITION | OBJECT'
Apply @authAdd @auth to fields or types that require authentication
Implement directive logicIn your server, check user authentication in the directive resolver
Pass user infoInclude user data in context for authentication checks
Handle errorsThrow errors if user is not authenticated

Key Takeaways

Use a custom @auth directive in your schema to mark protected fields or types.
Implement the directive logic on the server to check user authentication before resolving fields.
Always pass user information in the context to enable authentication checks.
Apply @auth consistently to all sensitive fields to prevent unauthorized access.
Test your directive by querying with and without authentication headers.