Setting up Microsoft authentication in Next.js used to mean writing 50+ lines of middleware, manual redirects, and boilerplate in every protected page. Not anymore.
The Problem
Here's what protecting a route looked like before:
// middleware.ts - 30 lines
export async function middleware(request: NextRequest) {
const session = await getServerSession();
if (!session) {
return NextResponse.redirect(new URL('/login', request.url));
}
// ... more boilerplate
}
// app/dashboard/page.tsx - 20 more lines
export default async function Dashboard() {
const session = await getServerSession();
if (!session) {
redirect('/login');
}
// Finally, your actual code
return <div>Dashboard</div>;
}
Painful. Repetitive. Error-prone.
The Solution
// app/dashboard/page.tsx
export const auth = { required: true };
export default function Dashboard() {
return <div>Dashboard</div>;
}
That's it. One line. The page is now protected.
How It Works
Install the package:
npm install @chemmangat/msal-next @azure/msal-browser @azure/msal-react
Wrap your app:
// app/layout.tsx
import { MSALProvider } from '@chemmangat/msal-next';
export default function RootLayout({ children }) {
return (
<html>
<body>
<MSALProvider
clientId={process.env.NEXT_PUBLIC_CLIENT_ID}
tenantId={process.env.NEXT_PUBLIC_TENANT_ID}
>
{children}
</MSALProvider>
</body>
</html>
);
}
Protect any page:
export const auth = { required: true };
Done. Users get redirected to login automatically. Return URLs handled. Loading states included.
Real-World Examples
Role-based access:
export const auth = {
required: true,
roles: ['admin', 'editor']
};
Custom validation:
export const auth = {
required: true,
validate: (account) => account.username.endsWith('@company.com')
};
Custom UI:
export const auth = {
required: true,
loading: <Spinner />,
unauthorized: <AccessDenied />
};
Why This Matters
Before:
- 30 minutes to set up middleware
- Boilerplate in every protected page
- Easy to forget protection
- Hard to maintain
After:
- 30 seconds to protect a route
- Zero boilerplate
- Explicit and visible
- Easy to maintain
The Full Feature Set
Beyond zero-config protection, you get:
- Pre-built components: Sign-in button, user avatar, auth status
-
Powerful hooks:
useMsalAuth(),useGraphApi(),useUserProfile() - TypeScript first: Full type safety
- Production ready: Error handling, token refresh, retry logic
- Next.js 14+ optimized: Built for App Router
Quick Start
// 1. Install
npm install @chemmangat/msal-next
// 2. Wrap your app
<MSALProvider clientId="..." tenantId="...">
{children}
</MSALProvider>
// 3. Protect routes
export const auth = { required: true };
// 4. Add login page
import { MicrosoftSignInButton } from '@chemmangat/msal-next';
<MicrosoftSignInButton />
Under the Hood
The package uses React Context and Next.js App Router features to:
- Check auth state on page load
- Redirect to login if needed (with return URL)
- Show loading state during check
- Render page when authorized
All automatic. All configurable.
Migration from v3.x
Good news: v4.0 is 100% backward compatible. Your existing code works. The new protection feature is optional but recommended.
Why I Built This
I was tired of copying the same middleware code across projects. Tired of forgetting to protect routes. Tired of debugging auth issues.
So I built what I wanted: protection that's explicit, visible, and requires zero boilerplate.
Try It
npm install @chemmangat/msal-next
- npm: @chemmangat/msal-next
- GitHub: chemmangat/msal-next
- Docs: Full documentation in the README
2,200+ developers are already using it. Join them.
TL;DR: Protect Next.js routes with Microsoft auth using one line: export const auth = { required: true }. No middleware, no boilerplate, just works.
Top comments (0)