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.16k stars 2.76k forks source link

provide JWT token in transactions #3872

Open ElixirMike opened 4 years ago

ElixirMike commented 4 years ago

In my Postgres DB, I have some tables where I have specified some default inserts based on passed in JWT token claims. This was from using a different solution..but utlimately, in Postgres, I could specify the variable using this format for example. I could place this in the default value, such that upon insert, it would use the logged in users "userid" value.

(current_setting('request.jwt.claims.userid'::text, true))::integer

Does Hasura pass the JWT claims to Postgres like this? I tried the above, but nothing was recognized so I'm wondering if you don't pass them or if you use a different format.

arjunyel commented 4 years ago

https://docs.hasura.io/1.0/graphql/manual/schema/default-values/index.html

ElixirMike commented 4 years ago

Yes, I'm familiar with those settings, but when it mentions role based column presets, it's all done through Hasura permissions.

https://docs.hasura.io/1.0/graphql/manual/schema/default-values/column-presets.html

I was explicitly asking if Hasura passes these Sessions to Postgres so that I can reference them directly in postgres tables, Like how I showed in my previous posting.

pnappa commented 4 years ago

@ElixirMike if you want to see the query sent to Postgres for a given graphql query, enable the logging for queries, and observe the logs (using docker-compose logs, or whatever, depending on how you're running it).

You'll be able to see the SQL query (as a function, with arguments passed in). It's fairly big, so it may be a bit difficult to understand what's going on.

ElixirMike commented 4 years ago

Thanks, but not exactly what I was looking for. I've used a tool called Postgrest, which allows PostGres SQL to access JWT claoms through GUC variables that are set by Postres per request.

Here is the snippet that explains: http://postgrest.org/en/v6.0/auth.html#web-users-sharing-role

I'm guessing Hasura has a different implementation, but this feature would be very nice to add.. The ability to include whatever we want in the JWT claim, and then have direct access to this data in Postgres direclty enables a bunch of different scenarios. The most important one for me is to be able to use RLS (Row Level Security) directly in Postgres.

leoalves commented 4 years ago

@ElixirMike,

Maybe this is what you are looking for: https://docs.hasura.io/1.0/graphql/manual/guides/auditing-tables.html

ecthiender commented 4 years ago

@ElixirMike can you explain your use-case in a bit more detail, of accessing session variables in Postgres? That will help us to get a better understanding. A concrete example will be immensely helpful.

Currently, you can access the session variables only inside Postgres functions. See https://docs.hasura.io/1.0/graphql/manual/schema/custom-functions.html#accessing-hasura-session-variables-in-custom-functions . Let us know if this helps.

ElixirMike commented 4 years ago

Sure, I've posted a separate thread on this, but will restate here. The way Hasura permissions works is problematic for my use-case, which allows users to dynamically define their tables. When adding a field to a table, the only current solution for permissions is to totally delete/remove permissions from the table, and then re-apply all permissions again. This is a very heavy transaction and very slow. And it happens on every field add/delete to a table.

I'm looking for work-around solution and was hoping that I could use Postgres Row level security for my permissions....but this requires I have access to the sessions variable so I can define the appropriate RLS policies. This is how permissions work with a similar solution to Hasura called PostGREST . But it does not look like that's supported here..

ultimately I'm just trying to find a performant solution for implementing permissions in my solution.

ecthiender commented 4 years ago

@ElixirMike Got it. Thanks for the reply!

I can see the other thread you mention here: https://github.com/hasura/graphql-engine/issues/2104#issuecomment-585758423

As you have guessed, currently, there is no support. But we will look into this and get back to you.

shahidhk commented 4 years ago

@ElixirMike I am not sure if I understand your use case completely, but I can point to some notes that could help.

For mutations, which are executed in a transaction, current_setting('hasura.user') will give you the session variables. For example, if you want to access the user id, you can do current_setting('hasura.user')->>'x-hasura-user-id' (see more at https://docs.hasura.io/1.0/graphql/manual/guides/auditing-tables.html#auditing-actions-on-tables-in-postgres)

For queries, using custom functions, they can be used as described in this page: https://docs.hasura.io/1.0/graphql/manual/schema/custom-functions.html#accessing-hasura-session-variables-in-custom-functions

Let me know if any of this helps.

marionschleifer commented 4 years ago

@ElixirMike just checking in if your problem is solved? 🙂

m4dc4p commented 4 years ago

@shahidhk I'd really like that current_setting thing to work with SELECTs as well. In my use case, postgres is accessed through multiple paths, and Hasura is only one of them. For my REST API, I'm passing authentication through to postgres via local session variables. With Hasura, I'd essentially like to forward the JWT received to postgres. Looks like that happens with mutations but not queries. (My REST approach was actually inspired by this Hasura pattern, but I didn't realize it only did it with mutations.)

m4dc4p commented 4 years ago

@marionschleifer @shahidhk I was able to use custom functions and track_function v2 to pass session information from Hasura to Postgres outside a mutation (awesome!!!). I do lose the ability to construct arbitrary GraphQL queries over my tracked tables (not awesome).

Is there any way I can help make this a priority feature? Would you accept a PR for it?

tirumaraiselvan commented 4 years ago

Another use-case

extract the "sub" value from our JWTs and use that to enforce tenant separation

ghost commented 4 years ago

I was also looking into this for my permissions system.

For exemple, I have a case where a user may have many roles (x-hasura-allowed-roles), each of which may give access to different ressources of a reservation system. I would like to expose a custom function that takes the JWT claims as a parameter to return ressource specific access. This way I can easily retrieve and present to a user the informations / operations to which they have access with their given roles.

Gintasz commented 4 weeks ago

Passing session variables to SELECT queries would be very useful... Is this made on purpose, so that Hasura users would be incentivized to use Hasura's RBAC feature instead of working with native postgresql RLS?