Pass more data to session in Next-auth
Asked Answered
C

2

10

We are doing OTP auth in our website. So in order to get authorized, a visitor enter his phone number in input and we send him a OPT number and he again enters the sent opt, then if it matches, we send him his account credendials (token, userID) if exists or we create new and we want to save that credentails in session useing next-auth.

This is where i got so far:

export default NextAuth({
  providers: [
    CredentialsProvider({
      credentials: {
        phoneNumber: { label: 'PhoneNumber', type: 'text' },
        code: { label: 'Code', type: 'text' },
        type: { label: 'Type', type: 'text' },
      },
      async authorize(credentials, req) {
        const user_needs = await requests.auth.signInEnterOtp(
          credentials.phoneNumber,
          credentials.code,
          credentials.type
        )
        return user_needs.ok ? true : null
      },
    }),
  ],
  callbacks: {
    async session({ session, user, token }) {
      return session
    },
  },
  secret: process.env.JWT_SECRET,
})

I need to save the user_needs in session but how can i pass it throuh authorize to session?

I tried returning the user_need in authorize but it was not passed to session callback.

Celia answered 19/2, 2022 at 13:6 Comment(2)
You can return a user object from authorize that will be passed to the jwt and session callbacks.Correspondent
I tried it but got nothing of it in session callback, Could you please show me code as an answer!Celia
C
28

Eventually i figured it out like this:

async authorize(credentials, req) {
 const res = fetchUserInfo(credentials.opt)
 if(res.ok) return {user: res.data} // res.data contains whatever received from DB call => fetchUserInfo(credentials.opt)

 return null
},
callbacks: {

 async jwt({ token, user }) {
  // the user present here gets the same data as received from DB call  made above -> fetchUserInfo(credentials.opt)

  return { ...token, ...user }
 },
  async session({ session, user, token }) {
  // user param present in the session(function) does not recive all the data from DB call -> fetchUserInfo(credentials.opt)

  return token
 },
},

Edit: 2023 Feb 15

I myself understood callback cycle better now:

authorize --> jwt --> session

jwt callback(cb) accepts the user object that authorize cb returns.

By default jwt retuns the token and things return from there is then available in the token object of session cb

Example:

async authorize(credentials, req) {
  return { user: { role: 'ADMIN' } }
},

async jwt({ token, user }) {
  return { ...token, role: user.role }
},

async session({ session, token }) {
  return { ...session, token.role }
}

But when i use Providers, i won't have authorize cb, so to get user's role i need to query db in jwt cb but this callback runs a lot and i don't know what is the better option

Celia answered 21/2, 2022 at 7:28 Comment(6)
Thanks, all others' answers are not clear as yours.Humankind
@Celia I do have large user object which contains "user's all settings", so it throws "431 Request Header Fields Too Large" while passing ...user from jwt callback.Heilner
@NimeshVaghasiya Session has limit, it's not good idea to store all the info to it. Instead store less user info in session and create an api endpoint which brings all the info and create a hook useUser which fetch the api and returns itCelia
@Celia Thanks, I'm looking for something that user setting api should only call one time after user login, later share setting to all over app pages (nextjs). is it possible using useUser hook?Heilner
@NimeshVaghasiya The same idea. For example in the login page after a login button is clicked and revieved 200 status code, fetch the user setting from the api and save to local storage or i usually use swr or react-query with that useUser hookCelia
I'm doing exactly this, but the session callback is never called. I find answers where this caused by the token is too large, but mine is not. Even if I run with all defaults except an identity session callback, it is never called.Impedance
L
0

A.Anvarbekov, i think it works but maybe in callbacks we should also pass other session properties? something like:

 async session({ session, token }) {
  return {
   ...session,
   user:{...token.user}
 },
Libreville answered 30/9, 2022 at 13:18 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.