Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improving the flow of handling sessions for better clarity due to RLS issues #915

Open
Mamdouh66 opened this issue Aug 30, 2024 · 1 comment

Comments

@Mamdouh66
Copy link

A new refactor? or a way to handle sessions

Describe the chore

I a normal flow (just following the docs (python api reference)) to insert some data into a table called X would kinda look like this

  1. A user would init a client
from supabase.client import AsyncClient, create_async_client

client = await create_async_client(
    settings.SUPABASE_PROJECT_URL, settings.SUPABASE_API_KEY
)
  1. Get the user
access_token = "getting-it-from-the-frontend"
user = await client.auth.get_user(jwt=access_token)
  1. inserting data into table X
response = await client.table("X").insert(data, returning="minimal").execute()

Now, if the developer has implemented RLS such as enabling insert for users based on user_id and them being authenticated
we would get this kind of error

postgrest.exceptions.APIError: {'code': '42501', 'details': None, 'hint': None, 'message': 'new row violates row-level security policy for table "X"'}

Now the main reason for that upon further investigations, is what happens in our RLS policy which looks like this

alter policy "Enable insert for users based on user_id"


on "public"."X"


to public


with check (

7
  (( SELECT auth.uid() AS uid) = user_id)

);

and what happens when inserting, kinda like the following

postgrest.exceptions.APIError: {'code': '42501', 'details': None, 'hint': None, 'message': 'new row violates row-level security policy for table "X"'}

Now the main reason for that upon further investigations, is what happens in our RLS policy which looks like this

alter policy "Enable insert for users based on user_id"


on "public"."X"


to public


with check (

7
  (( Null ) = "some-user-id"

);

now it auth.uid() happens to be null because when inserting and calling the db api the information of the user is not sent or the session idk.

now there are a hacky ways to solve it and a (right) way.

  1. is by using the set_session function.
    This function would require you to set both the access_token and refresh_token but this didn't make sense to make me to send them both from the frontend due to security purposes

  2. Using the secret key to bypass RLS policy.
    Still doesn't make sense due to security purposes.

  3. A problem with the get_session function is that it doesn't take any param and so it wouldn't give us the user's session to solve the problem

  4. the Right way is to use ClientOptions

client = await create_async_client(
    settings.SUPABASE_PROJECT_URL,
    settings.SUPABASE_API_KEY,
    options=ClientOptions(headers={"Authorization": f"Bearer {access_token}"}),
)

and the problem would go away and it would work normally, although the get_session still wouldn't work properly.

So, what is the problem.

That this problem is not well documented in the docs from a python perspective and one has to delve deep to find the proper solution.

Second, is that the get_session function would be more proper if it can take an access_token or an id or whatever to get the same session we have. it would save so much hassle and the use would make more sense.

After all, thanks for the team for their hard work maintaining this project

@silentworks
Copy link
Contributor

This is how row level security (RLS) works and the docs shows that you need to be meeting the requirements of the RLS policy if you want to do something on that table. This is a general documentation issue and not specific to the Python library.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants