Better Auth, Start and protected routes
Hey 👋 I'm setting up authentication with Better Auth and TanStack Start. I’ve got it working, but the solution feels messy, lots of duplicated code.
Does anyone have a clean example or template to share? Ideally with good practices like global middleware for protected routes and user object available via context, etc.
24 Replies
absent-sapphire•2mo ago
GitHub
GitHub - notKamui/miniverso: Self-hostable grouping of mini web app...
Self-hostable grouping of mini web applications for everyday use - notKamui/miniverso
absent-sapphire•2mo ago
mind you, i also utilize daveyplate's libs to help
"@daveyplate/better-auth-tanstack": "^1.3.6",
"@daveyplate/better-auth-ui": "^2.0.12",
don’t hesitate if you need help
extended-salmon•2mo ago
This is excellent 👌🏽
absent-sapphire•2mo ago
thank you very much !
just curious, what did you find particularly good ? the auth implementation ?
or the codebase in general ?
extended-salmon•2mo ago
The code base in general. I am putting together my own base and we follow similar patterns. better auth, drizzle, shad etc. The organisation looks really clean to me and has given me some ideas on cleaning up my own structure. One deviation is that I want to be authed by default. So every server action should be explicitly marked as anonymous. Too many times in the past I've come across an api endpoint that should be authed but wasn't because it was forgotten about. Which is why I am struggling a bit with global middleware not working as I want. I posted a question on your repo about how you got global middleware working. You seem to import it in multiple places but this would be an issue with me going auth first. Ie if global middleware doesnt get registered properly then poitentiall every endpoint with be not protected 😮
absent-sapphire•2mo ago
thank you so much for the great compliments, i’ll answer your question here: yes
for now we have to import it somewhere
however, people seem to have made it work by importing in router.tsx and server.tsx only
i have not tried it yet, however this seems to be the way
in any case, it is NOT how they want this to work
it’s not a priority, but i know they want the global middleware to just work
« they » being the tanstack team
and you know what, i also contemplated going authed by default, and this actually was the reason i didn’t go for it for now
extended-salmon•2mo ago
I'll do a bit more digging and let you know if I find anything out but I think you are way ahead of me here lol
foreign-sapphireOP•2mo ago
sorry to ask, but just trying to understand "high level" approach, for basic setup, so I only want for user to be able to navigate to some routes (pages) if it's authenticated, otherwise redirect him to e.g. /login?
btw if I have all me authenticated pages under
/app/...
routes, is there a best practice to easily achieve it?absent-sapphire•2mo ago
have a
src/routes/app.tsx
file, and in the beforeLoad you check if the user is authenticated, and if not -> redirect to login, and the rendered components is just <Outlet/>
with that, every subroute of /app/* will have that behavior
if you then want an actual route for /app, you can create src/routes/app/index.tsx
app.tsx effectively becomes a layout route
@markoforeign-sapphireOP•2mo ago
File: src/routes/app/index.tsx
thanks I have done it like this, but still not sure what I'm missing since it doesn't work, for example I can still navigate to
/app/dashboard
as logged out 🤔absent-sapphire•2mo ago
because /app/dashboard is not a subroute of /app/(index)
you didn't do exactly as told
this should be app.tsx, not app/index.tsx
also you dont need (and shouldnt) type the loader params
TS Router is already typesafe
foreign-sapphireOP•2mo ago
this should be app.tsx, not app/index.tsxhm but I'm having folder based structure, shouldnt this be the same 🤔
absent-sapphire•2mo ago
no
app/index.tsx is the same as app.index.tsx
and neither of them is the same as app.tsx
app.index.tsx is to explicitely opt out of subroutes
in other words, app.index.tsx can never have any subroute
so app.dashboard.tsx will never be a subroute of app.index.tsx
however, both app.dashboard.tsx and app.index.tsx ARE subroutes of app.tsx
you can replace the dots (.) with slashes (/), it's the same thing
foreign-sapphireOP•2mo ago
hm but I'm using folder
absent-sapphire•2mo ago
you dont understand
foreign-sapphireOP•2mo ago
oh I named it route.tsx seems to work
absent-sapphire•2mo ago
because
app/route.tsx is the same as app.tsx
which is different from app/index.tsx or app.index.tsx
i think you should read the docs
because i feel you still dont understand the nuance
because this has NOTHING to do with the issue at hand
but you keep repeating
foreign-sapphireOP•2mo ago
I see thanks!
hm how could I get the user in this subroute 🤔
do I need to define a loader again 🤔
absent-sapphire•2mo ago
no, just put the redirection logic in the beforeLoad of app.tsx or app/route.tsx
foreign-sapphireOP•2mo ago
hm you mean like this, its still doesnt infer user in child routes, when trying to acces it
optimistic-gold•2mo ago
Are you wanting access to
user
in all route context? If so, you should return the user from your __root
file's loader
That should be using the createRootRouteWithContext
function, rather than your standard createFileRoute
.
This will populate context.user
in your routesforeign-sapphireOP•2mo ago
thanks, I added
but I also realized that if I want
User
available on all /app/*
routes (user is not null), I need to add this
File: src/routes/app/route.tsx
And this is how I finnaly access the user on protected route
not sure if there is a better wayoptimistic-gold•2mo ago
That works! I am doing it similar to this, but instead of a route.tsx file, I use pathless layout files. Both solutions are fine
foreign-sapphireOP•2mo ago
btw I tried implementation like this in _root.tsx
but got some strange/buggy behavior with better auth and invalid tokens, if I tried to login and logout many times consequently, so just using now same as you posted 👍