Add Microsoft Authentication to Next.js in 5 Minutes
No fluff. No theory. Just working code.
By the end of this tutorial, you'll have a Next.js app with Microsoft authentication that actually works.
What You'll Build
A Next.js app where users can:
- ✅ Sign in with their Microsoft account
- ✅ See their profile information
- ✅ Sign out
Prerequisites
- Node.js 18+ installed
- A Microsoft account (personal or work)
- 5 minutes
Step 1: Create Next.js App (30 seconds)
npx create-next-app@latest my-auth-app
cd my-auth-app
Choose these options:
- TypeScript: Yes
- ESLint: Yes
- Tailwind CSS: Yes
- App Router: Yes
- Everything else: Default
Step 2: Install Auth Package (15 seconds)
npm install @chemmangat/msal-next @azure/msal-browser @azure/msal-react
Step 3: Get Azure Credentials (2 minutes)
- Go to Azure Portal
- Search for "Azure Active Directory"
- Click "App registrations" → "New registration"
- Fill in:
- Name:
my-auth-app - Supported account types: "Accounts in any organizational directory and personal Microsoft accounts"
- Redirect URI:
http://localhost:3000
- Name:
- Click "Register"
- Copy the "Application (client) ID"
Step 4: Add Environment Variable (10 seconds)
Create .env.local:
NEXT_PUBLIC_CLIENT_ID=paste-your-client-id-here
Step 5: Add Auth Provider (30 seconds)
Edit app/layout.tsx:
import type { Metadata } from "next";
import { Inter } from "next/font/google";
import "./globals.css";
import { MsalAuthProvider } from '@chemmangat/msal-next';
const inter = Inter({ subsets: ["latin"] });
export const metadata: Metadata = {
title: "My Auth App",
description: "Microsoft authentication demo",
};
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<body className={inter.className}>
<MsalAuthProvider clientId={process.env.NEXT_PUBLIC_CLIENT_ID!}>
{children}
</MsalAuthProvider>
</body>
</html>
);
}
Step 6: Create Login Page (2 minutes)
Replace app/page.tsx:
'use client';
import { MicrosoftSignInButton, useMsalAuth, SignOutButton } from '@chemmangat/msal-next';
export default function Home() {
const { isAuthenticated, account } = useMsalAuth();
if (!isAuthenticated) {
return (
<main className="flex min-h-screen flex-col items-center justify-center p-24">
<div className="text-center">
<h1 className="text-4xl font-bold mb-8">Welcome!</h1>
<p className="text-xl mb-8">Sign in to continue</p>
<MicrosoftSignInButton variant="dark" size="large" />
</div>
</main>
);
}
return (
<main className="flex min-h-screen flex-col items-center justify-center p-24">
<div className="text-center">
<h1 className="text-4xl font-bold mb-4">Hello, {account?.name}!</h1>
<p className="text-xl mb-2">Email: {account?.username}</p>
<p className="text-gray-600 mb-8">ID: {account?.homeAccountId}</p>
<SignOutButton variant="light" size="medium" />
</div>
</main>
);
}
Step 7: Run It! (5 seconds)
npm run dev
Click "Sign in with Microsoft" and you're done! 🎉
What Just Happened?
- MsalAuthProvider initialized MSAL with your client ID
- MicrosoftSignInButton handled the entire login flow
- useMsalAuth gave you access to user data
- SignOutButton handled logout
That's it. Production-ready Microsoft authentication in 5 minutes.
Bonus: Add User Profile (2 more minutes)
Want to show more user info? Add this:
'use client';
import {
MicrosoftSignInButton,
useMsalAuth,
SignOutButton,
useUserProfile,
UserAvatar,
} from '@chemmangat/msal-next';
export default function Home() {
const { isAuthenticated } = useMsalAuth();
const { profile, loading } = useUserProfile();
if (!isAuthenticated) {
return (
<main className="flex min-h-screen flex-col items-center justify-center p-24">
<div className="text-center">
<h1 className="text-4xl font-bold mb-8">Welcome!</h1>
<MicrosoftSignInButton variant="dark" size="large" />
</div>
</main>
);
}
if (loading) {
return (
<main className="flex min-h-screen flex-col items-center justify-center">
<div>Loading profile...</div>
</main>
);
}
return (
<main className="flex min-h-screen flex-col items-center justify-center p-24">
<div className="text-center">
<UserAvatar size={100} className="mb-4" />
<h1 className="text-4xl font-bold mb-4">{profile?.displayName}</h1>
<div className="text-left mb-8 space-y-2">
<p>📧 Email: {profile?.mail}</p>
<p>💼 Job Title: {profile?.jobTitle || 'N/A'}</p>
<p>🏢 Office: {profile?.officeLocation || 'N/A'}</p>
<p>📱 Phone: {profile?.mobilePhone || 'N/A'}</p>
</div>
<SignOutButton variant="light" size="medium" />
</div>
</main>
);
}
Now you get:
- ✅ User's profile photo
- ✅ Job title
- ✅ Office location
- ✅ Phone number
- ✅ All from Microsoft Graph API
Bonus: Protect a Page (1 minute)
Create app/dashboard/page.tsx:
'use client';
import { AuthGuard } from '@chemmangat/msal-next';
export default function DashboardPage() {
return (
<AuthGuard>
<main className="p-24">
<h1 className="text-4xl font-bold">Protected Dashboard</h1>
<p className="mt-4">Only authenticated users can see this!</p>
</main>
</AuthGuard>
);
}
Try visiting /dashboard without logging in - you'll be redirected to login automatically.
Bonus: Add Role-Based Access (2 minutes)
First, add roles in Azure AD (see enterprise guide for details).
Then use them:
'use client';
import { useRoles, AuthGuard } from '@chemmangat/msal-next';
export default function AdminPage() {
const { hasRole } = useRoles();
return (
<AuthGuard>
<main className="p-24">
{hasRole('Admin') ? (
<div>
<h1 className="text-4xl font-bold">Admin Panel</h1>
<p>Welcome, administrator!</p>
</div>
) : (
<div>
<h1 className="text-4xl font-bold">Access Denied</h1>
<p>You need admin role to access this page.</p>
</div>
)}
</main>
</AuthGuard>
);
}
Common Issues
"Invalid client" error
- Double-check your client ID in
.env.local - Make sure you added
http://localhost:3000as a redirect URI in Azure
"AADSTS50011" error
- Add
http://localhost:3000to redirect URIs in Azure Portal - Make sure there's no trailing slash
Hydration errors
- Make sure you're using
'use client'directive - The provider is in the root layout
"No active account" error
- User needs to log in first
- Check
isAuthenticatedbefore callingacquireToken
What's Next?
You now have working Microsoft authentication! Here's what to explore:
- MS Graph API - Access user's emails, calendar, files
- Middleware - Protect routes at the edge
- Server Components - Check auth server-side
- Role-Based Access - Implement RBAC with Azure AD roles
Full Code
Here's the complete app/page.tsx:
'use client';
import {
MicrosoftSignInButton,
useMsalAuth,
SignOutButton,
useUserProfile,
UserAvatar,
} from '@chemmangat/msal-next';
export default function Home() {
const { isAuthenticated } = useMsalAuth();
const { profile, loading } = useUserProfile();
// Not logged in
if (!isAuthenticated) {
return (
<main className="flex min-h-screen flex-col items-center justify-center p-24 bg-gradient-to-b from-blue-50 to-white">
<div className="text-center max-w-md">
<h1 className="text-5xl font-bold mb-4 bg-gradient-to-r from-blue-600 to-purple-600 bg-clip-text text-transparent">
Welcome!
</h1>
<p className="text-xl text-gray-600 mb-8">
Sign in with your Microsoft account to continue
</p>
<MicrosoftSignInButton variant="dark" size="large" />
<p className="text-sm text-gray-500 mt-8">
Secure authentication powered by Microsoft Azure AD
</p>
</div>
</main>
);
}
// Loading profile
if (loading) {
return (
<main className="flex min-h-screen flex-col items-center justify-center">
<div className="animate-pulse">Loading your profile...</div>
</main>
);
}
// Logged in
return (
<main className="flex min-h-screen flex-col items-center justify-center p-24 bg-gradient-to-b from-blue-50 to-white">
<div className="bg-white rounded-2xl shadow-xl p-8 max-w-md w-full">
<div className="text-center mb-6">
<UserAvatar size={120} className="mx-auto mb-4" />
<h1 className="text-3xl font-bold text-gray-800">
{profile?.displayName}
</h1>
</div>
<div className="space-y-3 mb-8">
<div className="flex items-center gap-3 text-gray-700">
<span className="text-2xl">📧</span>
<div>
<p className="text-sm text-gray-500">Email</p>
<p className="font-medium">{profile?.mail}</p>
</div>
</div>
{profile?.jobTitle && (
<div className="flex items-center gap-3 text-gray-700">
<span className="text-2xl">💼</span>
<div>
<p className="text-sm text-gray-500">Job Title</p>
<p className="font-medium">{profile.jobTitle}</p>
</div>
</div>
)}
{profile?.officeLocation && (
<div className="flex items-center gap-3 text-gray-700">
<span className="text-2xl">🏢</span>
<div>
<p className="text-sm text-gray-500">Office</p>
<p className="font-medium">{profile.officeLocation}</p>
</div>
</div>
)}
{profile?.mobilePhone && (
<div className="flex items-center gap-3 text-gray-700">
<span className="text-2xl">📱</span>
<div>
<p className="text-sm text-gray-500">Phone</p>
<p className="font-medium">{profile.mobilePhone}</p>
</div>
</div>
)}
</div>
<div className="text-center">
<SignOutButton variant="light" size="medium" />
</div>
</div>
</main>
);
}
Resources
That's it! You just added Microsoft authentication to Next.js in 5 minutes.
Questions? Drop them in the comments! 👇
Found this helpful? Give it a ⭐ on GitHub!
Top comments (0)