Custom Authorization Policies
The @policy directive lets you enforce authorization rules that the router cannot evaluate on its
own, such as resource ownership, tenant isolation, or any business rule that lives in your own
systems. Instead of hard-coding that logic in every subgraph, you declare a policy name in your
schema and let a coprocessor decide
whether the current request satisfies it.
@policy complements @authenticated and @requiresScopes,
which are described in the general Authorization guide. Use
@policy when the decision cannot be derived from a JWT scopes alone.
For the complete configuration reference, see
authorization configuration.
How It Works
- Collect - before calling the
graphql.analysiscoprocessor stage, the router walks the requested operation and publishes every@policypolicy it depends on to thehive::authorization::required_policiesrequest context key, mapped tonull. - Decide - your coprocessor (or a plugin) looks at
the request and overwrites each entry with
trueorfalse. - Enforce - after the stage returns, the router applies the decisions. Any policy left
null, or missing from the answer entirely, is treated as denied. Unauthorized fields are then handled exactly like@authenticated/@requiresScopesviolations, following your configuredauthorization.directives.unauthorized.mode.
Defining Policies in Your Schema
Just like @requiresScopes, policies is a list of lists: an OR of AND groups.
- Single list (AND logic): every policy in the list must be granted.
- Multiple lists (OR logic): at least one full list must be granted.
In the example above, users is allowed if the admin policy is granted, or if both
read_users and internal are granted.
When multiple directives protect the same field, all of them must be satisfied - @policy is
combined with @authenticated/@requiresScopes using AND, the same way multiple auth directives
on one field already compose in the Authorization guide.
Wiring Up a Coprocessor
Enable the graphql.analysis stage and include the request context, so your coprocessor can read
hive::authorization::required_policies and reply with its decisions:
Coprocessor Input
For an operation that selects Query.users, the graphql.analysis stage payload includes the
policies the router needs a decision on, each initialized to null:
Coprocessor Output
Your coprocessor looks up the current user (from headers, a session store, an internal service - whatever your business logic requires) and answers by overwriting the relevant entries:
Given this answer, the read_users AND internal group is fully satisfied, so users is
authorized even though admin was denied.
Handling Denied Policies
A denied policy is handled exactly like any other unauthorized field access - the field is filtered
out (or the whole request is rejected in reject mode) and an error is returned:
See Handling Authorization Errors
for the full behavior of filter and reject modes.