Migrating Next-Auth to Auth.js and Microsoft Entra ID
When you’re upgrading from Next-Auth v4 to Auth.js v5 and moving from Azure AD to the newly renamed Microsoft Entra ID, you need a clear…
Migrating Next-Auth to Auth.js and Microsoft Entra ID
When you’re upgrading from Next-Auth v4 to Auth.js v5 and moving from Azure AD to the newly renamed Microsoft Entra ID, you need a clear, step-by-step migration plan that covers configuration, code updates, and identity-mapping nuances.

Upgrade Next-Auth v5 to Auth.js v5 with Microsoft Elantra ID
Not a member: READ HERE
This guide walks you through:
- Inspecting the Auth.js migration document
- Swapping Azure AD references to Microsoft Entra ID
- Rewriting
src/lib/auth.tsfor Auth.js v5 - Handling the switch from
emailtopreferred_username
1. Inspecting the Auth.js Migration Document
Start by reviewing the Auth.js v5 migration guide on the official site. Key takeaways:
- Auth.js v5 is a ground-up rewrite of Next-Auth, enforcing stricter OAuth/OIDC compliance and moving to an App Router–first API model.
- Your old
[…nextauth]API route becomes a simple export of handlers from your root configuration file. - The single
auth()method replaces separate helpers—no moregetSession,getToken, oruseSessionimports. - Environment variables change:
NEXTAUTH_SECRET→AUTH_SECRETNEXTAUTH_URL→AUTH_URL
Follow each section of the migration guide — Installation, Configuration File changes, API Route refactors, and Server-Side methods — before editing your codebase.
2. Switching from Azure AD to Microsoft Entra ID
Azure Active Directory has officially been rebranded to Microsoft Entra ID. There’s no functional change beyond the name, but you’ll need to update all references in your code, docs, and environment variables.
Steps to migrate naming:
- Update provider IDs and display names from
AzureADorAzureADB2CtoMicrosoftEntraID. - Rename environment variables or config keys:
AZURE_CLIENT_ID→AUTH_MICROSOFT_ENTRA_ID_IDAZURE_CLIENT_SECRET→AUTH_MICROSOFT_ENTRA_ID_SECRETAZURE_TENANT_ID→AUTH_MICROSOFT_ENTRA_ID_ISSUER- Adjust documentation screenshots and user-facing text to show the new Entra ID portal.
3. Rewriting src/lib/auth.ts
Your legacy src/lib/auth.ts likely exported a NextAuth config. With Auth.js v5, centralize your auth setup at the repo root—then re-export handlers, auth, signIn, and signOut for use throughout your app.
Before (Next-Auth v4 style):
// src/lib/auth.ts
import NextAuth from "next-auth"
import AzureADProvider from "next-auth/providers/azure-ad"
export default NextAuth({
providers: [
AzureADProvider({
clientId: process.env.AZURE_AD_CLIENT_ID!,
clientSecret: process.env.AZURE_AD_CLIENT_SECRET!
})
],
callbacks: { /* … */ },
})
After (Auth.js v5):
// auth.ts (project root)
import NextAuth from "next-auth"
import MicrosoftEntraID from "next-auth/providers/microsoft-entra-id"
import { PrismaAdapter } from "@auth/prisma-adapter"
import { prisma } from "./src/libs/prisma"
export const { auth, handlers, signIn, signOut } = NextAuth({
adapter: PrismaAdapter(prisma),
providers: [
MicrosoftEntraID({
clientId: process.env.AUTH_MICROSOFT_ENTRA_ID_ID!,
clientSecret: process.env.AUTH_MICROSOFT_ENTRA_ID_SECRET!,
issuer: process.env.AUTH_MICROSOFT_ENTRA_ID_ISSUER!,
// in my case I have to do this because of the preferred_username and email clash
allowDangerousEmailAccountLinking: true,
checks: ["nonce"],
}),
],
secret: process.env.AUTH_SECRET,
session: { strategy: "database" },
})
Then in your API route:
// src/app/api/auth/[...nextauth]/route.ts
import { handlers } from "@/../auth"
export const { GET, POST } = handlers
4. Handling email vs. preferred_username in Entra ID
Unlike many OAuth providers that always return email, Microsoft Entra ID’s default userinfo payload uses preferred_username to represent a user’s unique login. That distinction can trip you up:
- Use
user.emailwhere available, but fall back touser.preferred_usernameif theemailclaim is missing. - Update your profile-mapping logic on sign-in:
signIn: async ({ user, profile, isNewUser }) => {
if (isNewUser || !profile || !user) return false
// preferred_username is the unique login
const username = profile.preferred_username
if (!username) return false
// apply your own collision or mapping checks here
if (user.email !== username) {
// …requery your data source
// …map preferred_username to your user record
}
return true
}
- Audit your database and user-creation logic to ensure
preferred_usernamevalues don’t collide with other sign-in methods.
By following this four-part plan — digging into the Auth.js v5 migration docs, renaming Azure AD to Microsoft Entra ID, rewriting your auth.ts, and handling the email/preferred_username nuance—you’ll complete a smooth transition without breaking user sessions or sign-in flows.
Looking ahead
- Add support for Entra Verified ID (decentralized credentials) as a future OIDC provider in Auth.js.
- Leverage Auth.js’s new
account()callback to integrate custom roles or MFA-bypass flags. - Explore edge-compatible auth middleware (
withAuth,authMiddleware) for route protection in Next.js App Router. - Automate your
.env.localupdates with a migration script to replace all old Azure AD variables.
With these extra steps, you’ll not only migrate — you’ll modernize your authentication stack.
메타데이터
- post_id
- 8422eb4a2d3b
- slug
- migrating-next-auth-to-auth-js-and-microsoft-entra-id-8422eb4a2d3b
- url
- https://medium.com/@muhaimincs/migrating-next-auth-to-auth-js-and-microsoft-entra-id-8422eb4a2d3b
- canonical_url
- https://medium.com/@muhaimincs/migrating-next-auth-to-auth-js-and-microsoft-entra-id-8422eb4a2d3b
- author_url
- https://medium.com/@muhaimincs
- status
- ok
- fetched_at
- 2026-07-17 13:44:34