Checking twice for userId with auth or once?
Answered
Amorph posted this in #help-forum
AmorphOP
this is my function inside my DAL file:
this is the only layout page that uses the function and the only place that will redirect if there is no userId:
export async function getStoreByUserAndStoreId(
userId: string,
storeId: string
) {
const store = await prisma.store.findFirst({
where: {
id: storeId,
userId,
},
});
return store;
}this is the only layout page that uses the function and the only place that will redirect if there is no userId:
import Navbar from "@/components/navbar";
import { getStoreByUserAndStoreId } from "@/server/data-access-layer";
import { auth } from "@clerk/nextjs/server";
import { redirect } from "next/navigation";
export default async function DashboardLayout({
children,
params,
}: {
children: React.ReactNode;
params: { storeId: string };
}) {
const { userId } = auth();
if (!userId) redirect("/sign-in");
const store = await getStoreByUserAndStoreId(userId, params.storeId);
if (!store) redirect("/");
return (
<>
<Navbar />
{children}
</>
);
}Answered by B33fb0n3
you shouldn't check your auth inside your layout. The user can still access the content and your layout leak. It's more described here: https://github.com/eric-burel/securing-rsc-layout-leak
Solutions:
checking authentication in a middleware
checking authentication in the page
checking authentication in the data fetching method
In your case I guess the best solution is checking it inside the middleware
Solutions:
checking authentication in a middleware
checking authentication in the page
checking authentication in the data fetching method
In your case I guess the best solution is checking it inside the middleware
5 Replies
AmorphOP
And this is one of my route handlers but they pretty much share the same logic and checks so i'll only post one of them:
I want to move, from all my route handlers into my DAL file, the part that checks for an user id and if there is no user id then error will be thrown, that implicitly meaning also removing the userId as an argument from the function, but there is the layout page where i want to do a redirect if there is no user id and i'm not sure how to approach this part. i can't move the redirect inside the function so only option i see is for layout i'll double check for userid, once in the layout and once when the function is called, is there a better way to approach this?
export async function POST(
request: Request,
{ params }: { params: { storeId: string } }
) {
try {
const { userId } = auth();
const body = await request.json();
const { label, imageUrl } = body;
if (!userId) return new NextResponse("Unauthenticated", { status: 401 });
if (!label) return new NextResponse("Label is required", { status: 400 });
if (!imageUrl)
return new NextResponse("Image URL is required", { status: 400 });
if (!params.storeId)
return new NextResponse("Store id is required", { status: 400 });
// confirm that this storeId exists for this user
const storeByUserAndStoreId = await getStoreByUserAndStoreId(
userId,
params.storeId
);
// if the store id in combination with the user id is not available, that means the user is trying to update someone elses store
if (!storeByUserAndStoreId)
return new NextResponse("Unauthorized", { status: 403 });
const heroImage = await createHeroImage(label, imageUrl, params.storeId);
return NextResponse.json(heroImage);
} catch (error) {
console.log("[HEROIMAGES_POST]", error);
return new NextResponse("Internal error", { status: 500 });
}
}I want to move, from all my route handlers into my DAL file, the part that checks for an user id and if there is no user id then error will be thrown, that implicitly meaning also removing the userId as an argument from the function, but there is the layout page where i want to do a redirect if there is no user id and i'm not sure how to approach this part. i can't move the redirect inside the function so only option i see is for layout i'll double check for userid, once in the layout and once when the function is called, is there a better way to approach this?
@Amorph this is my function inside my DAL file:
tsx
export async function getStoreByUserAndStoreId(
userId: string,
storeId: string
) {
const store = await prisma.store.findFirst({
where: {
id: storeId,
userId,
},
});
return store;
}
this is the only layout page that uses the function and the only place that will redirect if there is no userId:
tsx
import Navbar from "@/components/navbar";
import { getStoreByUserAndStoreId } from "@/server/data-access-layer";
import { auth } from "@clerk/nextjs/server";
import { redirect } from "next/navigation";
export default async function DashboardLayout({
children,
params,
}: {
children: React.ReactNode;
params: { storeId: string };
}) {
const { userId } = auth();
if (!userId) redirect("/sign-in");
const store = await getStoreByUserAndStoreId(userId, params.storeId);
if (!store) redirect("/");
return (
<>
<Navbar />
{children}
</>
);
}
you shouldn't check your auth inside your layout. The user can still access the content and your layout leak. It's more described here: https://github.com/eric-burel/securing-rsc-layout-leak
Solutions:
checking authentication in a middleware
checking authentication in the page
checking authentication in the data fetching method
In your case I guess the best solution is checking it inside the middleware
Solutions:
checking authentication in a middleware
checking authentication in the page
checking authentication in the data fetching method
In your case I guess the best solution is checking it inside the middleware
Answer
@B33fb0n3 you shouldn't check your auth inside your layout. The user can still access the content and your layout leak. It's more described here: https://github.com/eric-burel/securing-rsc-layout-leak
Solutions:
checking authentication in a middleware
checking authentication in the page
checking authentication in the data fetching method
In your case I guess the best solution is checking it inside the middleware
AmorphOP
yes, that's why i want to move the check for auth inside the DAL, but didn't know what to do with the redirect if theres no userid anymore, but now that you mentioned the middleware i'll check it out then 🙂 ty!
Sure thing