15

Hi I am new to nextjs and for authentication I am using next-auth. The users can log in using Google and when they are logged in and authenticated I want to get the access_token given by provider in this case Google. Although I can get that inside signIn callback function but is there a way to globally access that?

Mahdi-Jafaree
  • 882
  • 2
  • 9
  • 22

7 Answers7

21

you can create the callbacks key in the nextAuth config as below to access your userId and access_token, as well.

callbacks: {
    async session({ session, token, user }) {
      session.user.id = token.id;
      session.accessToken = token.accessToken;
      return session;
    },
    async jwt({ token, user, account, profile, isNewUser }) {
      if (user) {
        token.id = user.id;
      }
      if (account) {
        token.accessToken = account.access_token;
      }
      return token;
    },
  },
Saheb Mohammadi
  • 406
  • 3
  • 5
  • 10
    it seems like the accessToken is now removed from the Session type: https://next-auth.js.org/getting-started/upgrade-v4#schema-changes . Is there another way to do it with the latest version? – fbede Oct 27 '22 at 08:56
  • account in not null only when you sign in and you have no way of refreshing access_token – Łukasz Gruner Aug 18 '23 at 10:09
11

for next-auth v4 (and higher):
I had a problem accessing the access token inside the jwt callback, apparently, they have changed the schema and now accessToken is only stored in the Account table.

If you are storing user data in a database using an adapter, you could query the Account table inside the session function. In my case I was using the Prisma adapter and this worked fine for me:

async session({ session, token, user }) {
      const getToken = await prisma.account.findFirst({
        where: {
          userId: user.id,
        },
      });

      let accessToken: string | null = null;
      if (getToken) {
        accessToken = getToken.access_token!;
      }

      session.user.token = accessToken;
      return session;
    },

If you are using typescript and you want to return the token to the client, there is one more step you should do because it would complain otherwise,
Create a /types directory inside your source folder and add a next-auth-d.ts file inside of it.
You will extend the session interface here
import NextAuth, { DefaultSession } from "next-auth";

declare module "next-auth" {
  /**
   * Returned by `useSession`, `getSession` and received as a prop on the `SessionProvider` React Context
   */
  interface Session {
    user: {
      /** Oauth access token */
      token?: accessToken;
    } & DefaultSession["user"];
  }
}

You can now access the session from clientside:

import React from "react";
import { useSession, signIn, signOut } from "next-auth/react";

type Props = {};

function ExampleComponent({}: Props) {
  const { data: session } = useSession();

  if (session) {
    return (
      <>
        Access token {session.user.token} <br />
        <button onClick={() => signOut()}>Sign out</button>
      </>
    );
  }
  return (
    <>
      Not signed in <br />
      <button onClick={() => signIn("discord")}>Sign in with Discord</button>
    </>
  );
}

export default ExampleComponent;
Mohammed Tawfik
  • 571
  • 1
  • 8
  • 21
  • Do I need to register that next-auth.d.ts file somewhere? I still cannot augment my session object – JangoCG Dec 22 '22 at 19:24
  • No, it should automatically pick the type up, refer to: https://next-auth.js.org/getting-started/typescript#main-module – Berke Anday Baloglu Dec 25 '22 at 04:29
  • Be sure the 'NEXTAUTH_SECRET' is set to a strong password! If you don't the access token can be obtained by an evil party, by brute force, this password should not be easily obtained! rotating the `NEXTAUTH_SECRET` is probably a good idea – Mark Bakker Apr 23 '23 at 10:02
5

In Next Auth v4, the accessToken is now in the account object so you can get it with the jwt callback assign it to the token object and then assign it to session object using a callback as well.

import NextAuth from "next-auth"
import GithubProvider from "next-auth/providers/github"


export const authOptions = {
  providers: [
    GithubProvider({
      clientId: process.env.GITHUB_CLIENT_ID,
      clientSecret: process.env.GITHUB_CLIENT_SECRET,
    }),
  ],
  secret: process.env.JWT_SECRET,
  
  callbacks: {
    async jwt({token, account}) {
      if (account) {
        token = Object.assign({}, token, { access_token: account.access_token });
      }
      return token
    },
    async session({session, token}) {
    if(session) {
      session = Object.assign({}, session, {access_token: token.access_token})
      console.log(session);
      }
    return session
    }
  }

}
éniocarlos
  • 69
  • 1
  • 3
4

Please refer to this post which i think will help.

Please be aware of next-auth version, in V4 you can access the access token by: account.access_token, before V4 it will be account.accessToken.

Also this link will help wih callbacks in next0auth V4.

Safwat Fathi
  • 758
  • 9
  • 16
1

for Credentials login

use callbacks like this

callbacks: {
    jwt: async ({ token, user }) => {
        user && (token.user = user)
        return token
    },
    session: async ({ session, token }) => {
        session.user = token.user
        return session
    }
}

then in page import

import { getSession ,useSession, signIn, signOut } from "next-auth/react";

and use this for get token

const { data: token, status } = useSession()
console.log(token)

for get sessin use this

const { data: session, status } = useSession()
console.log(session)
Mandeep Singh
  • 455
  • 2
  • 14
  • 8
    That's not true. In your answer: `const { data: token, status }` and `const { data: session, status }` won't give you two different results, but the same. This means token & session will be the same object. The colon in object destructuring just renames the given variable. – TechWisdom Aug 11 '22 at 10:54
-1

You can access this using the getSession method, which can be used server-side (i.e. in next.js methods like getServerSideProps and client side (i.e. in your normal react components).

See: https://next-auth.js.org/getting-started/client#getsession

ndom91
  • 719
  • 1
  • 9
  • 19
-1
callbacks: {
  async jwt({ token, user, account, profile, isNewUser }) {
    if (account) {
      console.log(account.id_token)
    }
  },
},