Let's say you have a Sitecore JSS site running Next.js and you want to secure either a portion or all of it. This might be because you have a QA environment you want to secure, or you want to lock down a portion for other purposes. While there are a number of options, using middleware is friendly to the end-user as well as to the author who might be using Experience Editor.
Update Your Next.js Version
One thing to keep in mind is when you might have started your Next.js project, it was < 12.3
. While you can make it work, this approach will not work properly as prior to 12.3, middleware was in beta.
Create The Middleware File
If you're using Docker, you likely have a folder structure that resembled ../rendering/companyABC/src
. You need to create a file called middleware.ts
in this folder. As of 12.3, partial middleware - commonly delineated by a file called _middleware.ts
and found under pages/
folder, is no longer supported.
Setup
Let's create a simple middleware.ts
file.
import { NextRequest, NextResponse } from 'next/server';
export function middleware(request: NextRequest) {
return NextResponse.next();
}
It's important to note that the above setup, while simple, will actually break your Experience Editor. One way to get around this is to have two rendering hosts, one with middleware and one without. Not everyone has this ability, so instead, Next.js has an alternative.
Configuring A Conditional Middleware
Thankfully there is a way to run the middleware on specific routes, e.g. /about
or say secret
. What if you need to secure it on everything but a specific route? This will ensure POST calls from within Experience Editor don't run the middleware and break.
export const config = {
matcher: ['/((?!api|sitecore|-|_next|static|favicon.ico).*)', '/'],
};
We prevent it from running on our API calls, the /sitecore
folder and the /-/media
folder.
You may have requirements for additional routes to remain unblocked, but we found these were the minimum to have Experience Editor remain operational while having a secure front end.
Complete Setup
We've added an example below where you'd check to see if a person is authorized. This could be basic authentication or IP restriction. We then also check for the __prerender_bypass
cookie which is only present when in Experience Editor. Otherwise, what ends up happening is some of the calls that shouldn't be re-written break any chance of authoring using Experience Editor.
import { NextRequest, NextResponse } from 'next/server';
function isAuthorized() {
...
}
export function middleware(request: NextRequest) {
const hasPrerenderBypass =
request.cookies.get('__prerender_bypass') != null &&
request.cookies.get('__prerender_bypass') != '';
if (!isAuthorized() && !hasPrerenderBypass){
const loginUrl = new URL('https://companyabc.com/403', request.url);
errorPage.searchParams.set('from', request.nextUrl.pathname);
}
return NextResponse.next();
}
export const config = {
matcher: ['/((?!api|sitecore|-|_next|static|favicon.ico).*)', '/'],
};
And that's it. Hope this helps you out.