info:To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
# GraphQL Authorization
Authorizations can be applied in these places:
- Types:
- Objects (all classes descending from `::Types::BaseObject`)
- Enums (all classes descending from `::Types::BaseEnum`)
- Resolvers:
- Field resolvers (all classes descending from `::Types::BaseResolver`)
- Mutations (all classes descending from `::Types::BaseMutation`)
- Fields (all fields declared using the `field` DSL method)
Authorizations cannot be specified for abstract types (interfaces and
unions). Abstract types delegate to their member types.
Basic built in scalars (such as integers) do not have authorizations.
Our authorization system uses the same [`DeclarativePolicy`](../policies.md)
system as throughout the rest of the application.
- For single values (such as `Query.project`), if the currently authenticated
user fails the authorization, the field resolves to `null`.
- For collections (such as `Project.issues`), the collection is filtered to
exclude the objects that the user's authorization checks failed against. This
process of filtering (also known as _redaction_) happens after pagination, so
some pages may be smaller than the requested page size, due to redacted
objects being removed.
Also see [authorizing resources in a mutation](../api_graphql_styleguide.md#authorizing-resources).
NOTE:
The best practice is to load only what the currently authenticated user is allowed to
view with our existing finders first, without relying on authorization
to filter the records. This minimizes database queries and unnecessary
authorization checks of the loaded records. It also avoids situations,
such as short pages, which can expose the presence of confidential resources.
See [`authorization_spec.rb`](https://gitlab.com/gitlab-org/gitlab/blob/master/spec/graphql/features/authorization_spec.rb)
for examples of all the authorization schemes discussed here.
## Type authorization
Authorize a type by passing an ability to the `authorize` method. All
fields with the same type is authorized by checking that the
currently authenticated user has the required ability.
For example, the following authorization ensures that the currently
authenticated user can only see projects that they have the
`read_project` ability for (so long as the project is returned in a
field that uses `Types::ProjectType`):
```ruby
moduleTypes
classProjectType<BaseObject
authorize:read_project
end
end
```
You can also authorize against multiple abilities, in which case all of
the ability checks must pass.
For example, the following authorization ensures that the currently
authenticated user must have `read_project` and `another_ability`
abilities to see a project:
```ruby
moduleTypes
classProjectType<BaseObject
authorize[:read_project,:another_ability]
end
end
```
## Resolver authorization
Resolvers can have their own authorizations, which can be applied either to the
parent object or to the resolved values.
An example of a resolver that authorizes against the parent is
`Resolvers::BoardListsResolver`, which requires that the parent
satisfy `:read_list` before it runs.
An example which authorizes against the resolved resource is
`Resolvers::Ci::ConfigResolver`, which requires that the resolved value satisfy
`:read_pipeline`.
To authorize against the parent, the resolver must _opt in_ (because this
was not the default value initially), by declaring this with `authorizes_object!`:
```ruby
moduleResolvers
classMyResolver<BaseResolver
authorizes_object!
authorize:some_permission
end
end
```
To authorize against the resolved value, the resolver must apply the
authorization at some point, typically by using `#authorized_find!(**args)`:
```ruby
moduleResolvers
classMyResolver<BaseResolver
authorize:some_permission
defresolve(**args)
authorized_find!(**args)# calls find_object
end
deffind_object(id:)
MyThing.find(id)
end
end
end
```
Of the two approaches, authorizing the object is more efficient, because it
helps avoid unnecessary queries.
## Field authorization
Fields can be authorized with the `authorize` option.
Fields authorization is checked against the current object, and
authorization happens _before_ resolution, which means that
fields do not have access to the resolved resource. If you need to
apply an authorization check to a field, you probably want to add
authorization to the resolver, or ideally to the type.
For example, the following authorization ensures that the
authenticated user must have administrator level access to the project