# How to migrate from JWT Auth to NextAuth
Prerequisite
It is required to have sufficient knowledge of NextAuth.js (opens new window) before reading this migration guide
How to secure API routes?
As the official guide from NextAuth for securing API routes (opens new window) is sufficient, we have not made any separate doc showing the same.
How to refresh a token?
If in case you need to implement refresh token functionality in your app, please refer to this (opens new window) guide from NextAuth.
To remove JWT authentication and implement NextAuth, please follow these steps:
Uninstall the
jsonwebtoken&@types/jsonwebtokenpackages and install thenext-authpackage using the following command:Delete the
src/@fake-db/auth/jwt.ts,src/config/auth.ts,src/context/AuthContext.tsxandsrc/hooks/useAuth.tsxfilesRemove the
import './auth/jwt'import statement from thesrc/@fake-db/index.tsfileRemove all the types related to the
AuthContextand user data from thesrc/context/types.tsfile. If you have not added any type in this file, you may delete this fileIf the
src/contextandsrc/hooksfolders are empty, delete themUpdate the Access Control (ACL) guard as the
src/hooks/useAuth.tsxfile has been deleted. It is not recommended to make changes in thesrc/@corefolder, so create a new file (saysrc/layouts/components/auth/UserAclGuard.tsx). Copy the code fromsrc/@core/components/auth/AclGuard.tsxfile, paste it into the new file, and make necessary modifications and replaceauthwithsession.dataas follows:For example, change the code from:
import { useAuth } from 'src/hooks/useAuth' const auth = useAuth() // User is logged in, build ability for the user based on his role if (auth.user && !ability) { ability = buildAbilityFor(auth.user.role, aclAbilities.subject) ... }to:
import { useSession } from 'next-auth/react' const session = useSession() // User is logged in, build ability for the user based on his role if (session.data && session.data.user && !ability) { ability = buildAbilityFor(session.data.user.role, aclAbilities.subject) ... }As mentioned in above step, it is necessary to modify the following code in each file where the import of
useAuthoccurs. Additionally, the variableauthshould be replaced withsession.datain most of the files.Change the code from:
import { useAuth } from 'src/hooks/useAuth' const auth = useAuth() auth.<something>to:
import { useSession } from 'next-auth/react' const session = useSession() session.data.<something>Update the Authentication guard as the
src/hooks/useAuth.tsxfile has been deleted. It is not recommended to make changes in thesrc/@corefolder, so create a new file (saysrc/layouts/components/auth/UserAuthGuard.tsx). Copy the code fromsrc/@core/components/auth/AuthGuard.tsxfile, paste it into the new file, and make necessary modificationsChange the code from:
import { useAuth } from 'src/hooks/useAuth' const auth = useAuth() useEffect( () => { ... if (auth.user === null && !window.localStorage.getItem('userData')) { if (router.asPath !== '/') { ... } else { ... } } }, // eslint-disable-next-line react-hooks/exhaustive-deps [router.route] ) if (auth.loading || auth.user === null) { return fallback }to:
import { useSession } from 'next-auth/react' const session = useSession() useEffect( () => { ... if (session.status === 'unauthenticated') { if (router.asPath !== '/') { ... } else { ... } } }, // eslint-disable-next-line react-hooks/exhaustive-deps [router.route, session.status] ) if (session.status !== 'authenticated') { return fallback }Update the Guest guard as the
src/hooks/useAuth.tsxfile has been deleted. It is not recommended to make changes in thesrc/@corefolder, so create a new file (saysrc/layouts/components/auth/UserGuestGuard.tsx). Copy the code fromsrc/@core/components/auth/GuestGuard.tsxfile, paste it into the new file, and make necessary modificationsChange the code from:
import { useAuth } from 'src/hooks/useAuth' const auth = useAuth() useEffect(() => { ... if (window.localStorage.getItem('userData')) { ... } // eslint-disable-next-line react-hooks/exhaustive-deps }, [router.route]) if (auth.loading || (!auth.loading && auth.user !== null)) { return fallback } return <>{children}</>to:
import { useSession } from 'next-auth/react' const session = useSession() useEffect(() => { ... if (session.status === 'authenticated' && !router.query.returnUrl) { ... } // eslint-disable-next-line react-hooks/exhaustive-deps }, [router.route, session.status]) if (session.status === 'unauthenticated') { return <>{children}</> } else { return fallback }Update the user dropdown as the
src/hooks/useAuth.tsxfile has been deleted. It is not recommended to make changes in thesrc/@corefolder, so create a new file (saysrc/layouts/components/UserDropdown.tsx). Copy the code fromsrc/@core/layouts/components/shared-components/UserDropdown.tsxfile, paste it into the new file, and make necessary modificationsChange the code from:
import { useAuth } from 'src/hooks/useAuth' const { logout } = useAuth() const handleLogout = () => { logout() handleDropdownClose() }to:
import { signOut } from 'next-auth/react' const handleLogout = () => { signOut({ callbackUrl: '/', redirect: false }).then(() => { router.asPath = '/' }) handleDropdownClose() }Update the import statement in
src/layouts/components/vertical/AppBarContent.tsxand/orsrc/layouts/components/horizontal/AppBarContent.tsxfile(s) after creating the new file and making modifications for theUserDropdownimport and also modify the file according to the step 7from:
import UserDropdown from 'src/@core/layouts/components/shared-components/UserDropdown'to:
import UserDropdown from 'src/layouts/components/UserDropdown'Remove the
src/@core/components/authfolder andsrc/@core/layouts/components/shared-components/UserDropdown.tsxfile from thesrc/@corefolder in order to prevent build-time errorsAs the
src/hooks/useAuth.tsxfile has been deleted, update the code in thesrc/pages/login/index.tsxfile according to the NextAuth's provider. We have demonstrated CredentialsProvider and you can find the related code in this guideUpdate the
src/pages/_app.tsxfile as the new guards have been created and theAuthContexthas been removedfrom:
import AclGuard from 'src/@core/components/auth/AclGuard' import AuthGuard from 'src/@core/components/auth/AuthGuard' import GuestGuard from 'src/@core/components/auth/GuestGuard' import { AuthProvider } from 'src/context/AuthContext' <AuthProvider> {...} </AuthProvider>to:
import AclGuard from 'src/layouts/components/auth/UserAclGuard' import AuthGuard from 'src/layouts/components/auth/UserAuthGuard' import GuestGuard from 'src/layouts/components/auth/UserGuestGuard' import { SessionProvider } from 'next-auth/react' <SessionProvider session={pageProps.session}> {...} </SessionProvider>Change the
.envfilefrom:
NEXT_PUBLIC_JWT_SECRET= YOUR_SECRET_GOES_HERE NEXT_PUBLIC_JWT_EXPIRATION= YOUR_EXPIRATION_DURATION_GOES_HERE NEXT_PUBLIC_JWT_REFRESH_TOKEN_SECRET= YOUR_REFRESH_TOKEN_SECRET_GOES_HEREto:
API_URL=http://localhost:3000 NEXTAUTH_URL=http://localhost:3000 NEXTAUTH_SECRET= YOUR_SECRET_GOES_HEREYou can refer to this (opens new window) guide for generating your own secret.
For
typescript-versionusers, add the following in thetsconfig.jsonfile:"compilerOptions": { "paths": { "next-auth": [ "./node_modules/next-auth" ], ... } },You may require the addition of the
next-auth.d.tsfile to your project's root directory to modify certain types specified by NextAuth. A tutorial on how to alter these types is available through the link provided in the next step. If thenext-auth.d.tsfile must be added, the following entry must be included in thetsconfig.jsonfile:"include": [ "next-auth.d.ts", ... ],Create the
src/pages/api/auth/[...nextauth].tsfile. Please refer to this article on how to implement authentication using CredentialsProvider (opens new window). You may customize this file according to your requirementsIf you get any type errors after doing the above steps, you need to refresh/reopen your editor.
This is it.