node.jsgraphqlapolloapollo-servergraphql-shield

How to Integrate the latest graphql-shield with my @apollo/server


import * as dotenv from "dotenv";
import mongoose from "mongoose";
import typeDefs from "./graphql/typeDefs.js";
import resolvers from "./graphql/resolvers.js";

import { ApolloServer } from "@apollo/server";
import { expressMiddleware } from "@apollo/server/express4";
import { ApolloServerPluginDrainHttpServer } from "@apollo/server/plugin/drainHttpServer";
import express from "express";
import http from "http";
import pkg from "body-parser";
import cors from "cors";
import { applyMiddleware } from "graphql-middleware";
import { shield } from "graphql-shield";
dotenv.config();
const { json } = pkg;
const MONGODB = process.env.MONGODB;

const app = express();
const httpServer = http.createServer(app);
const server = new ApolloServer({
  typeDefs,
  resolvers,
  plugins: [ApolloServerPluginDrainHttpServer({ httpServer })],
});

await mongoose.connect(MONGODB, {
  useNewUrlParser: true,
});

await server.start();

app.use(
  "/graphql",
  cors({
    origin: ["https://studio.apollographql.com", process.env.FRONTEND_DEV_URL],
  }),
  json(),
  expressMiddleware(server, {
    context: ({ req }) => ({
      token: req.headers.authorization || "",
    }),
  })
);

await new Promise((resolve) =>
  httpServer.listen({ port: process.env.PORT || 4000 }, resolve)
);
console.log(`🚀 Server ready `);

package.json:

  "dependencies": {
    "@apollo/server": "^4.7.1",
    "bcrypt": "^5.1.0",
    "body-parser": "^1.20.2",
    "cors": "^2.8.5",
    "express": "^4.18.2",
    "graphql": "^16.6.0",
    "graphql-middleware": "^6.1.34",
    "graphql-shield": "^7.6.5",
    "graphql-tag": "^2.12.6",
    "mongoose": "^7.0.4"
  }

The problem I have is that the official documentation for the graphql-shield is limited and It says I need to apply a middleware and pass my "Schema" and "server"

But as you can see in my code I do not have any Schema and it is automatically being generated by ApolloServer.

My Question: How to implement graphql-shield so I can start to define rules and limit access to queries and mutations or is there a better alternative?

official documentation


Solution

  • You need to pass schema to Apollo, you can create schema by using buildSchema from graphql

    Here's a simple pseudo code, its just example

    import { buildSchema} from 'graphql'
    
    const schema = buildSchema({
      typeDefs,
      resolvers
    })
    const permissions = shield({
      Query: {
        frontPage: not(isAuthenticated),
        fruits: and(isAuthenticated, or(isAdmin, isEditor)),
        customers: and(isAuthenticated, isAdmin),
      },
      Mutation: {
        addFruitToBasket: isAuthenticated,
      },
      Fruit: isAuthenticated,
      Customer: isAdmin,
    })
    const securedSchema = applyMiddleware(schema, permissions)
    
    const server = new ApolloServer({
        schema: securedSchema
    })
    ...