Custom Session Data + Provider authjs

This guide explains how to add custom data to the user session.

To expand / change / customize the session data you need to to follow the following steps:

  1. Return the custom data in the authorize function
  2. Add callbacks to the NuxtAuthProvider to alter the session data

In the following example we'll add 2 new fields to the session: accessToken and role.

Return the custom data in the Authorize function

// file: ~/server/api/auth/[...].tsexport default NuxtAuthHandler({  secret: config.NUXT_SECRET,  providers: [    // @ts-expect-error You need to use .default here for it to work during SSR. May be fixed via Vite at some point    CredentialsProvider.default({    ...      async authorize(credentials: any) {        const data = {          user: {            name: 'John Doe',            email: '[email protected]',            id: 1,            role: 'admin'          },          token: '123456890',        }        if (data.user) {          const u = {            id: data.user.id,            name: data.user.username,            email: data.user.email,            access_token: data.token, // additional field            role: response.user.role // additional field          };          return u;        } else {          throw createError({            statusCode: 403,            statusMessage: "Credentials not working",          });        }      },    )}   ]   ... // other config

We can see the new fields in the return object u role and access_token. Now we need to pass them in the callbacks.

Add callbacks to the NuxtAuthProvider to alter the session data

First, you must add jwt and session callbacks to the NuxtAuthHandler:

// file: ~/server/api/auth/[...].tsexport default NuxtAuthHandler({  // ... remainder of your config ...  callbacks: {    // Callback when the JWT is created / updated, see https://next-auth.js.org/configuration/callbacks#jwt-callback    jwt: async ({token, user}) => {      const isSignIn = user ? true : false;      if (isSignIn) {        token.jwt = user ? (user as any).access_token || '' : '';        token.id = user ? user.id || '' : '';        token.role = user ? (user as any).role || '' : '';      }      return Promise.resolve(token);    },    // Callback whenever session is checked, see https://next-auth.js.org/configuration/callbacks#session-callback    session: async ({session, token}) => {      (session as any).role = token.role;      (session as any).uid = token.id;      return Promise.resolve(session);    },  },  ..., // other config  providers: [...], // Your provider config})

Notice that in the jwt callback we pass both the access_token and the role but in the session callback we leave out the access_token and we only pass the role since this would expose the token on the frontend through the session object. Exposing the access_token is not recommended, but you can pass it to the session if needed.

After that you can access the new fields in the data portion of the session object:

const { status, data } = useAuth();console.log(data);

output:

{ "user": { "name": "xxxxxxx", "email": "[email protected]" }, "expires": "2023-02-28T20:36:12.584Z", "role": "admin", "uid": 1 }

With this approach data will automatically be correctly typed.

Thanks to