next.jsnext-auth

Updating my nextauth session is not detecting changes from the Database


I'm trying to implement a user reactivation feature. Everything is working except my nextauth session.

API call to Database is working, it's confirmed that field isDeactivated:true is being deleted from the user's account

However after the deletion I updated my session expecting isDeactivated to reset but it's still being displayed as true. This is how I update my nextauth session:

if(await updateSession(update)){
    // change router
}
else{
    //console error
}

async function updateSession(update){
    return new Promise(async(resolve,reject)=>{
        try{
            await update()// apply next-auth update
            resolve(true)
        }
        catch(error){
            console.log(error)
            resolve(false)
        }
    })
}

My nextauth:

async session({ session, user, token }){
    // assign the fields in token to session and return, e.g. if(token.isDeactivated) session.user.isDeactivated=token.isDeactivated
  return session
},
async jwt({ token, user, account, trigger }){
    // the if account checking the account.provider exist
    if(account?.provider){
      if((await CheckIfUserDeactivated_controller(user.id))===true) token.isDeactivated=true
    }

    if(account?.provider==='credentials'){
        // navigate DB to retrieve userid, name etc
    }          
    else if(account?.provider==="google" || account?.provider==="amazon"){
      // navigate DB to retrieve userid, name etc
    }
}

This is working for login. But for some reason it's not working for the update. I can confirm that the user document is being modified (i.e. the isDeactivated field is being deleted) before I updated my session. But the actual session is not being updated until I logoff and re-login the system. Any idea on how to solve this problem?


Solution

  • In your jwt callback, add an if statement and do not forget to return token

    async jwt({ token, user, account, trigger, session }) {
        //...
    
        if (trigger == "update") {
            if (session?.user?.isDeactivated) {
                token.isDeactivated = session.user.isDeactivated
            }
        }
    
        return token
    }
    

    You should have expanded the default user interface in your next-auth.d.ts file (path: /{your-project-name}/types/next-auth.d.ts

    import { DefaultSession } from "next-auth"
    
    declare module "next-auth" {
        interface User {
            id: string
            //...
            isDeactivated?: boolean | null
            //...
        }
    
        interface Session {
            user: User & DefaultSession["user"]
            expires: string
            error: string
        }
    }
    

    Now call update method in your page like the following

    import { Session } from "@auth/core/types"
    
    import { auth, unstable_update } from "auth" // your auth.ts file
    
    const Page = async ({ params }: { params: { slug: string } }) => {
        const session = await auth()
    
        const user = session?.user
    
        //...
    
        const handleUpdate = async (isDeactivated: boolean): Promise<Session | null> => {
            if (user) {
                try {
                    return await unstable_update({
                        user: {
                            ...user,
                            isDeactivated,
                        }
                    })
                } catch (error) {
                    console.log("error", error)
                }
            }
    
            return null
        }
    
        return (
            <>
                {/*Your JSX*/}
            </>
        )
    }