Need to set NEXTAUTH_URL dynamically as an Option for multi-domain/multi-tenant use #9785
Replies: 156 comments 16 replies
-
Server has a Lines 47 to 50 in 12a5d6b JWT. GetToken can be custom though: Lines 94 to 103 in 8115a7c And, for the client: Lines 24 to 26 in 8115a7c These are the references I found. @iaincollins I can try to fork and attempt a hack on my side, since I really need to solve this. If you can advise how to go about it, it would be awesome. It seems you intend to refine/refactor this at some point, as stated above. Above three are the only references I found. Any help is really appreciated. |
Beta Was this translation helpful? Give feedback.
-
Okay, so I managed to fork and make server-side work! Looking into the client side now... I added to server: const { origin } = absoluteUrl(req)
// @todo refactor all existing references to site, baseUrl and basePath
const parsedUrl = parseUrl(process.env.NEXTAUTH_URL || origin || process.env.VERCEL_URL) and export const absoluteUrl = (req) => {
var protocol = "https:"
var host = req
? req.headers["x-forwarded-host"] || req.headers["host"]
: window.location.host
if (host.indexOf("localhost") > -1 || host.indexOf(".local") > -1) {
protocol = "http:"
}
return {
protocol: protocol,
host: host,
origin: protocol + "//" + host,
}
} |
Beta Was this translation helpful? Give feedback.
-
Hi Sharad, If you are seeing this error there is likely problem with your build process or how you are linking to the libraries. You'd need to post and link to the repo before we can help with that. Regarding the wider question of supporting domains dynamically, this is something we don't support currently. I don't have an update on this I'm ready to share right now, but I hope there will be an update on this at some point in the coming weeks. |
Beta Was this translation helpful? Give feedback.
-
Thanks Iain, yes I am trying to get my head around this. I also started my own Adapter, based on your prisma adapter... to support multi-tenancy in database. Pretty much everything you have as-is, plus associating users with a Business (tenant) record. Excellent work with next-auth. So helpful. |
Beta Was this translation helpful? Give feedback.
-
We really need this as well, as we have a multi-tenant Next app in the works. It seems like you could take in a callback function in the |
Beta Was this translation helpful? Give feedback.
-
Our application is multi-tenant as well. We also need(ed) this feature. |
Beta Was this translation helpful? Give feedback.
-
I also need this to be able to properly setup salesforce as a custom oAuth2 provider:
There are cases where the user will need to specify their "subdomain" in order to be able to login. |
Beta Was this translation helpful? Give feedback.
-
I've tried to address this here: skilesare@86ea3de It may need some changes....and I only really focused on the session call back because I needed to get some data based on the domain in the session, but the pattern should be easy to follow for the other callbacks. Basically the request (req) just needs to be passed to these callbacks so that you can key in on the domain/sub domain. The other potential gotcha is the http vs https so if anyone has a suggestion for that, let me know. If any one wants to walk me through how to get this set up so that it can eventually be pulled in, let me know as well...haven't contributed to projects this big before and don't want to step on any toes. |
Beta Was this translation helpful? Give feedback.
-
Our application is multi-tenant as well. We also need(ed) this feature. I would like to be able to simply set the redirect_url in the provider options |
Beta Was this translation helpful? Give feedback.
-
One good reason to think to support multi-tenant is that nex-auth is likely to be deployed on vercel. On vercel each deployment has several domains (a lot more if the user defined aliases). Since this is a project for next.js, supporting Vercel looks natural to me. |
Beta Was this translation helpful? Give feedback.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
-
To anyone reading this, please stop +1 issues, it is really not helpful, and creates noise. 😕 If you have nothing constructive to add, do click "👍" on the original comment instead. |
Beta Was this translation helpful? Give feedback.
-
Vercel published a multi-tenant |
Beta Was this translation helpful? Give feedback.
-
Same question on the v5 front, trying to accomplish this and the NextAuth default export no longer accepts the |
Beta Was this translation helpful? Give feedback.
-
Short Answer: It's not supported. Some devs may find a work around but if you don't know what you're doing then please look for an alternative option. I wasted a lot of time looking for it and, in the end, had to look for an alternative option. Clerk Auth supports it otherwise go for a custom auth solution. |
Beta Was this translation helpful? Give feedback.
-
i solve this issue by adding edit SessionProvider and add baseUrl and basePath (baseURL + '/api/auth') to get baseUrl you can use this code
|
Beta Was this translation helpful? Give feedback.
-
A solution for My requirement is to support multiple domains from one Nextjs build (thirteen different county domains). For each domain I need separate NextAuth Provider configuration because each domain will authenticate with different providers. For example, the configuration I will basis this on will look a little like:
As I have different domains I have not set the I dynamically generate the [...nextauth]/route.ts
I'm using Auth0 as the authentication Provider, this is the following Provider definition (reduced for brevity) returned dynamically:
Finally, I had to set
Any feedback or potential issues with this approach are appreciated! |
Beta Was this translation helpful? Give feedback.
-
I still don't understand how little support for this is given from Vercel. |
Beta Was this translation helpful? Give feedback.
-
We faced quite the same problem. Our project is hosted on several subdomains:
Authorization flow works perfectly fine on Step 1. Step 2.
There is a huge disadvantage to this approach. You cannot customize the handler itself. There is no function body where you can insert your own custom code. Therefore, we suggest rewriting the file as follows:
It works exactly the same while being more flexible. Every auth request goes through this 'middleware'. Here we're going to dynamically set the
Step 3.
The first
Step 4. After completing the previous steps, your authorization flow should work fine. If you're concerned about the rest of the code, you can follow these tutorials: part1 and part2. However, you may encounter a bug: when different users from different computers log in at the same time, their redirect URLs after successful login may get mixed up, and, as a result, users may end up in someone else's subdomain. Because of that users see Step 5.
Avoid using |
Beta Was this translation helpful? Give feedback.
-
I also use next auth, and I need each tenant to have its own separate authentication, in which a token issued in one tenant cannot be valid for another tenant, I also need the callback URLs to be dynamic, I managed to handle this by making the callback to add the tenant field in the token, and then I compare the token's tenant with the host in a middleware:
Extend Session and JWT:
Auth Middleware:
Middleware:
|
Beta Was this translation helpful? Give feedback.
-
Hey everybody, This works for me.
Full example:
Thanks, |
Beta Was this translation helpful? Give feedback.
-
Hey 👋🏻, if you're still struggling with this issue, here's an update :
I hope it fixes your issues. |
Beta Was this translation helpful? Give feedback.
-
You can use this ugly hack for v4 and maybe v5. const nextAuthHandler = NextAuth({
...
})
...
...
...
const hackedResponse = new Proxy(res, {
get(target, prop) {
if (prop === 'send') {
return (body) => {
debug(`* sending response`, { body })
if (typeof body === 'string') {
body = fixUrls(body)
} else {
body = JSON.parse(fixUrls(JSON.stringify(body)))
}
debug(`* fixed response`, { body })
return res.send(body)
}
} else if (prop === 'json') {
return (body) => {
debug(`* sending json response`, { body })
body = JSON.parse(fixUrls(JSON.stringify(body)))
debug(`* fixed response`, { body })
return res.json(body)
}
} else {
return Reflect.get(target, prop)
}
},
})
return nextAuthHandler(req, hackedResponse) The way it work is that we proxy the response object and correct the response urls using |
Beta Was this translation helpful? Give feedback.
-
can't we add an i.e. something like this: export function reqWithEnvURL(req: NextRequest, config?: NextAuthConfig): NextRequest {
const url = config?.baseUrl ?? process.env.AUTH_URL ?? process.env.NEXTAUTH_URL
if (!url) return req
const { origin: envOrigin } = new URL(url)
const { href, origin } = req.nextUrl
return new NextRequest(href.replace(origin, envOrigin), req)
} Then we can set it within our NextAuth implementation:
looks like a 5 line PR, or so. Happy to contribute if this makes sense. PS. for multitenancy or reverse proxied apps, what is currently in place is not enough. |
Beta Was this translation helpful? Give feedback.
-
We managed to get multi-tenant authentication working (version The missing piece seemed to be the
I'd be interested to know if this works for others, here's a simplified version of our auth config: import { headers } from 'next/headers';
import NextAuth from 'next-auth';
import type { OIDCConfig } from '@auth/core/providers';
export const {
handlers: { GET, POST },
auth,
} = NextAuth(() => {
const headersList = headers();
const protocol = headersList.get('x-forwarded-proto');
const host = headersList.get('host');
const url = protocol && host ? `${protocol}://${host}/api/auth` : null;
if (!url) {
console.error('Invalid request url');
return { providers: [] };
}
return {
callbacks: {
jwt({ token, account, profile }) { ... },
session({ session, ...params }) { ... },
redirect() {
return `${protocol}://${host}/`;
},
},
providers: [
{
id: 'oidc-provider',
name: 'Test OIDC Provider',
type: 'oidc',
issuer: process.env.AUTH_ISSUER,
clientId: process.env.AUTH_CLIENT_ID,
clientSecret: process.env.AUTH_CLIENT_SECRET,
profile(profile) {
return { name: profile.name };
},
wellKnown: `${process.env.AUTH_ISSUER}/.well-known/openid-configuration`,
} satisfies OIDCConfig<Profile>,
],
secret: process.env.AUTH_SECRET,
redirectProxyUrl: url,
trustHost: true,
};
}); |
Beta Was this translation helpful? Give feedback.
-
Here's how I solved the issue: I used NextAuth solely for OIDC (OpenID Connect) without leveraging any other features. If you're facing a similar problem, check out this blog post for more details: https://blog.antosubash.com/posts/openid-connect-with-nextjs. |
Beta Was this translation helpful? Give feedback.
-
TL;DR: After committing a substantial amount of my own time to this package, including making my own fork to solve some problems as discussed above, realized that Vercel garbage is Vercel garbage; migrated to Lucia in under a day. Edit: 3 days after trying out Lucia, I have now fully removed all Auth.js code and dependencies from my application, and multi-tenant cross-domain login is now working exactly as I had originally wanted it to with Auth.js. The only outstanding item is to implement either magic links or traditional user/pass, as I had not yet decided (even with Auth.js) which I want to use as my non-OAuth solution. Original comment: I thought I had this solved on my end but as I added more enterprise features and did more extensive testing, Auth.js totally fell apart. I'm now testing across several real domains/subdomains. There's something wrong with the way cookies are handled when using a proxy redirect such that the state cookie is cleared. You also can't use Following the preview deployment guide as written does not work -- and it also redirects to the wrong URL (hence why I had to make my own next-auth package to override this). But even a clean install to beta.25 without my package does not work at all. I think that since this is a "preview deployment" guide, the expectation is that you're running (deploying) a fully isolated instance on the tenant, i.e. an on-prem deployment. This would work because then you could set At a broader level not related specifically to multi-tenancy but contributing to my distaste for this package, it's also problematic that the auth logic is totally separate from the application logic. Have to rely on hooking into callbacks and potentially implementing race conditions (specifically if using the event callbacks). Otherwise have to hijack the Originally I had avoided solutions like Lucia because they would require me investing time into writing a bunch of auth logic. But I've now spent weeks on and off trying to resolve Auth.js problems. Although Lucia v3 will be deprecated next year, it's ultimately a pretty simple library, though that's also why it requires writing some of your own auth logic. Even so, I rewrote 80% of my auth logic in about 4-5 hours yesterday. The proxy redirect was the first thing I implemented, making sure I could solve this huge Auth.js feature gap before doing anything else:
This was all very simple so I have no idea why it's nearly impossible in Auth.js. From what I've read of Auth.js' docs about the redirect proxy, the above is more or less what the Auth.js proxy redirect does anyway, so it's very strange to me that arguably the simplest part (writing the cookie at the tenant domain) is completely broken in Auth.js unless you set With an additional hour, converted my API to read the Lucia session ID rather than the Auth.js JWT to get the authenticated user. This is a pretty smooth conversion thanks to Auth.js and Lucia sharing some tables (users and sessions) and only a few minor changes were required to the tables. You also get the benefit of using proper sessions instead of JWTs. Also redid most of the front-end session state management. I already had my own contexts to guarantee a session (instead of always using Auth.js' Now it's just a matter of rewriting my logic to switch between tenants for the current user, which was some gross code I had to stuff into the Given that setting
|
Beta Was this translation helpful? Give feedback.
-
Your question
How to dynamically work with Passwordless/Email auth, without setting NEXTAUTH_URL.
What are you trying to do
I am working on a use-case where NEXTAUTH_URL is not fixed at deploy-time or build-time, but run-time, for a multi-domain (single codebase) scenario. This is to have Email passwordless only.
I have had good success with next-auth other providers for usual scenarios, and absolutely love the simplicity.
Feedback
I tried to browse around the code to get a sense of dependency of the deploy-time NEXTAUTH_URL, and it seems that it is use only to define the Url for
sendVerificationRequest
. If there was a way to pass it as an option, it would do it.Please advise, whats the best approach.
Beta Was this translation helpful? Give feedback.
All reactions