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
momoneko
momoneko3mo ago
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.
No description
sebastian
sebastian3mo ago
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 customise
SheldonFromBBT
SheldonFromBBTOP3mo ago
But 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
momoneko
momoneko3mo ago
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.
SheldonFromBBT
SheldonFromBBTOP3mo ago
Okay I'll try doing this and will update here
momoneko
momoneko3mo ago
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.
momoneko
momoneko3mo ago
also, don't forget to set advanced.cookies.domain to foo.abc, otherwise the cookie will work only for auth.foo.abc
SheldonFromBBT
SheldonFromBBTOP3mo ago
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
momoneko
momoneko3mo ago
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
SheldonFromBBT
SheldonFromBBTOP3mo ago
Okay, thanks for this info So setting up separate servers on same domain (subdomain) , is the only actual solution here?
momoneko
momoneko3mo ago
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.
SheldonFromBBT
SheldonFromBBTOP3mo ago
Yes, there must be another way, anyways thanks for the help, I'll update here If I come across any workaround or solution.
sebastian
sebastian3mo ago
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
defaultCookieAttributes: {
sameSite: "none",
httpOnly : true,
secure: false, // you can try changing this to see if true works in prod
}
defaultCookieAttributes: {
sameSite: "none",
httpOnly : true,
secure: false, // you can try changing this to see if true works in prod
}
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 difference
stormej
stormej3mo ago
I too have a similar issue
SheldonFromBBT
SheldonFromBBTOP3mo ago
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
sebastian
sebastian3mo ago
No It's documented that it's way better to use a subdomain instead
momoneko
momoneko3mo ago
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 domain
Seems 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 😄
SheldonFromBBT
SheldonFromBBTOP3mo ago
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
Mayur
Mayur3mo ago
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

Did you find this page helpful?