3
votes

If i understand correctly, to authorize a query or mutation in hasura using JWT, there are a few requirements that needs to be fulfilled in the request itself, which is:

  1. The JWT itself, presented in the request header
    Authorization: Bearer <token here>
  2. x-hasura-role, presented in the request header (optional)
    x-hasura-role: user
  3. The actual query or mutation, presented in the request body
myQuery {
  id
  name
  another_field
}

When the request is then sent to the hasura endpoint, the hasura GraphQL engine will then try to

  1. Validate the JWT
  2. Check if the value of x-hasura-role that is set in the request header exists inside the x-hasura-allowed-role claims of the jwt
  3. If all conditions are met, then the GraphQL engine will check whether the role that is assigned from the value of x-hasura-role header have the permission to execute the query from the request body

To my understanding, this means that someone can 'forge' a request to the hasura GraphQL engine by setting the value of x-hasura-role to something else that exists inside the x-hasura-allowed-roles claim of the JWT. For example, if the x-hasura-allowed-roles claim is something like this

{
  ...
    'x-hasura-allowed-roles': ['role1','role2'],
    'x-hasura-default-role': 'role1',
    'x-hasura-user-id': username
  }
}

then it means someone who is supposedly only assigned to role1 can execute a query that is restricted to role2 only just by setting the x-hasura-role header in the request to x-hasura-role: role2

Is my understanding correct? If it is, what is the best way to avoid this situation, as it seems like a security vulnerability? Do I just limit the x-hasura-allowed-roles claim of the jwt to ONLY the role assigned to each user based on my authentication service?

1

1 Answers

5
votes

Your understanding seems correct, and it is not a security vulnerability.

Do I just limit the x-hasura-allowed-roles claim of the jwt to ONLY the role assigned to each user based on my authentication service?

That's exactly right. In this documentation (https://hasura.io/docs/1.0/graphql/manual/auth/authentication/jwt.html), the key information is here:

The JWT is decoded, the signature is verified, then it is asserted that the current role of the user (if specified in the request) is in the list of allowed roles. If the current role is not specified in the request, then the default role is applied.

So it's important that your auth server issues the list of allowed roles (and default) specific to that user; seems like Hasura is supporting a multi-role user with this feature. E.g. an admin might be able to "sign in as" with a user role, or a user's role might be different in different contexts of an app.

And for more specific definitions of these fields:

  1. A x-hasura-default-role field: indicating the default role of that user i.e. the role that will be used in case x-hasura-role header is not passed.
  2. A x-hasura-allowed-roles field: a list of allowed roles for the user i.e. acceptable values of the x-hasura-role header.