I am building a multi-tenant subdomain-based app with Auth0 and Next.js with Hono as router. I am using withMiddlewareAuthRequired in middleware.ts to protect my app and redirect users based on their subdomains. My middleware looks like this:
export default withMiddlewareAuthRequired( async function middleware(request: NextRequest) {
const response = NextResponse.next();
const pathname = request.nextUrl.pathname;
const host = request.headers.get('host');
const session = await getSession(request, response);
if (host) {
const domain = getDomain(host, true);
const segments = host.split('.');
//check for subdomain existence
if (host.includes('localhost') ? segments.length > 1 : segments.length > 2) {
//if user access url with subdomain and at root (example: abc.domain.com)
if (pathname === '/') {
//redirect user to abc.domain.com/main
return NextResponse.redirect(
process.env.NODE_ENV === 'production' ? `https://${host}/main` : `http://${host}/main`
);
//redirect to error page if user don't have access to the subdomain
} else if (session && segments[0] !== session.user.org_name) {
return NextResponse.redirect(
process.env.NODE_ENV === 'production'
? `https://${domain}/error/401/unauthorized_org`
: `http://${domain}/error/401/unauthorized_org`
);
}
//if user try to access /main without subdomain (example: domain.com/main)
} else if (pathname === '/main') {
//redirect user to homepage
return NextResponse.redirect(
process.env.NODE_ENV === 'production' ? `https://${host}` : `http://${host}`
);
} else {
return NextResponse.next()
}
}
})
export const config = {
matcher: ['/((?!_next/static|_next/image|favicon.ico).*)'],
};
This works fine for protecting pages and API routes. However, calling API routes result in an error:
Access to fetch at ‘http://localhost:3002/api/organizationFromId/org_IA9V4aMfsDJwcCkW’ from origin ‘http://abc_company.localhost:3002’ has been blocked by CORS policy: No ‘Access-Control-Allow-Origin’ header is present on the requested resource. If an opaque response serves your needs, set the request’s mode to ‘no-cors’ to fetch the resource with CORS disabled.
If I exclude api route from the protection by include it in matcher like so:
export const config = {
matcher: ['/((?!_next/static|_next/image|favicon.ico|api).*)'],
};
Then there are no CORS error but the API route won’t be protected.
I did add app.user(‘*’, cors()) in my route handler (I’m using Hono).
I did know about withApiAuthRequired
export default withApiAuthRequired(function Protected(req) {
const session = getSession();
...
});
but it expect Nodejs req res where Hono uses context object so I don’t know how to bridge the gap.