You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: core/graphql.md
+105-1Lines changed: 105 additions & 1 deletion
Original file line number
Diff line number
Diff line change
@@ -176,7 +176,7 @@ If you don't know what queries are yet, please [read the documentation about the
176
176
For each resource, two queries are available: one for retrieving an item and the other one for the collection.
177
177
For example, if you have a `Book` resource, the queries `book` and `books` can be used.
178
178
179
-
###Global Object Identifier
179
+
###Global Object Identifier
180
180
181
181
When querying an item, you need to pass an identifier as argument. Following the [GraphQL Global Object Identification Specification](https://relay.dev/graphql/objectidentification.htm),
182
182
the identifier needs to be globally unique. In API Platform, this argument is represented as an [IRI (Internationalized Resource Identifier)](https://www.w3.org/TR/ld-glossary/#internationalized-resource-identifier).
@@ -1132,6 +1132,110 @@ class Book
1132
1132
}
1133
1133
```
1134
1134
1135
+
### Securing Properties (Including Associations)
1136
+
1137
+
You may want to limit access to certain resource properties with a security expression. This can be done with the `ApiProperty` `security` attribute.
1138
+
1139
+
Note: adding the `ApiProperty` `security` expression to a GraphQL property will automatically make the GraphQL property type nullable (if it wasn't already).
1140
+
This is because `null` is returned as the property value if access is denied via the `security` expression.
1141
+
1142
+
In GraphQL, it's possible to expose associations - allowing nested querying.
1143
+
For example, associations can be made with Doctrine ORM's `OneToMany`, `ManyToOne`, `ManyToMany`, etc.
1144
+
1145
+
It's important to note that the security defined on resource operations applies only to the exposed query/mutation endpoints (e.g. `Query.users`, `Mutation.updateUser`, etc.).
1146
+
Resource operation security is defined via the `security` attribute for each operation defined in the `ApiResource` `graphql` attribute.
1147
+
This security is *not* applied to exposed associations.
1148
+
1149
+
Associations can instead be secured with the `ApiProperty` `security` attribute. This provides the flexibility to have different security depending on where an association is exposed.
1150
+
1151
+
To prevent traversal attacks, you should ensure that any exposed associations are secured appropriately.
1152
+
A traversal attack is where a user can gain unintended access to a resource by querying nested associations, gaining access to a resource that prevents direct access (via the query endpoint).
1153
+
For example, a user may be denied using `Query.getUser` to get a user, but is able to access the user through an association on an object that they do have access to (e.g. `document.createdBy`).
1154
+
1155
+
The following example shows how associations can be secured:
The above example only allows admins to see the full collection of each resource (`collection_query`).
1232
+
Users must be granted the `VIEW` attribute on a resource to be able to query it directly (`item_query`) - which would use a `Voter` to make this decision.
1233
+
1234
+
Similar to `item_query`, all associations are secured, requiring `VIEW` access on the parent object (*not* on the association).
1235
+
This means that a user with `VIEW` access to a `Document` is able to see all users who are in the `viewers` collection, as well as the `createdBy` association.
1236
+
This may be a little too open, so you could instead do a role check here to only allow admins to access these fields, or check for a different attribute that could be implemented in the voter (e.g. `VIEW_CREATED_BY`.)
1237
+
Alternatively, you could still expose the users, but limit the visible fields by limiting access with `ApiProperty` `security` (such as the `User::$email` property above) or with [dynamic serializer groups](serialization.md#changing-the-serialization-context-dynamically).
1238
+
1135
1239
## Serialization Groups
1136
1240
1137
1241
You may want to restrict some resource's attributes to your GraphQL clients.
0 commit comments