{"id":16628,"library":"graphql-directive-auth","title":"GraphQL Authentication Directives","description":"graphql-directive-auth is a utility library designed to simplify common authentication and authorization tasks in GraphQL APIs by providing schema directives. It offers `@isAuthenticated` and `@hasRole` directives, which can be used to protect fields and types based on JWT tokens and user roles. The current stable version is 0.3.2, indicating it's still in a pre-1.0 development phase, which typically implies an irregular release cadence and potential for API changes. Its key differentiators include a straightforward setup with environment variables for default behavior and highly customizable authentication and role-checking functions for more complex scenarios. It ships with TypeScript types, enhancing developer experience in TypeScript projects. It integrates with `graphql-tools` and expects a `graphql` peer dependency, providing a declarative approach to security within the GraphQL schema itself.","status":"active","version":"0.3.2","language":"javascript","source_language":"en","source_url":"https://github.com:graphql-community/graphql-directive-auth","tags":["javascript","typescript"],"install":[{"cmd":"npm install graphql-directive-auth","lang":"bash","label":"npm"},{"cmd":"yarn add graphql-directive-auth","lang":"bash","label":"yarn"},{"cmd":"pnpm add graphql-directive-auth","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Peer dependency for core GraphQL functionality.","package":"graphql","optional":false},{"reason":"Peer dependency for schema directive functionality, specifically makeExecutableSchema.","package":"graphql-tools","optional":false}],"imports":[{"note":"While CommonJS `require` works, ESM `import` is preferred. The default export is a function factory.","wrong":"const AuthDirective = require('graphql-directive-auth');","symbol":"AuthDirective","correct":"import { AuthDirective } from 'graphql-directive-auth';"},{"note":"Access specific directives from the factory function's return. This allows aliasing, e.g., 'auth' instead of '@isAuthenticated'.","symbol":"AuthDirective().isAuthenticated","correct":"import { AuthDirective } from 'graphql-directive-auth';\n// ...\nauth: AuthDirective().isAuthenticated"},{"note":"Access specific directives for role checking. Can be aliased for custom names in the schema.","symbol":"AuthDirective().hasRole","correct":"import { AuthDirective } from 'graphql-directive-auth';\n// ...\nrole: AuthDirective().hasRole"}],"quickstart":{"code":"import { makeExecutableSchema } from 'graphql-tools';\nimport { AuthDirective } from 'graphql-directive-auth';\n\n// Set APP_SECRET for default JWT verification.\n// In a real application, use proper environment management (e.g., dotenv, Kubernetes secrets).\nprocess.env.APP_SECRET = process.env.APP_SECRET ?? 'your_super_secret_key_for_dev';\n\nconst typeDefs = `\n  directive @isAuthenticated on FIELD_DEFINITION | OBJECT\n  directive @hasRole(role: String!) on FIELD_DEFINITION | OBJECT\n\n  type User @isAuthenticated {\n    id: ID!\n    name: String!\n    role: String! @hasRole(role: \"admin\")\n  }\n\n  type Query {\n    me: User @isAuthenticated\n    adminPanel: String @hasRole(role: \"admin\")\n    publicGreeting: String\n  }\n`;\n\nconst resolvers = {\n  Query: {\n    me: (root, args, ctx) => {\n      // ctx.auth will contain the decoded JWT payload or custom auth object\n      if (!ctx.auth || !ctx.auth.user) throw new Error('Not authenticated');\n      return { id: ctx.auth.user.id, name: ctx.auth.user.name, role: ctx.auth.user.role };\n    },\n    adminPanel: () => 'Welcome to the admin panel!',\n    publicGreeting: () => 'Hello, world!'\n  }\n};\n\nconst schema = makeExecutableSchema({\n  typeDefs,\n  resolvers,\n  schemaDirectives: {\n    ...AuthDirective(), // Registers @isAuthenticated and @hasRole directives\n    // Optionally, you can rename them:\n    // auth: AuthDirective().isAuthenticated,\n    // role: AuthDirective().hasRole\n  }\n});\n\n// To use this schema, you would typically pass it to a GraphQL server (e.g., Apollo Server).\n// For brevity, the server setup is omitted here.\n// console.log(schema); // You can inspect the generated schema\n","lang":"typescript","description":"This quickstart demonstrates setting up `graphql-directive-auth` with default authentication, protecting types and fields using `@isAuthenticated` and `@hasRole` directives, and accessing authenticated user data within resolvers. It includes type definitions, resolvers, and directive registration."},"warnings":[{"fix":"Refer to the package's changelog or GitHub releases for specific upgrade instructions when updating across minor or major pre-1.0 versions. Thorough testing is recommended.","message":"As of version 0.3.x, the library is still pre-1.0. Future major or minor versions may introduce breaking changes to the API, particularly to the signature of custom authentication or role-checking functions, or the structure of the `AuthDirective()` factory.","severity":"breaking","affected_versions":"<1.0.0"},{"fix":"Ensure `process.env.APP_SECRET` is set to a strong, consistent secret key. For `@hasRole`, verify that the JWT token, when decoded, includes a `role` property matching the expected string. If custom logic is needed, implement `authenticateFunc` and `checkRoleFunc`.","message":"The default `@isAuthenticated` and `@hasRole` directives rely on the `APP_SECRET` environment variable for JWT verification and expect the JWT token to contain a `role` property for role-based access control. Misconfiguration or missing these elements will lead to authentication failures.","severity":"gotcha","affected_versions":">=0.1.0"},{"fix":"Standardize the return structure of your custom `authenticateFunc`. Always check for the existence of `ctx.auth` and its properties within resolvers before accessing them, especially if authentication is optional or conditional for certain fields.","message":"The authenticated user object is made available in the GraphQL `context` under `context.auth`. If you provide a custom `authenticateFunc`, ensure it returns an object with a consistent structure, as resolvers will depend on it. For example, if your custom function returns `{ user: { id: '...' } }`, your resolvers should access `ctx.auth.user.id`.","severity":"gotcha","affected_versions":">=0.1.0"}],"env_vars":null,"last_verified":"2026-04-22T00:00:00.000Z","next_check":"2026-07-21T00:00:00.000Z","problems":[{"fix":"Ensure a valid, unexpired JWT token is sent in the `Authorization` header. Verify `APP_SECRET` is correctly set and matches the key used to sign the token.","cause":"The `@isAuthenticated` directive was applied, but no valid JWT token was provided in the `Authorization: Bearer <token>` HTTP header, or the token was invalid/expired.","error":"Error: Not authenticated!"},{"fix":"Check the `role` value in the JWT token (e.g., using jwt.io). Ensure it exactly matches the `role` argument provided to the `@hasRole` directive in your schema. If using a custom `checkRoleFunc`, debug its logic.","cause":"The `@hasRole` directive was applied, but the `role` property in the authenticated user's JWT payload does not match the role specified in the directive argument.","error":"Error: Unauthorized! User does not have the required role."},{"fix":"Add null/undefined checks before accessing properties of `ctx.auth` within resolvers (e.g., `if (ctx.auth?.user?.id) { ... }`). Review your custom `authenticateFunc` to ensure it always returns an object with the expected `user` property if authentication is successful.","cause":"A resolver attempted to access `ctx.auth.user.id` or similar, but `ctx.auth` (or its `user` property) was `undefined` because authentication failed or a custom `authenticateFunc` did not return the expected structure.","error":"TypeError: Cannot read properties of undefined (reading 'id')"}],"ecosystem":"npm"}