Skip to content
This repository has been archived by the owner on Jan 27, 2022. It is now read-only.

How to precompute query hashes, store it, and use it to whitelist persisted queries. #28

Open
2 of 4 tasks
joonhocho opened this issue Oct 10, 2018 · 17 comments
Open
2 of 4 tasks
Labels
blocking Prevents production or dev due to perf, bug, build error, etc.. feature Feature: new addition or enhancement to existing solutions

Comments

@joonhocho
Copy link

joonhocho commented Oct 10, 2018

I want disallow arbitrary queries from client to prevent abusive queries.
How do I extract and compute query hashes and save it as a query white list file and use load it on apollo server to whitelist them?
I've tried apollo-cli apollo queries:extract, but its hashed value does not match the one created by apollo-link-persisted-queries.

  • has-reproduction
  • feature
  • blocking
  • good first issue
@ghost ghost added blocking Prevents production or dev due to perf, bug, build error, etc.. feature Feature: new addition or enhancement to existing solutions labels Oct 10, 2018
@abumalick
Copy link

abumalick commented Mar 14, 2019

We had the same problem while trying to implement persisted queries in our apps.

I made a reproduction repository to clearly show that the hash generated by apollo-link-persisted-queries is different from the one generated by apollo-tooling.

https://github.com/abumalick/persisted-queries-showcase

You can clearly see the hash generated by apollo client:extract in this file.

And you can see the hash generated by apollo-link-persisted-queries in the deployed app. You can look in the request details in devtools.

If you want more details, I explained everything in the README

Also I tried hard, exploring apollo-tooling source code and playing with generateHash config to try to generate hashes that match but I could not do it.

Help would be very appreciated.

@abumalick
Copy link

you can see this issue for more informations about this: apollographql/apollo-tooling#1117

@Sceat
Copy link

Sceat commented Apr 29, 2019

isn't the point of automatic persisted queries to not use whitelist ? if i understand correctly you can use persistgraphql

@poshaughnessy
Copy link

you can use persistgraphql

NB. persistgraphql is being deprecated in favour of apollo-link-persisted-queries and apollo-cli...

@bartero
Copy link

bartero commented Aug 12, 2019

@abumalick why use the apollo-link-persisted-queries at all?
Writing your own link is the easiest thing to make from it all! I wrote my own apollo link to work with the vue-apollo without problems.

If you know how to:

  • generate a map from normalized query string to some unique identifier
  • map each query in your apollo link implementation to a normalized string

you are at home.
Just use the generated map in your apollo link on the client side and for reversing on the server side.

I want to do the same but I am stuck with seemingly trivial task: how, for God's sake, use this apollo client:extract tool to generate the normalized query string --> unique identifier map.

After that I have to face another challenge: find someway to generate matching normalized stringified query (to use in my simple apollo link implementation)

@abumalick
Copy link

abumalick commented Aug 12, 2019

Manipulating the hash on the client side with apollo-link-peristed-queries is pretty easy, you can use the generateHash arg.

Like you said, the real problem is making these hashes match the normalized queries generated by apollo client:extract, I tried hard and eventually stopped working on it.

You should read this answer from apollo team if you didn't already: apollographql/apollo-tooling#1117 (comment)

Personally I chose to not work on something that is not supported by the package maintainers, it will feel hacky and will probably not be stable. I stopped working on this at the moment.

@bartero
Copy link

bartero commented Aug 12, 2019

@abumalick Is then only the <step of normalized stringifying of a query> problematic to repeat in same way (actually: with same function) in the apollo link (which is then passed to the generateHash function) and in the command generating the map of queries ?

@bartero
Copy link

bartero commented Aug 12, 2019

@abumalick https://www.apollographql.com/docs/platform/operation-registry/

Note: Operation safelisting is an Apollo Platform feature that is only available to subscribers of the Apollo Team and Enterprise plans. Visit this guide to learn more about the Apollo Platform.

... and it seems more clear now. This is an already made feature but for paid plans only, unfortunately (!)

@bartero
Copy link

bartero commented Aug 12, 2019

@abumalick Anyway, thanks for your reply!

@abumalick
Copy link

You are welcome. Sorry that I cannot help more.

@Cerberus
Copy link

I've forked apollo repo to implement this for workaround. (In case you are interested)

https://github.com/Cerberus/apollo-persisted-hash

The result: top half is chrome screen-shot on network tab and the another one is part of white-list file that generated by apollo client:extract ..

Screen Shot example

@bartero
Copy link

bartero commented Aug 22, 2019

Hello everyone,
Hello @abumalick again,
I have worked out a very simple solution with no hacks at all by writing a very small amount of code and only using the official libraries from the apollo ecosystem: graphql-tag, graphql and apollo-utilities.

I have a script which traverse directories where I keep the *.graphql files (with queries) on the client side. It produces a json mapping all the queries to consecutive integers. It does use exactly the same loader tool from graphql-tag, which webpack uses - what your webpack setup can work with so it can! :-)

That script in full readable/formatted form is just 56 lines of code and makes up ~80% of all code to make the whole scheme with frontend <--> backend safely work.

I may share code snippets for the interested.

@abumalick
Copy link

Yes, it is interesting.

Would you consider to opensource it ? If it is very simple to implement it may bring interest of the community.

@bartero
Copy link

bartero commented Aug 22, 2019

Yes,
I will think how would it be feasible to make an universal lib out of it.
Will let know

@Sytten
Copy link

Sytten commented Apr 2, 2020

@bartero I am in the same exact situation, I think it would be nice for the community to create a tool to extract queries and a simple link for the server to filter.

@stefanvs
Copy link

stefanvs commented Jun 19, 2020

I just use the hashing function from this library to create a whitelist, and return a 403 if you make a request with a different hash. If you make a request using a valid hash but provide a query that doesn't correspond to the hash you'll get a 400 provided sha does not match query, even if the query wasn't persisted yet.

import gql from 'graphql-tag';
import _ from 'lodash';
import { defaultGenerateHash } from 'apollo-link-persisted-queries';

const LOGIN = gql`
  mutation Login($email: String!, $password: String!) {
    login(email: $email, password: $password) {
      success
      error
      __typename
    }
  }
`;

export const queries = {
  LOGIN,
};

export const whitelist = _.mapValues(queries, defaultGenerateHash);

@antonin87
Copy link

Hello,
Any updates about queries hashes ? I worked on persisted queries too, but i would not use deprecated lib persistgraphql to do that, even if it's works.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
blocking Prevents production or dev due to perf, bug, build error, etc.. feature Feature: new addition or enhancement to existing solutions
Projects
None yet
Development

No branches or pull requests

10 participants