skip to Main Content

Stack I’m using:

  • Appwrite (Backend)
  • Next.js

I’m using Next.js middleware to implement some protected routes. In the middleware.ts file, I’ve added a method that checks whether the user is logged in. After adding that, it’s showing the window is not defined error. But I haven’t used window anywhere in the method. Below is the main content of middleware.ts

    const NOT_LOGGED_IN_ROUTES = ["/login"];
    const LOGGED_IN_ROUTES = ["/edit-profile"];

    export async function middleware(request: NextRequest) {
      const currentPath = request.nextUrl.pathname;

      const { AppwriteServices } = await import("@/AppwriteServices");
      const appwriteServices = new AppwriteServices();
      const isUserLoggedIn = (await appwriteServices.getCurrentUser()) !== null;
      
      if (isUserLoggedIn && NOT_LOGGED_IN_ROUTES.includes(currentPath)) {
        return NextResponse.redirect(new URL("/", request.url));
      }

      if (!isUserLoggedIn && LOGGED_IN_ROUTES.includes(currentPath)) {
        return NextResponse.redirect(new URL("/login", request.url));
      }
    }

if the user is logged in, the getCurrentUser method returns the user data, otherwise null. Below is the content of getCurrentUser

  getCurrentUser = async () => {
    try {
      await this.setSession();

      return await account.get();
    } catch (error) {
      // throw new Error((<Error>error).message);
      /*
        Cannot throw an error here,
        cause in Appwrite's `account.get()`,
        catch means the user is not logged in.      
      */
    }

    return null;
  };

Above used setSession method is shown below

private async setSession() {
    try {
      const cookieValue = await this.getCookieValue();

      const authCookies = {
        [`a_session_${AppwriteProject.toLowerCase()}`]: cookieValue,
      };

      client.headers["X-Fallback-Cookies"] = JSON.stringify(authCookies);
    } catch (error) {
      throw new Error((<Error>error).message);
    }
  }

Above used client is the client object provided by appwrite. And the getCookieValue method is shown below

private async getCookieValue() {
    try {
      const { cookies } = await import("next/headers");

      const sessionNames = [
        `a_session_${AppwriteProject.toLowerCase()}`,
        `a_session_${AppwriteProject.toLowerCase()}_legacy`,
      ];

      const cookieStore = cookies();
      const hash =
        cookieStore.get(sessionNames[0]) ??
        cookieStore.get(sessionNames[1]) ??
        null;

      return hash?.value || "";
    } catch (error) {
      throw new Error((<Error>error).message);
    }
  }

The AppwriteProject variable used above is just an env variable.

I had to set the sessions manually cause Appwrite uses localStorage to store and retrieve session tokens and I’m doing everything on the server-side.

So as you can see above, I haven’t used window anywhere in the method/s. There are some appwrite provided methods as well. the account.get(), which source code you can check here

In the account.get() method, another client.call() method is used, where we can see some use of the window object. But it’s not used directly. There are fallback checks with if statements. So there’s no way for the window object to get executed.

Besides that, I’m using the same getCurrentUser method on another server component and that works fine.

Can’t understand what’s the issue here. Any help will be appreciated. Also, let me know if you need any further info

2

Answers


  1. There are 3 contexts where your code can run when you make a Next.js app

    1. Client side (browser)
    2. Server side (hosting server)
    3. Edge (edge networks)

    The Appwrite web sdk (appwrite NPM package) uses isomorphic fetch so that the same fetch can be used in both client and server side, but it doesn’t work on the edge.

    For now, I would suggest not using the web sdk in the middleware.

    Login or Signup to reply.
  2. In order to use the window object you need to use it in a client component and wrap it in a window != undefined.

    Note: It can’t be used in a sever component or in a Next JS middleware.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search