apollo-link-persisted-queries
apollo-link-persisted-queries copied to clipboard
How to precompute query hashes, store it, and use it to whitelist persisted queries.
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
- [x] feature
- [x] blocking
- [ ] good first issue
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.
you can see this issue for more informations about this: https://github.com/apollographql/apollo-tooling/issues/1117
isn't the point of automatic persisted queries to not use whitelist ? if i understand correctly you can use persistgraphql
you can use persistgraphql
NB. persistgraphql is being deprecated in favour of apollo-link-persisted-queries and apollo-cli...
@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)
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: https://github.com/apollographql/apollo-tooling/issues/1117#issuecomment-486653821
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.
@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 ?
@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 (!)
@abumalick Anyway, thanks for your reply!
You are welcome. Sorry that I cannot help more.
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 ..

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.
Yes, it is interesting.
Would you consider to opensource it ? If it is very simple to implement it may bring interest of the community.
Yes, I will think how would it be feasible to make an universal lib out of it. Will let know
@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.
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);
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.