{"id":22421296,"url":"https://github.com/treedomtrees/graphql-auth-opa","last_synced_at":"2026-01-04T16:47:20.466Z","repository":{"id":255487816,"uuid":"852653113","full_name":"treedomtrees/graphql-auth-opa","owner":"treedomtrees","description":"GraphQL OPA authentication directive","archived":false,"fork":false,"pushed_at":"2024-09-12T08:21:30.000Z","size":55,"stargazers_count":0,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2024-11-29T16:43:33.937Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/treedomtrees.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-09-05T07:22:33.000Z","updated_at":"2024-09-12T08:18:16.000Z","dependencies_parsed_at":"2024-09-05T18:59:39.323Z","dependency_job_id":"80b5c9ef-2648-40ab-8300-6075b7acbb08","html_url":"https://github.com/treedomtrees/graphql-auth-opa","commit_stats":null,"previous_names":["treedomtrees/graphql-auth-opa"],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/treedomtrees%2Fgraphql-auth-opa","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/treedomtrees%2Fgraphql-auth-opa/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/treedomtrees%2Fgraphql-auth-opa/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/treedomtrees%2Fgraphql-auth-opa/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/treedomtrees","download_url":"https://codeload.github.com/treedomtrees/graphql-auth-opa/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":228339340,"owners_count":17904513,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-12-05T17:06:38.767Z","updated_at":"2026-01-04T16:47:20.425Z","avatar_url":"https://github.com/treedomtrees.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# @treedom/graphql-auth-opa\n\n\u003ca href=\"https://www.treedom.net/it/organization/treedom/event/treedom-open-source?utm_source=github\"\u003e\u003cimg src=\"https://badges.treedom.net/badge/f/treedom-open-source?utm_source=github\" alt=\"plant-a-tree\" border=\"0\" /\u003e\u003c/a\u003e\n\nGraphQL Auth OPA is a directive for GraphQL Schema that adds an Authentication and Authorization directive using Open Policy Agent\n\n__Made with ❤️ at\u0026nbsp;\u0026nbsp;[\u003cimg src=\"https://assets.treedom.net/image/upload/manual_uploads/treedom-logo-contrib_gjrzt6.png\" height=\"24\" alt=\"Treedom\" border=\"0\" align=\"top\" /\u003e](#-join-us-in-making-a-difference-)__, [join us in making a difference](#-join-us-in-making-a-difference-)!\n\n## Usage\n\n```typescript\nimport { opaAuthDirective } from \"@treedom/graphql-auth-opa/opaAuthDirective\";\n// You could also use the @styra/opa OpaClient\nimport { OpenPolicyAgentClient } from \"@treedom/opa-client-sdk\";\n// \n\n// Include the directive in the schema\nconst typeDefs = `#graphql\n${opaAuthDirective}\n\ntype Query {\n  ping(message: String!): String! @opa(path: \"my/opa/policy\", options: { ... })\n}\n`\n\n// Configure OPA auth transformer\nconst opaTransformer =  opaAuthDirective(\n  {\n    requestContextField?: string // default: 'req' \n    directiveName?: string\n  }\n)\n\n// Apply the transformer function to the schema\nconst schema = opaTransformer(makeExecutableSchema({ typeDefs }))\n\n// if you want the context apply it to the Apollo context type\ntype MyContext = {request: IncomingMessage}\n\nconst server = new ApolloServer\u003cMyContext\u003e({\n  schema\n});\n\n// Start apollo with standalone server\n\nconst { url } = await startStandaloneServer(server, {\n  // require an http.IncomingMessage implementation \n  context: async ({ req }) =\u003e ({ request: req }),\n});\n```\n\n## OPA policy input\n\nThis plugin queries OPA providing the following properties as `input`:\n\n- `headers` the headers object, this requires a context request forwarding\n- `parent` the GraphQL parent object of the field/object which got queried\n- `args` the GraphQL args object of the field/object which got queried\n- `options` static untyped properties defined in the directive arguments _(optional)_\n\n### Example Rego Policy\n\nLet's imagine a GraphQL server which accept requests authorized using JWTs containing the `role` property in their claims.\nThe following Rego uses a hypotetical `oidc.verify_token` that validates the JWT signature and returns the token claims\nor false if the token is not valid.\n\n```rego\npackage my.opa.policy\n\nimport rego.v1\nimport data.oidc\n\ndefault allow := false\n\nallow if {\n    user := oidc.verify_token(input.headers.authorization)\n\n    user\n    user.role = \"admin\"\n}\n```\n\n## Headers forwarding\n\nIf you need to forward the headers to OPA you can use the `requestContextField` option to specify the name of the request context field.\n\nTo do that you need to manually build the context by adding the request object. \n\n\u003e Currently the request should have a `headers` property with `http.IncomingHttpHeaders` type. \n\u003e Compatible with `FastifyRequest\u003c...\u003e` and `http.IncomingRequest`.\n\n### Apollo Server Example\n```typescript\nimport { IncomingMessage } from 'node:http'\n\ntype MyContext { \n  req: IncomingMessage\n}\n\nconst opaClient = new OpenPolicyAgentClient({\n  url: 'http://opa.test:3000',\n})\n\nconst transformer = opaTransformer(opaClient, {\n  requestContextField: 'req' // should be the name of the request context field\n})\n\nconst schema = transformer(makeExecutableSchema({ typeDefs, ... }))\n\n\nconst server = new ApolloServer\u003cMyContext\u003e({...})\n\nconst { url } = await startStandaloneServer(server, {\n  context: async (ctx) =\u003e (ctx),\n});\n\n```\n\n### Fastify Example\n\n```typescript\nimport fastify, { FastifyRequest } from 'fastify'\nimport fastifyApollo, {\n  fastifyApolloDrainPlugin,\n} from '@as-integrations/fastify'\n\ntype MyContext = {\n  request: FastifyRequest\n}\n\nconst opaClient = new OpenPolicyAgentClient({\n  url: 'http://opa.test:3000',\n})\n\nconst transformer = opaTransformer(opaClient, {\n  requestContextField: 'request' // should be the name of the request context field\n})\n\nconst schema = transformer(makeExecutableSchema({ typeDefs, ... }))\n\n\nconst apolloServer = new ApolloServer\u003cApolloContext\u003e({\n    schema,\n    plugins: [fastifyApolloDrainPlugin(app)],\n  })\n\n  await apolloServer.start()\n\n  app.log.debug({}, 'Apollo Server plugin loaded')\n\n  // Build context function\n  await app.register(fastifyApollo(apolloServer), {\n    context: async (request) =\u003e {\n      return {\n        request, // FastifyRequest\n      }\n    },\n  })\n\n```\n\n\n## Custom directive\n\nThe authorization directive can be customized registering a custom one in the schema and specifying its name in the plugin configuration:\n\n```graphql\nscalar OpaOptions\ndirective @policy(path: String!, options: OpaOptions) on OBJECT | FIELD_DEFINITION\n```\n\n```typescript\nconst transformer = opaTransformer(opaClient, {\n  authDirective: 'policy'\n  opaOptions: {\n    // ...\n  }\n})\n\n```\n\n## 🌳 Join Us in Making a Difference! 🌳\n\nWe invite all developers who use Treedom's open-source code to support our mission of sustainability by planting a tree with us. By contributing to reforestation efforts, you help create a healthier planet and give back to the environment. Visit our [Treedom Open Source Forest](https://www.treedom.net/en/organization/treedom/event/treedom-open-source) to plant your tree today and join our community of eco-conscious developers.\n\nAdditionally, you can integrate the Treedom GitHub badge into your repository to showcase the number of trees in your Treedom forest and encourage others to plant new ones. Check out our [integration guide](https://github.com/treedomtrees/.github/blob/main/TREEDOM_BADGE.md) to get started.\n\nTogether, we can make a lasting impact! 🌍💚\n\n## Contributing\n\nContributions are welcome! Please read the contributing guidelines before submitting a pull request.\n\n## License\n\nThis project is licensed under the MIT License.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftreedomtrees%2Fgraphql-auth-opa","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftreedomtrees%2Fgraphql-auth-opa","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftreedomtrees%2Fgraphql-auth-opa/lists"}