Skip to content

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

refreshAccessToken is giving me an error, "Cannot read property 'user' of undefined" #4966

Closed
eesazahed opened this issue Jul 18, 2022 · 1 comment
Assignees
Labels
mongodb @auth/mongodb-adapter question Ask how to do something or how something works TypeScript Issues relating to TypeScript

Comments

@eesazahed
Copy link

Question 馃挰

Hello, I'm following this tutorial (https://next-auth.js.org/tutorials/refresh-token-rotation) from the official documentation.

I believe this works correctly in JS, but I wanted to build my project fully in Typescript, so I changed some code. However, upon a user sign in, I receive this error:

[next-auth][error][SESSION_ERROR] 
https://next-auth.js.org/errors#session_error Cannot read property 'user' of undefined {
  message: "Cannot read property 'user' of undefined",
  ...
  name: 'TypeError'
}

The complete code for [...nextauth].ts is below. The Google OAuth is working perfectly, as well as the mongodb connection. The only errors are for the jwt and session callback functions (lines 75-100)

Any help would be appreciated. Thanks.

I'm using the latest version of MacOS, and I'm testing on the latest Google Chrome browser. This is a test project that is running on localhost:3000 for now.

How to reproduce 鈽曪笍

import NextAuth, { Profile, NextAuthOptions } from "next-auth";
import { MongoDBAdapter } from "@next-auth/mongodb-adapter";
import clientPromise from "../../../lib/mongodb";
import GoogleProvider from "next-auth/providers/google";
import { OAuthConfig } from "next-auth/providers";
import { JWT } from "next-auth/jwt/types";

const GOOGLE_AUTHORIZATION_URL =
  "https://accounts.google.com/o/oauth2/v2/auth?" +
  new URLSearchParams({
    prompt: "consent",
    access_type: "offline",
    response_type: "code",
  });

const refreshAccessToken = async (token: JWT) => {
  console.log(typeof token);

  try {
    const url =
      "https://oauth2.googleapis.com/token?" +
      new URLSearchParams({
        client_id: process.env.GOOGLE_ID as string,
        client_secret: process.env.GOOGLE_SECRET as string,
        grant_type: "refresh_token" as string,
        refresh_token: token?.refreshToken as string,
      });

    const response = await fetch(url, {
      headers: {
        "Content-Type": "application/x-www-form-urlencoded",
      },
      method: "POST",
    });

    const refreshedTokens = await response.json();

    if (!response.ok) {
      throw refreshedTokens;
    }

    return {
      ...token,
      accessToken: refreshedTokens.access_token,
      accessTokenExpires: Date.now() + refreshedTokens.expires_at * 1000,
      refreshToken: refreshedTokens.refresh_token ?? token.refreshToken, // Fall back to old refresh token
    };
  } catch (error) {
    console.log(error);

    return {
      ...token,
      error: "RefreshAccessTokenError",
    };
  }
};

export const authOptions: NextAuthOptions = {
  adapter: MongoDBAdapter(clientPromise),
  providers: [
    GoogleProvider({
      clientId: process.env.GOOGLE_ID as string,
      clientSecret: process.env.GOOGLE_SECRET as string,
      authorization: GOOGLE_AUTHORIZATION_URL,
    }) as OAuthConfig<Profile>,
  ],
  callbacks: {
    signIn: async ({ user, account, profile }) => {
      return true;
    },
    redirect: ({ url, baseUrl }) => {
      return baseUrl;
    },

    jwt: async ({ token, user, account }) => {
      // Initial sign in
      if (account && user) {
        return {
          accessToken: account.access_token,
          accessTokenExpires: Date.now() + account.expires_at! * 1000,
          refreshToken: account.refresh_token,
          user,
        };
      }

      if (Date.now() < (token.accessTokenExpires as number)) {
        // Return previous token if the access token has not expired yet
        return token;
      }

      // Access token has expired, try to update it
      return refreshAccessToken(token);
    },
    session: async ({ session, token }) => {
      session!.user = token.user as {};
      session.accessToken = token.accessToken;
      session.error = token.error;

      return session;
    },
  },

  secret: process.env.NEXTAUTH_SECRET,
  pages: {
    signIn: "/auth/signin",
    signOut: "/",
  },
};

export default NextAuth(authOptions);

Contributing 馃檶馃徑

No, I am afraid I cannot help regarding this

@eesazahed eesazahed added question Ask how to do something or how something works TypeScript Issues relating to TypeScript labels Jul 18, 2022
@github-actions github-actions bot added the mongodb @auth/mongodb-adapter label Jul 18, 2022
@ramadhansyah
Copy link

@nextauthjs nextauthjs locked and limited conversation to collaborators Jul 19, 2022
@balazsorban44 balazsorban44 converted this issue into discussion #4971 Jul 19, 2022

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

Labels
mongodb @auth/mongodb-adapter question Ask how to do something or how something works TypeScript Issues relating to TypeScript
Projects
None yet
Development

No branches or pull requests

4 participants