TheLearner
TheLearner

Reputation: 2873

How to query a Strapi backend using GraphQL as an authenticated user?

Currently, I'm able to just run a query as a public user and Strapi fetches me the results. However, I want to completely block all query access to public users and only allow it for authenticated users (preferably just one specific user).

I know I can block query access in the Roles & Permissions plugin and I also know that one could just create a new user with its own password in the Content Types -> Users screen. In fact, I already have, it's called web. Now, how do I execute queries in my /graphql/ endpoint as this particular user?

Upvotes: 3

Views: 2390

Answers (1)

Jim LAURIE
Jim LAURIE

Reputation: 4118

The GraphQL endpoint is not managed via a route but via a middleware. So the policy system is not applied.

You will not be able to remove access to this endpoint. but you can disable the GraphQL Playground GET /graphql by updating the GraphQL config files. Here is the documentation to do that https://strapi.io/documentation/3.0.0-beta.x/guides/graphql.html#configurations

If you want to restrict access to the GraphQL endpoint I suggest you to create a new middleware that will check if the triggered endpoint is /graphql and check if the authenticated user is the one you want.

Here is the documentation to create a middleware https://strapi.io/documentation/3.0.0-beta.x/advanced/middlewares.html

Your middleware will look to something like that

module.exports = strapi => {
  return {
    initialize() {
      strapi.app.use(async (ctx, next) => {
        const handleErrors = (ctx, err = undefined, type) => {
          if (ctx.request.graphql === null) {
            return (ctx.request.graphql = strapi.errors[type](err));
          }

          return ctx[type](err);
        };

        // check if it's a graphql request
        if (ctx.request.url === '/graphql' && ctx.request.method === 'POST') {
          if (ctx.request && ctx.request.header && ctx.request.header.authorization) {
            try {
              // get token data
              const { id } = await strapi.plugins[
                'users-permissions'
              ].services.jwt.getToken(ctx);

              if (id === undefined) {
                throw new Error('Invalid token: Token did not contain required fields');
              }

              // check if the id match to the user you want
              if (id !== 'my-user-id') {
                return handleErrors(ctx, 'You are not authorized to access to the GraphQL API', 'unauthorized');
              }
            } catch (err) {
              return handleErrors(ctx, err, 'unauthorized');
            }
          } else {
            // if no authenticated, return an error
            return handleErrors(ctx, 'You need to be authenticated to request GraphQL API', 'unauthorized');
          }
        }

        await next();
      });
    }
  };
};

This code will restrict to my-user-id the access to your GraphQL API.

To be authenticated you will have to send the JWT in the header. Please follow the documentation here to learn about it https://strapi.io/documentation/3.0.0-beta.x/guides/authentication.html

Upvotes: 2

Related Questions