If a user is signed into the app between app upgrades, then I want to sign out the user the next time they visit.
I am pulling the version in from the package.json
and storing it in the jwt/session to have for comparison of which version the user authenticated from and what version is now running.
// pages/api/auth/[nextauth].ts const version = require('../../../package.json').version import NextAuth from 'next-auth' import { signOut } from 'next-auth/react' export default NextAuth({ providers: [ /*...*/ ], session: { strategy: 'jwt' }, callbacks: { async jwt(props) { const { token, user, account } = props const isSignIn = user?.username ? true :false if(isSignIn) { token.version = version // ... } if (token?.version !== version) { await signOut() return {} } return token }, // ... } })
This works, but it is throwing an error
https://next-auth.js.org/errors#jwt_session_error window is not defined { message: 'window is not defined', stack: ... name: 'ReferenceError }
I know the error is throwing because I am calling the signOut
function on the server side when it is meant to be a browser side function hence the error for window
is not defined.
How else can I call the signOut
function without it trying to use the browser side call including the reference to window
?
Advertisement
Answer
You can’t use signOut on sever side from what I gathered, but here is a trick I used in my case. Instead trying signOut from the server side return an error code.
const version = require('../../../package.json').version import NextAuth from 'next-auth' import { signOut } from 'next-auth/react' export default NextAuth({ providers: [ /*...*/ ], session: { strategy: 'jwt' }, callbacks: { async jwt(props) { const { token, user, account } = props const isSignIn = user?.username ? true :false if(isSignIn) { token.version = version // ... } if (token?.version !== version) { return { // You can ignore this if you don't need the previous data ...token, // Return an error code error: "invalid-version", } } return token }, // ... } })
Create a wrapper around the secured routes. you can do this in a common layout too.
export const Auth = ({children}) => { const { data: sessionData } = useSession(); const router = useRouter(); useEffect(() => { // check if the error has occurred if (sessionData?.user.error === "invalid-version") { // Sign out here signOut(); } }, [sessionData?.user.error, router]); return ( <>{children}</> ) }