Search code examples
strapi

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?


Solution

  • 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