integrating with postgres rls (supabase)

hi. i'm trying to migrate off of supabase auth so i wanted to go with better-auth. my question is, how could i correctly use the JWT integration to setup RLS auth? do i need to always fetch the endpoint to get the JWT token, or could i get it auto-provided every time? that would be much simpler for setup i need to setup RLS for maybe two days with supabase and then i'm migrating to neon (want auth and db to be staggered, don't want a big screwup to hit all at once)
25 Replies
bekacru
bekacru3mo ago
@daveycodez might help but check the jwks plugin https://www.better-auth.com/docs/plugins/jwt
JWT | Better Auth
Authenticate users with JWT tokens in services that can't use the session
oof2win2
oof2win2OP3mo ago
yeah i saw that plugin + the usage davey has (https://discord.com/channels/1288403910284935179/1296058482289676320/1337526387967266847), just wondering how to set it up what complicates it more i feel is me migrating auth and then db - it makes sense to do like this but makes some parts more annoying / painful
daveycodez
daveycodez3mo ago
The best way atm is to use the Tanstack library
daveycodez
daveycodez3mo ago
GitHub
GitHub - daveyplate/better-auth-tanstack
Contribute to daveyplate/better-auth-tanstack development by creating an account on GitHub.
daveycodez
daveycodez3mo ago
This provides the useToken hook
oof2win2
oof2win2OP3mo ago
hell yeah, thank you hey @daveycodez, do you by chance have any knowledge on how to get supabase working with better-auth? i've looked at your package, but i have no idea how to get supabase to cooperate with the better-auth tokens - do you know how by chance? i have this so far
import { Database } from "@repo/types/supabase";
import { createBrowserClient } from "@supabase/ssr";
import { useToken } from "./use-auth-hooks";

export function useSupabase() {
const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL!;
const supabaseAnonKey = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!;

const { token } = useToken();

if (!supabaseUrl || !supabaseAnonKey) {
throw new Error("Missing Supabase environment variables");
}

const supabase = createBrowserClient<Database>(supabaseUrl, supabaseAnonKey, {
accessToken: token || "",
});

return supabase;
}
import { Database } from "@repo/types/supabase";
import { createBrowserClient } from "@supabase/ssr";
import { useToken } from "./use-auth-hooks";

export function useSupabase() {
const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL!;
const supabaseAnonKey = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!;

const { token } = useToken();

if (!supabaseUrl || !supabaseAnonKey) {
throw new Error("Missing Supabase environment variables");
}

const supabase = createBrowserClient<Database>(supabaseUrl, supabaseAnonKey, {
accessToken: token || "",
});

return supabase;
}
turns out i just had to forge my auth token on an api route and put some cache headers on it, kinda sick tbh
daveycodez
daveycodez3mo ago
Got it to work? great One day I would suggest to migrate to Neon and implement a rate limiter, Supabase can be a lil riskay
oof2win2
oof2win2OP3mo ago
yeah i know that's the next step - just need to setup proper auth so that i can migrate off supabase part by part @daveycodez i've been looking more and more into this, saw the issue here and convos in discord. how would you ideally have the jwt support work? like it's just stored in the session or something so it can be used on both the client and server in the ideal case, and can be revalidated every 5m or something
daveycodez
daveycodez3mo ago
I'm hoping we can get an update where the JWT plugin simply adds "token" to sessionData so you have sessionData.session, sessionData.user, and sessionData.token It can simply be synchronized with the session and signed every time you get a session, since it's 0ms latency to sign a new one. So every session refresh has a new JWT as .token I might make my own plugin that does this in the future but my Tanstack solution is working for me in the meantime
XEDD
XEDD5w ago
Looking forward to this
daveycodez
daveycodez5w ago
I’m not gonna lie I’ve totally migrated to InstantDB and it’s awesome
XEDD
XEDD5w ago
Damn. No self hosted. Which is critical for me. (Heavy trafic)
XEDD
XEDD5w ago
With your tanstack have you achieved all niuanses of authorization? https://github.com/daveyplate/better-auth-tanstack
GitHub
GitHub - daveyplate/better-auth-tanstack
Contribute to daveyplate/better-auth-tanstack development by creating an account on GitHub.
daveycodez
daveycodez5w ago
there I just have the useToken hook which will get your JWT It will also refetch before it expires, and when session changes
XEDD
XEDD5w ago
Damn.
Lucas
Lucas5w ago
@XEDD let me know how that goes. I just got away from CLerk exactly because dealing with the JWT token was so annoying. Didnt wanna have to go through this again. May I ask why youre moving away from supabase for DB?
bekacru
bekacru5w ago
Could you gus let me know the issue exactly? also a heads-up - we're collbarinting soon with supabase to add direct integration
XEDD
XEDD4w ago
Basically. It's the JWT tokens you cant manipulate them force dissconnect and etc. i would be glad using Cookie based auth. For example i creating my own role system which has its own subrole . yes thats not very secure. But the RLS policies should fix it. but still it's kinda pain in the ass because. You cannot add your own [ 40+ ] roles still you have to use direct postgress. For permissions 🙂 RPC also for some functions. There is no ready steady variant currently for react based auth. Which kinda sucks. I hadnt theese problems with PHP and Mysql 🙂 @Lucas im not moving away i will just not use the InstantDB (overpriced). No self host option is pretty much dealbreaker for me. I will host my own supabase instance on dedicated server eventualy, i will launch geoblocked to my country Results system.
Lucas
Lucas4w ago
@XEDD as far as I know you cant manipulate the JWT but you can create and use a refresh token instead once the JWT expires but as I've understood @bekacru there's no easy way to sync Supabase RLS with the JWT token directly through Better Auth right now - it would require manual setup. Correct?
bekacru
bekacru4w ago
Yea it does. Honestly, I haven’t looked much into it. I should pretty soon in preparation for the direct integration.
daveycodez
daveycodez4w ago
I thought Instantdb was a good price lol. But I'm looking at Triplit now for reasons
oof2win2
oof2win2OP3w ago
hey @daveycodez, i'm looking at some code you wrote on neon-drizzle-tanstack and integrating RLS. i'm wondering how you get the anon and authenticated DB with neon correctly? i can't seem to get them working with rls at the same time per se, how do you get anonymous to work correctly? passwordless auth doesn't work there
daveycodez
daveycodez3w ago
I used a separate instance for auth. I’m on a call with Neon tomorrow to come up with the best solution and some good docs for better Auth For anonymous they recommended creating a separate db URL for anonymous and use that when not logged in This URL will accept a password, so you need to copy the password for the anonymous role so you'll have DATABASE_URL for admins, DATABASE_AUTHENTICATED_URL for authenticated users (no password) and DATABASE_ANONYMOUS_URL with anonymous user and anonymous pw Since you log in as anonymous to the anonymous URL, those queries will only go through if your RLS policies allow anonymous to read or write there The other option is to use the anonymous users plugin for Better Auth, since those are just users, and create one on page load, and then do a custom check for isAnonymous on that user's JWT
oof2win2
oof2win2OP2w ago
yeah fair enough, that's what i have setup right now. supabase had it in only one query (based on if the JWT was present or not) which was IMO better for this type of setup but we'll see
daveycodez
daveycodez2w ago
Other option is to manually sign a guest JWT and just pass that Maybe there's a better way but you probably want to ask in their channel

Did you find this page helpful?