how to get the provider access token in next-auth
Asked Answered
K

7

19

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?

Kluge answered 6/9, 2021 at 2:12 Comment(0)
S
25

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;
    },
  },
Sheep answered 3/6, 2022 at 16:30 Comment(3)
it seems like the accessToken is now removed from the Session type: next-auth.js.org/getting-started/upgrade-v4#schema-changes . Is there another way to do it with the latest version?Jegar
account in not null only when you sign in and you have no way of refreshing access_tokenUndersheriff
i had to define the session callback as follow and I was able to access token it in the session: callbacks: { async session({ session, token, user }) { return { ...session, token: token }; } }Kordula
H
16

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;
Huskey answered 22/12, 2022 at 1:16 Comment(4)
Do I need to register that next-auth.d.ts file somewhere? I still cannot augment my session objectConcoct
No, it should automatically pick the type up, refer to: next-auth.js.org/getting-started/typescript#main-moduleHuskey
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 ideaMargerymarget
I want to share the user session data to Node.js(apollo-graphql) and I tried many ways to solve that problem but I have still errors. you can see my question here: #77593530Magneton
L
14

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
    }
  }

}
Luciferous answered 6/4, 2023 at 17:16 Comment(2)
Works perfectly, just need the next-auth-d.ts snippet included in @Berke's answer if you're working in TypeScript.Doublebreasted
Excellent. This worked fine for the latest Auth.js 5.0.0-beta.19. Thanks a tonTorhert
E
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.

Excommunicative answered 1/11, 2021 at 16:13 Comment(0)
G
2

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)
Garamond answered 11/2, 2022 at 11:57 Comment(1)
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.Any
M
-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

Mullite answered 18/9, 2021 at 23:41 Comment(0)
A
-1
callbacks: {
  async jwt({ token, user, account, profile, isNewUser }) {
    if (account) {
      console.log(account.id_token)
    }
  },
},
Arhna answered 12/12, 2022 at 20:11 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.