पाठ 14 / 25

Context and Authorisation

Who is asking, and may they see this field?

Authenticate once, authorise everywhere

Authenticate the request once (from a session cookie or bearer token) when building the context, and pass the user, data loaders and services to all resolvers. Authorise in the business layer or per field: because clients can reach any object through many paths in the graph, checking only at root fields is not enough. Schema directives (such as an @auth directive) or middleware can apply rules declaratively, but the checks must run for every field that exposes protected data.

Field-level authorisation

Resolver sketch.

const resolvers = {
  User: {
    // anyone who can see a user sees the name
    name: (user) => user.name,
    // only the user themself or an admin sees the email
    email: (user, _args, { viewer }) => {
      if (!viewer) throw new GraphQLError("Not authenticated", { extensions: { code: "UNAUTHENTICATED" } });
      if (viewer.id !== user.id && !viewer.isAdmin) return null;
      return user.email;
    },
  },
};

Authorise the object, not the path

An order reachable via me.orders and via product.recentOrders must be protected in both places; enforce it where the order is loaded.

त्वरित जाँच: Why is authorising only root fields insufficient in GraphQL?

  • GraphQL has no authentication
  • Root fields cannot have resolvers
  • Context is not available in nested fields
  • The same data can be reached through many nested paths
Answer

The same data can be reached through many nested paths — Protect data where it is resolved.