Hi guys!
In the article today, we'll discuss, and I'll also show you how to set up NextJS 13 (with app folder), Auth0, and sub-domains.
I'm currently working on a web multi-tenancy app. So, we need multiple sub-domains. For security reasons, we decided to use Auth0. We did follow the basic setup for Auth0, which can be found
Anyway, after a lot of research, a colleague of mine has found that we need to create our SDK. If you followed the basic quickstart from Auth0, you should have something like
// src/api/auth/[auth0]/route.ts
import { NextResponse, NextRequest } from 'next/server';
import { handleAuth } from '@auth0/nextjs-auth0';
export const GET = (req: NextRequest, res: NextResponse) => {
return handleAuth()(req, res); // not neccesary to have (req, res)
};
And beside of that, in our case, we had a middleware to set the user token from Auth0
You can ignore the first if statement for /api/status as we needed it for other checks in deployments. It is the only route on the application which doesn't require authentification.
// src/middleware.ts
import { NextRequest, NextResponse } from ‘next/server’;
import {
withMiddlewareAuthRequired,
getSession,
} from ‘@auth0/nextjs-auth0/edge’;
export default withMiddlewareAuthRequired(async (req: NextRequest) => {
if (req.nextUrl.pathname === ‘/api/status’) {
return NextResponse.next();
}
const res = NextResponse.next();
const user = await getSession(req, res);
if (user) {
// set your user.token whenever you want, db, cookies, localStorage etc
return res;
}
return res;
});
export const config = {
matcher: ‘/’,
};
So basically, with this setup, the
Now, as I mentioned earlier, my colleague found out we have to create our own
The following configuration is for macOS and Linux.
If you use Windows, use a Google search such as: how to add sub domains local windows
So, open your terminal and run:
$ sudo nano /etc/host
Here, you have to add a root domain and a few subdomains the name will not matter, but the extension, yes. So they can be anything but need to end with .local
.
127.0.0.1 cloudstar.local
127.0.0.1 apple.cloudstar.local
127.0.0.1 microsoft.cloudstar.local
127.0.0.1 github.cloudstar.local
After you finish, click CTRL + X
then press Y
and enter
Now you need to flush it in the terminal run $ sudo killall -HUP mDNSResponder
So now, in Auth0 Dashboard at your application settings, you'll have to set the:
* Please note that before Cloudstar.local there's a . (dot)
Allowed callbacks urls to:
http://.cloudstar.local:3000/api/auth/callback
Allowed logout urls to:
http://.cloudstar.local:3000
// src/lib/auth0.ts
import { initAuth0 } from '@auth0/nextjs-auth0';
export const initializeAuth0 = (req): ReturnType<typeof initAuth0> => {
return initAuth0({
baseURL: `http://${req.headers.get('host')}`,
secret: process.env.AUTH0_SECRET,
issuerBaseURL: process.env.AUTH0_ISSUER_BASE_URL,
clientID: process.env.AUTH0_CLIENT_ID,
clientSecret: process.env.AUTH0_CLIENT_SECRET,
session: {
cookie: {
domain: `.${req.headers
.get('host')
.split(':')[0]
.split('.')
.slice(-2)
.join('.')}`,
},
},
});
};
The req.headers.get('host')
will return
And at the session.cookie.domain
we want to set up the domain. But without a port, we need to make sure the cookie will be set for
A small tip:
If you want to set HTTP or HTTPS based on development or production, you can pass this to the base.
baseURL: `${
process.env.NODE_ENV === 'development' ? 'http' : 'https'
}://${req.headers.get('host')}`
We need to modify the API route as well to use the custom Sdk.
// src/api/auth/[auth0]/route.ts
import type { NextApiRequest, NextApiResponse } from 'next'
import { initializeAuth0 } from '@/lib/auth0';
export const GET = (req: NextApiRequest, res: NextApiResponse) => {
const auth0 = initializeAuth0(req);
return auth0.handleAuth()(req, res);
}
Now, if you're trying to access your instance, it has to work to log in but will not work to log out. Why, you wonder? So, if you open the dev tools from your browser and go to application -> cookies. You'll see two cookies:
First with the name appSesion, value, and the domain:
But if you want to log out, I will do the refresh I was saying at the start of the article and will log you back in.
And now comes the fix:
The issue is middleware withMiddlewareAuthRequired. This middleware is setting the domain cookie, aka
Let's get back at the fix. So, you just have to change the name of middleware from withMiddlewareAuthRequired to anything else, let's say, middleware, and it will work perfectly fine.
I'm also providing a GitHub repo for the final code to be more concise because here, I mostly explained what was the issues and so on, and we didn't focus too much on the code itself.
End note:
I'm pretty sad that most of the discussions on Auth0 are open; there are a few responses or no responses at all, and then the topic is closed. Or, in some discussions, folks came and said:
"Oh yeah, I had the same issue, but I managed to fix it" - Yes, I'm glad you did, but how? Because I need a fix as well at that very moment.
Anyway, that's it for today, guys!
Many thanks to my colleagues for help, the internet, and you guys for reading. If you have any queries, please let me know at
Until next time!
Cheers! 🍻
Also published here.