Restrict Command Execution with Role-based Permissions
Introduction
Often, you'll want to limit a user's ability to execute certain commands — which power mutations in your GraphQL API — based on some related data. In the example below, we'll build on the tutorial found in our PostgreSQL getting-started section and restrict users to only being able to update posts of which they're the author.
Before continuing, ensure you have:
- A local Hasura DDN project.
- Either JWT or Webhook mode enabled in your AuthConfig.
Tutorial
Step 1. Add an author
role to your CommandPermissions object
---
kind: CommandPermissions
version: v1
definition:
commandName: UpdatePostsById
permissions:
- role: admin
allowExecution: true
- role: author
allowExecution: true
argumentPresets:
- argument: preCheck
value:
booleanExpression:
relationship:
# Here, `user` refers to the pre-generated relationship's name
name: user
predicate:
fieldComparison:
field: id
operator: _eq
value:
sessionVariable: x-hasura-user-id
This role grants the author
role permission to execute the UpdatePostsById
command, but only if the user who
authored the post has an id
that matches the x-hasura-user-id
session variable in the request header. This ensures
users can only update posts they have authored.
Step 2. Add TypePermissions to your response type
The new author
role will need access to return types for the UpdatePostsByIdResponse
type.
kind: TypePermissions
version: v1
definition:
typeName: UpdatePostsByIdResponse
permissions:
- role: admin
output:
allowedFields:
- affectedRows
- returning
- role: author
output:
allowedFields:
- affectedRows
In the configuration above, we're only allowing a user with the role of author
to access the number of affected rows.
Alternatively, you could include returning
in the output
array and then set ModelPermissions and
TypePermissions for the author
role on the Posts
type to allow for any or specific fields to be returned.
Step 3. Create a new build and test
kind: AuthConfig
version: v3
definition:
mode:
noAuth:
role: author
sessionVariables: { "x-hasura-user-id": 1 }
This will set your x-hasura-role
session variable as author
and the x-hasura-user-id
as 1
, enabling you to
impersonate Alice.
ddn supergraph build local && ddn run docker-start
mutation UPDATE_POST_TITLE {
updatePostsById(keyId: "1", updateColumns: { title: { set: "This is not Alice's first post" } }) {
affectedRows
}
}
{
"data": {
"updatePostsById": {
"affectedRows": 1
}
}
}
mutation UPDATE_POST_TITLE {
updatePostsById(keyId: "4", updateColumns: { title: { set: "Malicious Actions in the API" } }) {
affectedRows
}
}
{
"data": {
"updatePostsById": {
"affectedRows": 0
}
}
}
Wrapping up
In this tutorial, we've demonstrated the minimum sets of permissions necessary to enforce role-based execution of commands. While the example illustrates limiting users to updating their own posts, the principles can be applied to any scenario by which you want to limit command execution — and mutations — based on relationships.
Learn more about permissions and auth
- Permissions with Hasura DDN
- Auth with Hasura DDN