Skip to content

Instantly share code, notes, and snippets.

@danmaby
Created October 17, 2024 07:40
Show Gist options
  • Save danmaby/f34c175459164941f7cbd3a43808b3ed to your computer and use it in GitHub Desktop.
Save danmaby/f34c175459164941f7cbd3a43808b3ed to your computer and use it in GitHub Desktop.
Next.js 14 + tRPC + Appwrite: Session cookie not being set or persisted

I'm building a Next.js 14 application with tRPC and Appwrite for authentication. The T3 Stack was used as a starting point for this app. I'm encountering an issue where the session cookie is not being set or persisted after a successful login.

Environment:

  • Next.js 14 (App Router)
  • tRPC
  • Appwrite for authentication
  • Running on localhost with custom subdomain (my.example.localhost:3000)

Steps to reproduce:

  1. User navigates to the sign-in page
  2. User enters credentials and submits the form
  3. The server successfully authenticates with Appwrite and receives a session token
  4. The server attempts to set a cookie with the session token
  5. The user is redirected to the account page
  6. The middleware checks for the presence of the session cookie
  7. The cookie is not found, and the user is redirected back to the sign-in page

Expected behavior: After successful authentication, the session cookie should be set and persisted, allowing the user to access protected routes.

Actual behavior: The session cookie is not being set or persisted, resulting in the user being unable to access protected routes and getting stuck in a redirect loop.

Relevant code:

  1. Auth Router (src/server/api/routers/auth.ts):
import { cookies } from 'next/headers';

// ... other imports

export const authRouter = createTRPCRouter({
  signIn: publicProcedure
    .input(z.object({
      email: z.string().email(),
      password: z.string(),
    }))
    .mutation(async ({ input }) => {
      const { email, password } = input;
      const { account } = await createAdminClient();

      try {
        const session = await account.createEmailPasswordSession(email, password);
        console.log("Session created:", session);

        cookies().set('appwrite_session', session.secret, {
          httpOnly: true,
          secure: process.env.NODE_ENV === 'production',
          sameSite: 'strict',
          path: '/',
          maxAge: 60 * 60 * 24 // 1 day
        });

        console.log("Cookie set:", cookies().get('appwrite_session'));

        return { success: true };
      } catch (error) {
        console.error("Sign in error:", error);
        return { success: false, error: "Authentication failed" };
      }
    }),
});
  1. Middleware (src/middleware.ts):
import { type NextRequest, NextResponse } from "next/server";
import { createSessionClient } from "./lib/server/appwrite";

export async function middleware(request: NextRequest) {
  console.log("Request URL:", request.url);
  console.log("All headers:", Object.fromEntries(request.headers.entries()));
  console.log("All cookies:", request.cookies.getAll());
  
  const sessionCookie = request.cookies.get('appwrite_session');
  console.log("Session cookie:", sessionCookie);

  if (sessionCookie) {
    const { account } = await createSessionClient(sessionCookie.value);
    try {
      const user = await account.get();
      console.log("Authenticated user:", user.$id);
      return NextResponse.next();
    } catch (error) {
      console.error("Error getting user:", error);
    }
  }

  return NextResponse.redirect(new URL("/signin", request.url));
}

export const config = {
  matcher: ['/((?!api|_next/static|_next/image|favicon.ico).*)'],
};
  1. Sign-in Page (src/app/(auth)/signin/page.tsx):
// ... imports and component setup

const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
  event.preventDefault();
  setLoading(true);

  const formData = new FormData(event.currentTarget);
  const email = formData.get("email") as string;
  const password = formData.get("password") as string;

  signInMutation.mutate(
    { email, password },
    {
      onSuccess: (result) => {
        setLoading(false);
        if (result.success) {
          console.log("Sign-in successful:", result);
          console.log("Cookies after sign-in:", document.cookie);
          if (document.cookie.includes('appwrite_session')) {
            console.log("Session cookie found in browser");
          } else {
            console.log("Session cookie not found in browser");
          }
          setSignInSuccess(true);
          router.push("/account");
        } else {
          // ... error handling
        }
      },
      onError: (error) => {
        // ... error handling
      },
    },
  );
};

Server logs:

Session created: {
  // ... session details
}
Cookie set: {
  name: 'appwrite_session',
  value: 'eyJpZCI6IjY2ZTNk-REMOVED-FOR-BREVITY',
  path: '/'
}
POST /api/trpc/auth.signIn?batch=1 200 in 1930ms
Request URL: http://localhost:3000/account
All headers: {
  // ... headers
}
All cookies: []
Session cookie: undefined
Error getting session: [AppwriteException: User (role: guests) missing scope (account)]
Middleware session: undefined

Browser console logs:

Sign-in successful: {success: true}
Cookies after sign-in: 
Session cookie not found in browser

I've tried setting the cookie using both the cookies() API from Next.js and manually setting the Set-Cookie header. Neither approach seems to result in the cookie being set or persisted in the browser.

Any help or insights would be greatly appreciated. Thank you!

@reloadlife
Copy link

have you found any fix for this? i am having the same issue, and can't figure out how to set a cookie after a proc is completed and the user is authenticated.

@GIT-Gizmo
Copy link

I'm also having the same issue, were you able to fix it?

@reloadlife
Copy link

I'm also having the same issue, were you able to fix it?

@GIT-Gizmo, i fixed it by having an api route, and redirecting users there (safely of course) to set whatever cookies i want

@GIT-Gizmo
Copy link

Oh, thanks man that was helpful, got it to work too 🙏

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment