Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Graphql shield returns Not Authorised for allowed mutation

I am trying to implement GraphQL API using apollo-server-express. I want to manage permissions by graphql-shield middleware but I am having issues with allowing execution of mutations. My goal is to have JWT based authentication but to allow execution of some queries/mutations to unauthenticated users which is needed for register/login mutations. There for I am using default allow rule. But when I try to run login mutation, I receive Not Authorised! error. I have no clue why is that. The rule works fine with queries.

Thank you for the answer.

Server

import express from "express";
import cors from "cors";
import { ApolloServer, makeExecutableSchema } from "apollo-server-express";
import config from "./config";
import mockResolver from "./resolvers/mockResolver";
import typeDefs from "./graphql/typeDefs";
import { applyMiddleware } from "graphql-middleware";
import permissions from "./graphql/permissions";

const app = express();
app.use(cors());

const server = new ApolloServer({
  schema: applyMiddleware(
    makeExecutableSchema({ typeDefs, resolvers: mockResolver }),
    permissions
  ),
  playground: true,
  introspection: true,
});

server.applyMiddleware({ app, path: "/graphql" });
app.listen(config.PORT, () =>
  console.log("Server listening at http://localhost:%s", config.PORT)
);

TypeDefs

import { gql } from "apollo-server";

const typeDefs = gql`
  type User {
    id: Int!
    email: String!
    password: String!
  }

  type LoginResponse {
    id: String
    email: String
    token: String
  }

  type Query {
    user(id: Int!): User
    users: [User]
  }

  type Mutation {
    login(email: String!, password: String!): LoginResponse
  }
`;

Permissions

import { shield, allow } from "graphql-shield";

const permissions = shield({
  Query: {
    users: allow,
  },
  Mutation: {
    login: allow,
  },
});

export default permissions;
like image 709
Jakub Jaroš Avatar asked Sep 17 '25 02:09

Jakub Jaroš


2 Answers

const permissions = shield({
  Query: {
    users: allow,
  },
  Mutation: {
    login: allow,
  },
});    

to

const permissions = shield({
  Query: {
    users: allow,
  },
  Mutation: {
    login: allow,
  },
},
{
  debug: true
});

and trace to error messages.

like image 136
Selpano Avatar answered Sep 18 '25 17:09

Selpano


Both of the above are correct, but if you want to limit the data that might accidentally get exposed to the client, you could keep both allowExternalErrors: false and debug: false and handle this on a case-by-case basis. To accomplish that, you need to return any intentionally created errors instead of throwing them. That way, GraphQL Shield can handle those errors intelligently because it knows that returned errors are intended to filter up to the client.

return new Error('This should make it passed the Shield');

vs

throw new Error('This will return a "Not Authorised!" message')

Per their documentation:

To return custom error messages to your client, you can return error instead of throwing it. This way, Shield knows it's not a bug but rather a design decision under control. Besides returning an error you can also return a string representing a custom error message

https://the-guild.dev/graphql/shield/docs/errors

like image 42
NobleBema Avatar answered Sep 18 '25 18:09

NobleBema