Auth not working across completely different domains (app)
I'm trying to set up authentication where users log in on one domain and use the app on another completely different domain (think
auth-service.com
and my-app.io
- totally unrelated domains).
My setup:
- Auth server on a.xyz
- Main app on foo.abc
- Both use the same Turso database and identical Better-Auth configs
- Same session table, same cookie names, everything
What happens:
1. User logs in on auth server → works fine, session created in database
2. Auth server sends session token back to main app
3. Main app sets the token as a cookie on its domain
4. When I call getSession()
on the main app → returns null every time
I can see the session in the database and the cookie is set correctly, but Better-Auth just won't recognize it.
My question: Does Better-Auth tie sessions to the domain where they were created? Even with a shared database, will a session created on a.xyz
never work on foo.abc
?
I'm using SvelteKit + Better-Auth + Drizzle + Turso. Has anyone got this working with completely different domains?
All other config are normal or same as installation docs.
I may be missing something very obvious here, help would be really appreciated
Thanks!19 Replies
The issue is that you can't set a cookie for a different domain. The browser refuses cookies that don't match the domain where they're comming from or from a higher level domain.
In theory, you could set the
advanced.cookies.domain
to foo.abc
, but even then, the browser will refuse to set the cookies.
E.g. the screenshot shows what I get when I try to sed the domain to httpbin.org
What you can do is to get your auth server on a subdomain (e.g. auth.foo.abc
) and set the domain
to foo.abc
.
The cookies are not send between different domains because its not secure and generally avoided. However, you can bypass that by using cookie attribiutes that comes with security risks.
https://www.better-auth.com/docs/reference/options#advanced
Here you can use options like use secure cookies and disable csrf check that will allow you to send between domains, i think that you also need to customise to cookie to have
SameSite
set to none property which you can also customiseBut while setting the cookie which is a better auth session token, returned by the auth server app, we don't get to set this option, in sveltekit you set normally as you would, do you mean that the token generated by better auth on auth server (app), when returned to different domain app, gets invalidated or useless? Is this a better auth specific behaviour or cookies in general?
Is the session token tied to a origin or domain it was created? such that when better auth client on other domain validates it, it fails and return null?
I am doing this because of a very specific issue of cpu time limits on cloudflare workers, due to that I thought of a workaround of hosting the auth server on vercel and main app on cloudflare, while I may upgrade to paid plans or higher limits in future, I want to have a solution or workaround for now, I am doing this first time i.e the different or separate server for auth and main app.
This doesn't seem to work, it only specifies for subdomain apps and not totally different TLD or domains
This is a cookie behavior in general; you can't set cookies for
google.com
from facebook.com
and viceversa (or a.xyz
from foo.abc
) ; but you can set cookies for app.foo.abc
from auth.foo.abc
I don't remember if Cloudflare offers this for the free plan or not (not using Cloudflare at the moment), but you can set a DNS CNAME record for auth.foo.abc
to point to a.xyz
and disable proxy, so that the traffic doesn't pass through Cloudflare and cost you money.
This way, requests to auth.foo.abc
will hit the vercel server directly and you'll be able to set the token.Okay I'll try doing this and will update here
Here's some docs to help you out https://developers.cloudflare.com/dns/proxy-status/#dns-only-records
Cloudflare Docs
Proxy status
While your DNS records make your website or application available to visitors and other web services, the Proxy status of a DNS record defines how Cloudflare treats incoming DNS queries for that record.
also, don't forget to set
advanced.cookies.domain
to foo.abc
, otherwise the cookie will work only for auth.foo.abc
I had one doubt that, does better auth while validating the session (with getSession()) also inherently validates the domain it was set or created on?
with the session token
it doesn't; the browser doesn't send contain domain data with the cookie - and from what I'm seeing, BA doesn't add any info in the cookie itself.
It does add a signature (the part after the dot), so it will check that the cookie was created by the same server that validates it
Okay, thanks for this info
So setting up separate servers on same domain (subdomain) , is the only actual solution here?
That'd be the easiest, yea
You can look into using Bearer tokens, but that opens up a totally separate can of worms; at the very least you'll need to figure out a way of storing the token, then you need to set up CORS for your particular setup, then all API requests may or may not need to be changed (I'm actually not familiar with BA on the frontend 😅 ).
If I had the option, I'd go the subdomain route. But I think it's worth knowing that there's another option.
Yes, there must be another way, anyways thanks for the help, I'll update here If I come across any workaround or solution.
haev you tried making the cookie have samesite set to none attribiute? the docs are bit unclear but i believe it's tottally possible withouit using subdomains
i mean the cookie attribiutes in you auth config
I mean this under advanced, if you're using backend then update cors to handle your domain also.
Also, i would recommend trying anything in incognito, as browser likes to cache everything
also, options like
disableCSRFCheck
in your auth config also may make a differenceI too have a similar issue
I'll try doing this
Would it be appropriate to tag and ask for clarity or help from bekacru?
This issue seems to have unclear solutions and documentation, should be not this hard to resolve or atleast debug
No
It's documented that it's way better to use a subdomain instead
This is hard by design, specifically browser design
if it weren't, any website would be able to set any cookie for any other website, opening new avenues for DoS and data injection
There actually are options to do it, but it becomes messy real quick, and may have unintended consequences down the road
Some of things i know for sure work
- you can do a double redirect, passing the cookie via a query param as described in https://stackoverflow.com/a/12370586; not really safe, cause the cookie value will be left in the browser history
- you can make use of
postMessage
, as suggested by another answer to the same question - https://stackoverflow.com/a/22935156
- you could make a fetch request to foo.abc
, passing the cookie in the body or headers, and the foo.abc
could do a Set-Cookie
; but then you need to figure out all the CORS needed for this
In either case, you can't make your cookie HttpOnly
, as JS needs to be able to access it in order to populate the params. But this makes you vulnerable to XSS
The OP of the question above actually wrote another, pretty comprehensive answer detailing the approaches above - https://stackoverflow.com/a/73599289; just reading through that should tell you how messy the approaches are.
If you decide to go through with any of them, good luck, and have fun 🙂
@SheldonFromBBT, I just took a look at your qustion once again, and steps 2 and 3 kinda bug me
2. Auth server sends session token back to main app 3. Main app sets the token as a cookie on its domainSeems like you actually figured out a way of sharing the cookie between the apps. How does this happen? And if that's the case, does your token look like example 1 or 2? 1.
rxuUpeKEyQPbVPMimw9Ib1vBxLcobHkw
2. rxuUpeKEyQPbVPMimw9Ib1vBxLcobHkw.bkVHMxIs9jukr7U9tyaMZtmEp4oSTShi%2FqyTPT2VNp8%3D
If it's like in the first example, it won't work - the actual cookie also includes a signature. You can see it after the .
in the second example.
I assume you're parsing the signInEmail
response and grabbing the token from there. You'll need to parse the headers of the response, and grab the cookie from the Set-Cookie
response header. You'll need to add returnHeaders
to the call to signInEmail
If the above didn't make sense, then all my assumptions were wrong and we'll need more details about your setup 😄Yes, it's almost same
I do get the session token in this format: <>.<>, as you said
The thing is this flow or logic does work for same domain or app, just not for different domain apps
I do get the session token and upon setting it as the cookie, I do get signed in as expected
Everything went over my head when I applied this for different apps 🥲
And yes its url decoded as expected
Im facing the same issue, now i have placed my auth and my app as 2 subdomians under a same domain and it worked . But what if i want a mobile app to use my same Auth Backend . How can i solve this . Im using Honojs , Better Auth , google oauth with mongodb deployed on cloudflare workers