Neon Authorize + Better Auth JWT + Drizzle + Row Level Security

has anyone managed to set this up? (or something similar) The Neon Authorize docs don't have an "official" guide for how we can use better-auth :( i just started using better-auth today, so i'm new to this library! i would really appreciate advice on how to implement this/a barebones template if there is one. thank you!
Neon
About Neon RLS Authorize - Neon Docs
JSON Web Tokens (JWT) Row level Security (RLS) How Neon RLS Authorize works Neon RLS Authorize Tutorial Postgres Row Level Security tutorial Simplify RLS with Drizzle Neon RLS Authorize integrates wit...
17 Replies
lonelyplanet
lonelyplanet7d ago
Interesting didnt know about Neon RLS but from a quick skim looks like you need JWTs better auth does support this see https://www.better-auth.com/docs/plugins/jwt
JWT | Better Auth
Authenticate users with JWT tokens in services that can't use the session
lonelyplanet
lonelyplanet7d ago
I believe for getting JWT serverside you could do:
const res = await auth.api.token({
headers: {} // instead of doing {} you would pass in your request headers for example in nextjs headers:await headers()
})

const token = res.token;
if(!token) {
console.log("token could not be requested");
} else {
// do what you want with token
}
const res = await auth.api.token({
headers: {} // instead of doing {} you would pass in your request headers for example in nextjs headers:await headers()
})

const token = res.token;
if(!token) {
console.log("token could not be requested");
} else {
// do what you want with token
}
export async function insertTodo(newTodo: { newTodo: string; userId: string }) {
// instead of doing {} you would pass in your request headers for example in nextjs headers:await headers()
const headersList = {};

//get the current user session
const session = await auth.api.getSession({
headers: headersList,
});

// ensure use is authed
if (!session) throw new Error('Not authenticated');

// get userid from session
const { userId } = session

// get the jwt token from the api
const res = await auth.api.token({
headers: headersList,
});
const token = res.token;

// ensure token was recieved
if (!token) throw new Error('Error getting token');

// User mismatch
if (newTodo.userId !== userId) throw new Error('Unauthorized');

const db = drizzle(process.env.DATABASE_AUTHENTICATED_URL!, { schema });
return db.$withAuth(authToken).insert(schema.todos).values({
task: newTodo.newTodo,
isComplete: false,
userId, // Explicitly ties todo to the user
});
}
export async function insertTodo(newTodo: { newTodo: string; userId: string }) {
// instead of doing {} you would pass in your request headers for example in nextjs headers:await headers()
const headersList = {};

//get the current user session
const session = await auth.api.getSession({
headers: headersList,
});

// ensure use is authed
if (!session) throw new Error('Not authenticated');

// get userid from session
const { userId } = session

// get the jwt token from the api
const res = await auth.api.token({
headers: headersList,
});
const token = res.token;

// ensure token was recieved
if (!token) throw new Error('Error getting token');

// User mismatch
if (newTodo.userId !== userId) throw new Error('Unauthorized');

const db = drizzle(process.env.DATABASE_AUTHENTICATED_URL!, { schema });
return db.$withAuth(authToken).insert(schema.todos).values({
task: newTodo.newTodo,
isComplete: false,
userId, // Explicitly ties todo to the user
});
}
I tried adapting the example from the article. I have no idea if that works havent tested it but i think thats how you could do it
daveycodez
daveycodez6d ago
Hey I use this use my better-auth-tanstack library for the useToken hook
daveycodez
daveycodez6d ago
GitHub
GitHub - daveyplate/better-auth-tanstack
Contribute to daveyplate/better-auth-tanstack development by creating an account on GitHub.
daveycodez
daveycodez6d ago
https://github.com/daveyplate/neon-drizzle-tanstack These are my Tanstack hooks to use Neon Drizzle from front end
GitHub
GitHub - daveyplate/neon-drizzle-tanstack: Use Drizzle from the fro...
Use Drizzle from the front end using Tanstack Query hooks, secured with Neon RLS - daveyplate/neon-drizzle-tanstack
daveycodez
daveycodez6d ago
I'll have in depth walkthroughs and guides soon enough better-auth 1.2 is coming with a new JWT plugin for better ways to sign with 0 latency via api I'm running my tanstack hooks through my custom proxy middleware that simply uses vercel firewall for rate limiting But I have 0 API for data requests, it's all just drizzle from React directly useFindMany just wraps Drizzle findMany into a React hook fully typesafe based on Drizzle schema This way I don't have any serverless invocations for any of my data requests and don't have to pay Vercel for any bandwidth for data either, just middleware and WAF
lonelyplanet
lonelyplanet6d ago
@daveycodez Your packages can do Neon RLS?
daveycodez
daveycodez6d ago
That's what I'm using them for Neon RLS through client side react hooks Using JWT from better-auth jwt plugin ES256
lonelyplanet
lonelyplanet6d ago
Thats cool
daveycodez
daveycodez6d ago
https://newtech.dev I implemented the Books and Todos examples from Neon docs but with better-auth
vz
vz2d ago
do you have link to the github repo?
daveycodez
daveycodez2d ago
I'm working on better-auth-ui right now that repo isn't exactly ready for the site itself, but to use neon-drizzle-tanstack library it's pretty simple you just wrap your app/layout in a NeonQueryProvider
<NeonQueryProvider
db={getDb("authenticated")}
fetchEndpoint={`${getURL()}/api/sql`} // optional endpoint for custom proxy
mutateInvalidate={true}
optimisticMutate={true}
token={token}
>{children}</NeonQueryProvider>
<NeonQueryProvider
db={getDb("authenticated")}
fetchEndpoint={`${getURL()}/api/sql`} // optional endpoint for custom proxy
mutateInvalidate={true}
optimisticMutate={true}
token={token}
>{children}</NeonQueryProvider>
Token comes from useToken hook from better-auth-tanstack
daveycodez
daveycodez2d ago
You add this file to create all the Tanstack hooks with type inference from your DB schema so you can just do something like const { data } = useFindMany("books") I'll have a lot more to share soon but yea I'm working a lot on better-auth-ui right now with new support for all the better-auth 1.2 features as well
daveycodez
daveycodez2d ago
I'm working on full Fumadocs sites for both packages, hopefully ready soon
vz
vz2d ago
Thank you!!

Did you find this page helpful?