Allow disabling introspection queries
Is your feature request related to a problem? Please describe.
I would like to avoid serving introspection in production builds of some services. I have a build pipeline that publishes the schema to an artifact at build time using juniper::introspect, so I really don't need the online schema to be available on my production services.
Describe the solution you'd like I was looking for a way to disable introspection lookups on a RootNode, or filter introspection queries out at some layer of context, but I couldn't find an option to do that.
Describe alternatives you've considered Haven't found an alternative yet.
Additional context I'm happy to implement this but I'm not sure where to hang this. On the executor? That way in src/schema/schema.rs resolve_field, I could selectively resolve or fail depending on whether introspection was enabled or disabled on the executor, but would that involve passing in a new option to .execute(). Or does it makes sense to configure the root node with this flag?
It seems other graphql communities have something called "validations" that allow you to validate a query before even running it. Such as https://github.com/graphql-dotnet/graphql-dotnet/issues/766. That should probably be able to handle this. I wonder if it could also handle this https://github.com/graphql-rust/juniper/issues/447
I wonder if it could also handle this #447
Hmm... I guess not. The reason behind this that authorization is somewhat defined on user-defined GraphQL types, or even exists before any schema resolution (so schema in this case is authorization-agnostic), while the introspection query does not interact with user-defined types, but their meta (which handled by Juniper automatically).
I guess this could be solved either allowing to attach some code for meta resolving or deeply inspecting the request before executing.
Any more thought was given to this? Introspection should be disabled in production environments unless you have a public-facing API where you need it, in order to avoid enumeration of types/queries.
It would be nice to opt queries and types out of the default public visibility. Perhaps as a proc macro attribute where the default is to expose, but can be made private:
#[graphql(description = "..", visibility = "private")]
fn query(context: &Context, ..) -> FieldResult<..> {
//..
}
But with this approach, there is the problem of: A change on type visibility should also affect related queries, or is the user responsibility to expose properly?
Or even the simplest option is to disable introspection server-wide while there is a better solution to individual visibility.
Is it even spec compliant to not allow introspection? We don't handle introspections in a special way, we just treat them as a normal query (and this is how they are handled in the spec).
While I am almost certain it is not mentioned in the spec, it is positively a good thing to have natively in the framework. Please forgive me if there is already a mechanism to implement something like this, I still do not have a lot of familiarity with juniper.
Several frameworks allow disabling introspection nativaly, such as Apollo Graphql, grapql-php, graphql-ruby
Other frameworks allow the user to replace the schema with another one through middleware, e.g Python Graphene
Like @tyranron suggested, most of them inspect the query to check for __schema and __type introspection entry points.
We can find several security-oriented websites that recommend disabling introspection to make potential attackers have more trouble finding vulnerabilities, avoid leaking non-public types, and errors in general:
Thank you for this! I agree this is good to have.