How to use Supabase RLS with third-party client library? - postgresql

I'm using Supabase as my database, with RLS turned on. I query the DB from a Node backend using the postgres.js client (it could be any other JS client really). As such I'm connecting direct with the default postgres user and I issue raw SQL queries.
How can I query my DB while still maskerading as a user from Supa's auth.users table? I have triggers and RLS policies that take advantage of the current logged-in user, via Supa's auth.uid() function.
All I can find online is that I must set the current_user_id postgres setting to the current Supabase user, but I don't grasp the implications of that, from a functional and security perspective. I wouldn't want to leak the current user to another session.

Related

How to setup row level access in Postgres without creating a user

I have an existing API connected to an AWS PostgreSQL database that uses AWS Cognito for User authentication.
The goal is for users to insert data via the API with some field mapped to their Cognito id, and retrieve the same data. The idea would be for each user to only have access to the data 'owned' by them. Similarly to the way row level access works.
But I do not want to create a role for each user which seems to be necessary.
The idea would be that I need to somehow setup a connection to the PostgreSQL DB with the user_id without creating a user and handle the accessible data via a policy, or somehow pass the data to the policy directly.
What would be an ideal way to do this, or is creating a PG user for each user a necessity for this setup?
Thanks in advance
EDIT: I am currently querying the database through my backend with custom code. But I would rather have a system where instead of writing the code myself, the PostgreSQL system handles the security itself using policies(or something similar). I fully understand how PostgreSQL row-level-access works with roles and policies and I would prefer a system where PostgreSQL does the major work without me implementing custom back-end logic and preferably not creating thousands of PostgreSQL roles for the users.
You should not allow users to make a direct connection to the database.
Instead, they should make requests to your back-end, where you have business logic that determines what each user is permitted to access. Your back-end then makes the appropriate calls to the database and returns the response to the user.
This is a much 'safer' response because it prevents users having direct access to your database and it is also a better architecture because it allows you to swap-out the database engine for another one without impacting your service.
The database is for your application, not for your users.

How to integrate Postgres RLS into backend server

I'm trying to understand backends more and using row level security seems to be great idea to simplify backend code and increase security. I struggle to understand how to make RLS work. Let's say i have the following policy
CREATE POLICY user_mod_account ON accounts USING (username = current_user)
How does it know who is 'current_user'. I've followed few tutorials for making backend servers and if i'm not mistaken the way auth works is that you have some middleware that is in charge of authentication (usually by making additional requests against db to check if session exists and is valid), but all operations on the database are performed by backend which logs in as one user.
Let's say I have two tables - user, post and post has foreign key 'author' relating to 'username' in user table. Is it possible to have the following query on backend
SELECT * FROM post
and have it protected by RLS so the data is protected by the database itself (and have it return only posts from the user that backend is making request for)? If i connect to db as 'postgres' user, is 'current_user' postgres, or is there a way to make requests from backend as selected user. Maybe it's not the purpose of RLS, i would be glad if you could point me to some sources that could help me understand database <-> backend relation better. I feel like it is not really that complicated and my brain just didn't 'click' yet :P

Designing a Multi-tenant SAAS Database with Postgres RLS

I want to design a multi-tenant SAAS database with PostgreSQL and RLS. I want to be able to host all users and the tenants in the same database and isolate their data with RLS.
In my use case it makes sense for tenants to share a certain user data to avoid duplication of those data. The tenants will request a permission from users and these permissions are stored in a permissions table and these permissions are used to control the RLS.
However, I need tenants to have user data that's unique to their organization such as join date or other data. What I need to know is how I can design the database to hold all the organization specific data. I have thought of using JSONB to store this data like
user_data_for_tenant
id
user_id
tenant_id
data JSONB
this data is decided by the tenant from the front-end.
Is this okay? How better can I design the database to fit this use case?
I will be using Supabase for DB, Auth, Storage and other uses so the RLS can control access.
I would like to suggest the following design for the data management for permissions (AKA User Entity Permissions)
We can have a table that has the tenant users that are mapped to each entity in your SaaS Application. There will be permissions like Permission-C meaning Permission Create, so on for update, delete and read.
The tenant admin's can configure the access level for each of the users in their tenant based on the roles and we can internally use these roles to manage the policies in the Postgresql so that the queries are working fine based on the tenant level restrictions.
In case of having record level security, we can have all the ID's that can be accessed like below against each of the CRUD operation in the database.
The problem with the below approach is that as the data grows should the column grow, or you have a flat mapping of the IDS and the permissions. There are options to finetune this if the approach is suitable for your requirement.

Which postgres system table stores a map of PIDs to session authorizations?

I want to look further into the PIDs listed in pg_stat_activity to know what their last succesful call to SET SESSION AUTHORIZATION set their session authorization to. Which table or view do I need on PostgreSQL 9.0?
PostgreSQL doesn't expose that information, at least in 9.4 or any prior version.
The user id in pg_stat_activity is the login user; it's the user that RESET SESSION AUTHORIZATION goes back to. It won't change when you SET SESSION AUTHORIZATION or SET ROLE.
Information about the current effective session authorization and current role are internal to the backend. You can access them locally to the backend with SELECT current_user, current_role, etc, but there's no inter-process way to get at them.
It might be nice to have that, if it could be added without making it more expensive to maintain pg_stat_activity or to query it. You'd need to get into PostgreSQL's guts and develop a patch to expose the information, though.
Surprisingly, log_line_prefix doesn't seem to include format symbols to show the effective role and effective session user. Given the use of session authorization by PgBouncer that's sufficiently odd that I feel like I must have missed something.
In any case, the only way I see to do this is to dig through the logs, logging pid and session ID then associating successful SET SESSION AUTHORIZATION calls with subsequent statements.

How to Obtain Domain User Name when connecting via SQL Authentication

I have an application which connects to SQL Server 2000 (using a generic SQL Login and SQL Authentication). I would like to implement some logging via triggers to track data changes. I can't use USER_NAME() because that returns the generic account.
I've poked through master..sysprocesses and it doesn't seem to record the username (although it does record the machine name).
Any ideas how, within SQL, to gain access to the username?
(Note: yes, I could pass it in as a variable via the application ... but that would mean I'd have to roll out a new version of the app; I'm trying to do this from within SQL, so I can avoid that, if possible.)
You can't. Simple. SQL Server has no knowledge of the end user with a SQL login at all
The same applies if you use a proxy (web server etc) too: you don't know the end user. We use parameters/stored procs to pass in the username from the web server.
I would suggest that you set CONTEXT_INFO in the client which persists for that connection.
Have you tried SYSTEM_USER?
SELECT SYSTEM_USER