Next.js 14 App Layout + Server Actions + Protected Routes
Answered
pheralb posted this in #help-forum

pheralbOP
Hi! I have the following structure:
In the
My question is as follows. I am using
The app works but I am not clear if it is the right way. Taking into account that the app has multiple protected pages. π€
-
π app
| π [user]
| βοΈ layout.tsx
| βοΈ page.tsx
| βοΈ layout.tsx
| βοΈ page.tsx
In the
app/page.tsx
, I'm using Server Actions to redirect when the user is signed in:// π app/page.tsx
const user = await getUser();
if (user) {
return redirect(`/${user.user_metadata.user_name}`);
}
My question is as follows. I am using
app/[user]/layout.tsx
to protect paths that are [user]/*
:// π app/[user]/layout.tsx
import { getUserData } from "@/server/auth";
import { redirect } from "next/navigation";
const AppLayout = async ({ params }: { params: { user: string } }) => {
const user = await getUserData(params.user);
if (!user) {
return redirect("/auth");
}
return <div>AppLayout</div>;
};
export default AppLayout;
The app works but I am not clear if it is the right way. Taking into account that the app has multiple protected pages. π€
-
getUserData
It's a server action that checks if the user is logged in and if the path.user matches the Supabase getUser username:export const getUserData = async (username: string) => {
const user = await getUser();
if (!user) {
return redirect("/auth");
}
if (user.user_metadata.user_name !== username) {
return redirect(`/${user.user_metadata.user_name}`);
}
return user;
};
Answered by B33fb0n3
your middleware right now only updates the session. Right now, it does not handle the auth process. As I said: If I would be you, I would let my middleware handle the auth process to protect specific routes
11 Replies

@pheralb Hi! I have the following structure:
π app
| π [user]
| βοΈ layout.tsx
| βοΈ page.tsx
| βοΈ layout.tsx
| βοΈ page.tsx
In the ``app/page.tsx``, I'm using Server Actions to redirect when the user is signed in:
tsx
// π app/page.tsx
const user = await getUser();
if (user) {
return redirect(`/${user.user_metadata.user_name}`);
}
My question is as follows. I am using ``app/[user]/layout.tsx`` to protect paths that are ``[user]/*``:
tsx
// π app/[user]/layout.tsx
import { getUserData } from "@/server/auth";
import { redirect } from "next/navigation";
const AppLayout = async ({ params }: { params: { user: string } }) => {
const user = await getUserData(params.user);
if (!user) {
return redirect("/auth");
}
return <div>AppLayout</div>;
};
export default AppLayout;
The app works but I am not clear if it is the right way. Taking into account that the app has multiple protected pages. π€
- ``getUserData`` It's a server action that checks if the user is logged in and if the path.user matches the Supabase getUser username:
ts
export const getUserData = async (username: string) => {
const user = await getUser();
if (!user) {
return redirect("/auth");
}
if (user.user_metadata.user_name !== username) {
return redirect(`/${user.user_metadata.user_name}`);
}
return user;
};

If I need to protect data, then I would verify and authenticate my user inside my middleware and check only protected routes thought middleware. The middleware is handled on edge and serverside, so I am able to retrieve the data without a server action.
You might want to do the same, the secure your pages
You might want to do the same, the secure your pages

@B33fb0n3 If I need to protect data, then I would verify and authenticate my user inside my middleware and check only protected routes thought middleware. The middleware is handled on edge and serverside, so I am able to retrieve the data without a server action.
You might want to do the same, the secure your pages

pheralbOP
Hii! I'm using the Supabase middleware:
- https://supabase.com/docs/guides/getting-started/tutorials/with-nextjs?queryGroups=language&language=ts#nextjs-middleware
If I use the following in my
and my
Would it be well implemented? π€
- https://supabase.com/docs/guides/getting-started/tutorials/with-nextjs?queryGroups=language&language=ts#nextjs-middleware
import { type NextRequest } from "next/server";
import { updateSession } from "@/server/supabaseMiddleware";
export async function middleware(request: NextRequest) {
return await updateSession(request);
}
export const config = {
matcher: [
"/((?!_next/static|_next/image|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp)$).*)",
],
};
If I use the following in my
[user]/layout.tsx
:import { getUserData } from "@/server/auth";
const AppLayout = async ({ params }: { params: { user: string } }) => {
const user = await getUserData(params.user);
return <div>{user.user_metadata.name}</div>;
};
export default AppLayout;
and my
getUserData
:export const getUserData = async (username: string) => {
const user = await getUser();
if (!user) {
return redirect("/auth");
}
if (user.user_metadata.user_name !== username) {
return redirect(`/${user.user_metadata.user_name}`);
}
return user;
};
Would it be well implemented? π€
I would be protecting and doing the redirect directly from the layout

@pheralb Hii! I'm using the Supabase middleware:
- https://supabase.com/docs/guides/getting-started/tutorials/with-nextjs?queryGroups=language&language=ts#nextjs-middleware
tsx
import { type NextRequest } from "next/server";
import { updateSession } from "@/server/supabaseMiddleware";
export async function middleware(request: NextRequest) {
return await updateSession(request);
}
export const config = {
matcher: [
"/((?!_next/static|_next/image|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp)$).*)",
],
};
If I use the following in my ``[user]/layout.tsx``:
tsx
import { getUserData } from "@/server/auth";
const AppLayout = async ({ params }: { params: { user: string } }) => {
const user = await getUserData(params.user);
return <div>{user.user_metadata.name}</div>;
};
export default AppLayout;
and my ``getUserData``:
ts
export const getUserData = async (username: string) => {
const user = await getUser();
if (!user) {
return redirect("/auth");
}
if (user.user_metadata.user_name !== username) {
return redirect(`/${user.user_metadata.user_name}`);
}
return user;
};
Would it be well implemented? π€

your middleware right now only updates the session. Right now, it does not handle the auth process. As I said: If I would be you, I would let my middleware handle the auth process to protect specific routes
Answer

@pheralb Oh ok, I got it. Thank you very much π

does that information solved your problem? π

@pheralb ?

pheralbOP
Hii @B33fb0n3 π
In the end, I managed to solve it using Next.js middleware and looking at a Supabase example on Github. Thank you very much for your help!
Authentication and route protection worked great π₯³
In the end, I managed to solve it using Next.js middleware and looking at a Supabase example on Github. Thank you very much for your help!
Authentication and route protection worked great π₯³

@B33fb0n3 sure thing. Please mark solution

pheralbOP
Ready π