Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Discussion / Request for Proposal - Enabling Authentication Headers in GraphiQL #299

Closed
bryanerayner opened this issue Feb 4, 2017 · 3 comments

Comments

@bryanerayner
Copy link

Presently, it is possible to add authentication headers to the GraphiQL client via the passHeader option.

example (from #133)

createApolloServer({
  /* schema and resolvers */
}, {
  graphiqlOptions: {
    passHeader: "'Authorization': localStorage['Meteor.loginToken']"
  }
})

This feature has not been documented, for good reason; It's a hacky injection of code via a template string, that could easily be abused if it were well publicised.

I don't think there's much wrong with the current implementation, provided that developers are okay with knowing they can break stuff. Is there anything holding this back from being documented?

@helfer
Copy link
Contributor

helfer commented Feb 24, 2017

@bryanerayner Rather than documenting the hacky solution, I think it would be better to recommend using Apollo Client developer tools for this purpose, which will use the network interface in Apollo Client and add the headers usually sent along with the request. Would that work for your use-case?

@majodev
Copy link

majodev commented Feb 24, 2017

Hi, it would be cool if we can still provide a way to do this (in a safe way), without requiring the installation of a special Chrome-only developer tool (Apollo Client developer tools). This way, non Web-Teams (e.g. native iOS/Android) can consume a secured documentation endpoint without much fuss.

Beware, the following is Hapi specific...

Currently, we are authenticating the graphiQL endpoint through basic-auth (all other endpoints work via accessTokens), require a special authorization scope named root (set only for superuser accounts in our services) and finally inject a valid accessToken for this very user in the onPreResponse handler directly into the HTML. Might sound complex. but this has been working pretty well for us.

Sample Plugin Registration:

{
   register: require("graphql-server-hapi").graphiqlHapi,
   options: {
       route: {
           description: "GraphiQL Endpoint (documentation)",
           tags: ["api", "graphql"],
           auth: {
               strategy: "basic-authentication",
               scope: "root",
           },
           ext: {
               onPreResponse: [{
                   method: async (request, reply) => {
                       const { response } = request;
                       const user: any = _.get(request, "auth.credentials.user");

                       // noop on errors
                       if (response.isBoom || !response.source || !user) {
                           return reply.continue();
                       }

                       // Non error, INJECT the accessToken from the authenticated user context directly into the <head> of the html response
                       // this token can be reused for making queries to the protected graphql endpoint
                       // we inject directly into the <head> to make sure this is called immediately on the browser side.
                       const { token } = await user.getNewAccessToken();

                       return reply(response.source.replace("</head>", `
                           <script>
                               window.__TOKEN = "${token}";
                               console.info("Hi!");
                               console.info("A new AccessToken '${token}' was automatically injected into this debug session.");
                               console.info('Feel free to set a different accessToken for another user anytime using:');
                               console.info('window.__TOKEN = "MY_NEW_ACCESSTOKEN"');
                           </script>
                           </head>
                       `));
                   }
               }]
           },
       },
       path: "/documentation/graphiql",
       graphiqlOptions: {
           endpointURL: "/cms-api/graphql",
           passHeader: "'Authorization': window.__TOKEN ? 'Bearer ' + window.__TOKEN : ''" // custom header can be set on the browser console
       },
   }
}

@DxCx
Copy link
Contributor

DxCx commented Feb 27, 2017

@majordev hey,

Once the websocket work is done, i want to rebuild the graphiql module so it will bundle inline using webpack,
(The current implementation style (using cdn) will be renamed to graphiql-cdn)
This way, people can replace the graphiql implementation using the existing fetchers.
Ive already seen a modified version of graphiql where the headers can be provided from ui, so you will be able to just switch to it for your project.
How does it sound?

@helfer helfer closed this as completed Jun 28, 2017
trevor-scheer pushed a commit that referenced this issue May 6, 2020
trevor-scheer pushed a commit that referenced this issue May 14, 2020
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Mar 15, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants