graphql-shield

graphql-shield
GraphQL Server permissions as another layer of abstraction!
Overview
GraphQL Shield helps you create a permission layer for your application. Using an intuitive rule-API, you'll gain the power of the shield engine on every request and reduce the load time of every request with smart caching. This way you can make sure your application will remain quick, and no internal data will be exposed.
Try building a groceries shop to better understand the benefits of GraphQL Shield! Banana &Co. 🍏🍌🍓.
Explore common receipts and learn about advanced GraphQL! GraphQL Shield 3.0 ⚔️🛡🐴.
Features
✂️ Flexible: Based on GraphQL Middleware.
😌 Easy to use: Just add permissions to your Yoga
middlewaresset, and you are ready to go!🤝 Compatible: Works with all GraphQL Servers.
🚀 Smart: Intelligent V8 Shield engine caches all your request to prevent any unnecessary load.
🎯 Per-Type or Per-Field: Write permissions for your schema, types or specific fields (check the example below).
Install
Example
GraphQL Yoga
Others, using graphql-middleware
graphql-middlewareAPI
Types
shield(rules?, options?)
shield(rules?, options?)Generates GraphQL Middleware layer from your rules.
rules
A rule map must match your schema definition. All rules must be created using the rule function to ensure caches are made correctly. You can apply your rule across entire schema, Type scoped, or field specific.
Limitations
All rules must have a distinct name. Usually, you won't have to care about this as all names are by default automatically generated to prevent such problems. In case your function needs additional variables from other parts of the code and is defined as a function, you'll set a specific name to your rule to avoid name generation.
Cache is disabled by default. To enable
cachegeneration, set cache option when generating a rule.
Cache
You can choose from three different cache options.
no_cache- prevents rules from being cached.contextual- use when rule only relies oncontextparameter (useful for authentication).strict- use when rule relies onparentorargsparameter as well (field specific modifications).
Backward compatibility:
{ cache: false }converts tono_cache, and{ cache: true }converts tostrict.
Custom Errors
Shield, by default, catches all errors thrown during resolver execution. This way we can be 100% sure none of your internal logic can be exposed to the client if it was not meant to be.
To return custom error messages to your client, you can return error instead of throwing it. This way, Shield knows it's not a bug but rather a design decision under control. Besides returning an error you can also return a string representing a custom error message.
You can return custom error from resolver or from rule itself. Rules that return error are treated as failing, therefore not processing any further resolvers.
Errors thrown in resolvers can be tracked using
debugoption. This way Shield ensures your code is production ready at all times.
If you wish to see errors thrown inside resolvers, you can set
allowExternalErrorsoption totrue. This way, Shield won't hide custom errors thrown during query resolving.
options
allowExternalErrors
false
false
Toggle catching internal errors.
debug
false
false
Toggle debug mode.
fallbackRule
false
allow
The default rule for every "rule-undefined" field.
fallbackError
false
Error('Not Authorised!')
Error Permission system fallbacks to.
By default shield ensures no internal data is exposed to client if it was not meant to be. Therefore, all thrown errors during execution resolve in Not Authorised! error message if not otherwise specified using error wrapper. This can be turned off by setting allowExternalErrors option to true.
Per Type Wildcard Rule
There is an option to specify a rule that will be applied to all fields of a type (Query, Mutation, ...) that do not specify a rule. It is similar to the options.fallbackRule but allows you to specify a fallbackRule per type.
Basic rules
allow,denyare GraphQL Shield predefined rules.
allow and deny rules do exactly what their names describe.
Rules on Input Types or Arguments
Validate arguments using Yup.
Input rule works exactly as any other rule would work. Instead of providing a complex validation rule you can simply provide a Yup validation schema which will be mached against provided arguments. This can be especially useful when limiting optional fields such as create and connect with Prisma, for example.
Example:
Note that Yup receives entire args object, therefore, you should start composing schema with an object.
Logic Rules
and, or, not, chain, race
and,orandnotallow you to nest rules in logic operations.
and rule
and rule allows access only if all sub rules used return true.
chain rule
chain rule allows you to chain the rules, meaning that rules won't be executed all at once, but one by one until one fails or all pass.
The left-most rule is executed first.
or rule
or rule allows access if at least one sub rule returns true and no rule throws an error.
race rule
race rule allows you to chain the rules so that execution stops once one of them returns true.
not
not works as usual not in code works.
You may also add a custom error message as the second parameter
not(rule, error).
Global Fallback Error
GraphQL Shield allows you to set a globally defined fallback error that is used instead of Not Authorised! default response. This might be particularly useful for localization. You can use string or even custom Error to define it.
Fragments
Fragments allow you to define which fields your rule requires to work correctly. This comes in extremely handy when your rules rely on data from database. You can use fragments to define which data your rule relies on.
Whitelisting vs Blacklisting
Whitelisting/Blacklisting is no longer available in versions after
3.x.x, and has been replaced in favor offallbackRule.
Shield allows you to lock-in your schema. This way, you can seamlessly develop and publish your work without worrying about exposing your data. To lock in your service simply set fallbackRule to deny like this;
You can achieve same functionality by setting every "rule-undefined" field to
denythe request.
Troubleshooting
When a single field is "Not Authorised!" the entire parent object returns null.
This occurs when a non-nullable field (specified in the schema) returns a null value (due to GraphQL Shield blocking the field's value). GraphQL is a strongly typed language - the schema serves as a contract between client and server - which requires that the server response follow the schema definition.
See #126 and #97 for more detailed explanations.
A rule is executed only once even though the dataset contains multiple values (and thus should execute the rule multiple times)
This occurs because of caching. When the cache is set to contextual only the contextual variable of the rule is expected to be evaluated. Setting the cache to strict allows the rule to rely on parent and args parameters as well, while setting the cache to no_cache won't cache result at all.
Contributors
This project exists thanks to all the people who contribute. [Contribute].
Backers
Thank you to all our backers! 🙏 [Become a backer]
Sponsors
Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [Become a sponsor]
Contributing
We are always looking for people to help us grow graphql-shield! If you have an issue, feature request, or pull request, let us know!
License
MIT @ Matic Zavadlal
Last updated
