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:
- User navigates to the sign-in page
- User enters credentials and submits the form
- The server successfully authenticates with Appwrite and receives a session token
- The server attempts to set a cookie with the session token
- The user is redirected to the account page
- The middleware checks for the presence of the session cookie
- 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.
- 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" };
}
}),
});
- 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).*)'],
};
- 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
},
},
);
};
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
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!
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.