hasura / graphql-engine

Blazing fast, instant realtime GraphQL APIs on your DB with fine grained access control, also trigger webhooks on database events.
https://hasura.io
Apache License 2.0
31.18k stars 2.77k forks source link

why is x-hasura-default-role is prefered over x-hasura-role #2849

Closed ifdotpy closed 5 years ago

ifdotpy commented 5 years ago

Hi! Thank you for your awesome work.

I have an issue with jwt. While using this HASURA CLAIMS:

{ "x-hasura-default-role": "anonymous", "x-hasura-allowed-roles": [ "user", "anonymous", "admin", "institution-admin" ], "x-hasura-role": "user", "x-hasura-user-id": "rglCjqnVAKbBx0Q7jke73blCKmu1" }

Hasura identifies request sender as anonymous

When changed to this HASURA CLAIMS: { "x-hasura-default-role": "user", "x-hasura-allowed-roles": [ "user", "anonymous", "admin", "institution-admin" ], "x-hasura-role": "user", "x-hasura-user-id": "rglCjqnVAKbBx0Q7jke73blCKmu1" }

Hasura identifies request sender as user

image

Why can this be happening?

0x777 commented 5 years ago

x-hasura-role has to be sent with the http request. It is not expected to be part of the JWT's hasura claims and as such it is ignored. The x-hasura-role sent with the request is checked to see if it is part of the x-hasura-allowed-roles and if yes, the request is executed as that role. In case the x-hasura-role is missing, the x-hasura-default-role from the JWT is used.

dohomi commented 5 years ago

In my opinion / besides the confusion I had just now, the developer needs to verify the HTTP header again - I thought this would be done directly in the JSON token already. It leads to slightly more written code - the client side needs to attach the header, the server side needs to validate if the Authentication + x-hasura-role is actually still valid UPDATE: Is this not a potential security issue? if the generated token includes the hasura-role, thats not readable for any user. But to attach a request header as simple as x-hasura-role:"admin" could be fairly manipulated and as far as I see it won't be verified

ifdotpy commented 5 years ago

@dohomi Initially I also thought it is a security issue. But then realized that auth server should return correct role list (x-hasura-allowed-roles). Which means that the roles in the list are the only roles that can be put into x-hasura-role header.

dohomi commented 5 years ago

yes.. I was a bit slow in my head and initially thought that allowed-roles should be same across all created JWT tokens. But now I prepare the JWT on the server that the default-role and allowed-roles are directly connected to the user and the security flaw I had in mind before is gone. A user only has allowed-roles:["user"] while an admin potentially could verify himself as user-role:["admin","user","manager"] and set the default-role:"admin"

ifdotpy commented 5 years ago

@dohomi I thought same when created the issue.

galipmedia commented 4 years ago

This has really thrown me. I have my headers set in a boot file that gets setup once and checks if there is a jwt or not which is fine because that is either there or not. But say I want a 'user' to be able to see all his own details based on his x-hasura-id, but i also want him to be able to see as 'public' all the other users usernames and avatars he cannot, he only sees his own in the list. It means I will have to carefully chain all my queries and for each one set some state of x-user-role and inject it in the headers, that seems like a nightmare. Surely your average Joe using vue-apollo or something is not going to want to do this. Does anyone know a better way? Is it bad practice to have 2 apollos setup, one for each user role ?

galipmedia commented 4 years ago

It just occurred to me that I have to use a view in the database and give it different permissions, with just the fields I want them to see and allow public and user to view that table too.

nisharmultani commented 2 years ago

Documentation: An x-Hasura-default-role field: indicating the default role of that user i.e. the role that will be used in case the x-Hasura-role header is not passed.

Question? according to documentation, I don't have the x-Hasura-role in jwt then tack default role but I have x-Hasura-role but still its tack default role anyone can please find me the solution

code: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI2OSIsInJvbGUiOiJhZG1pbmlzdHJhdG9yIiwidXNlcm5hbWUiOiJhZG1pbiIsImlhdCI6MTY1MjEyMDU2MC4wNzMsImh0dHBzOi8vaGFzdXJhLmlvL2p3dC9jbGFpbXMiOnsieC1oYXN1cmEtYWxsb3dlZC1yb2xlcyI6WyJhZG1pbiIsInVzZXIiLCJhZG1pbmlzdHJhdG9yIl0sIngtaGFzdXJhLXVzZXItaWQiOiI2OSIsIngtaGFzdXJhLWRlZmF1bHQtcm9sZSI6InVzZXIiLCJ4LWhhc3VyYS1yb2xlIjoiYWRtaW5pc3RyYXRvciJ9LCJleHAiOjE2NTIyMDY5NjB9.muIsOEBM-G2MXn1SBn2HQp0XIAy_95b6QmU_c5B7ZzA

Screenshot from 2022-05-09 23-53-10

explanation: as you can see in the Screenshot I have x-Hasura-role but its still tack default roll

how to solve this problem?

ivan-kleshnin commented 2 years ago

Something's fundamentally wrong with names or docs here.

x-user-role is optional, but it has to override x-hasura-default-role, but it doesn't. You can send it, and it will be applied, but it will be ignored.

Sorry, what? 🤔 🤡

I second @nisharmultani. x-hasura-role has lower priority (or simply ignored) than x-hasura-default-role which directly contradicts this line (and naming):

The default role can be overridden by the x-hasura-role header, while making a request. https://hasura.io/docs/latest/auth/authentication/jwt/

This issue should be reopened. As a temporary workaround use:

"x-hasura-allowed-roles": [user.role],
"x-hasura-default-role": user.role,
"x-hasura-user-id": token.sub,

instead of supposedly more correct:

"x-hasura-allowed-roles": ALLOWED_ROLES,
"x-hasura-default-role": "visitor", // e.g.
"x-hasura-role": user.role,
"x-hasura-user-id": token.sub,
tjad commented 1 year ago

Are these headers case sensitive (traditionally headers shouldn't be case sensitive, but depend on the server impl) ? I am having similar issue. I send X-Hasura-Role as a header, it is completely ignored in favour of the default-role inside the token?