You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
## Next.js App Directory: Authorisation Checks in Pages
323
+
324
+
This can include checking session.user exists or session.org etc.
325
+
326
+
### TL;DR:
327
+
328
+
Don’t put permission checks in layout.tsx! Always put them directly inside your page.tsx or relevant server components for every restricted route.
329
+
330
+
331
+
### Why Not to Use Layouts for Permission Checks
332
+
333
+
* Layouts don’t intercept all requests: If a user navigates directly or refreshes a protected route, layout checks might be skipped, exposing sensitive content.
334
+
* APIs and server actions bypass layouts: Sensitive operations running on the server can’t be guarded by checks in the layout.
335
+
* Risk of data leaks: Only page/server-level checks ensure that unauthorized users never get protected data.
336
+
337
+
### ✅ How To Secure Routes (The Right Way)
338
+
339
+
* Check permissions inside page.tsx or the actual server component.
340
+
* Perform all session/user/role validation before querying or rendering sensitive content.
341
+
* Redirect or return nothing to unauthorized users, before running restricted code.
342
+
343
+
### 🛠️ Example: Page-Level Permission Check
344
+
345
+
346
+
```tsx
347
+
// app/admin/page.tsx
348
+
349
+
import { redirect } from"next/navigation";
350
+
import { getUserSession } from"@/lib/auth";
351
+
352
+
exportdefaultasyncfunction AdminPage() {
353
+
const session =awaitgetUserSession();
354
+
355
+
if (!session||session.user.role!=="admin") {
356
+
redirect("/"); // Or show an error
357
+
}
358
+
359
+
// Protected content here
360
+
return <div>Welcome, Admin!</div>;
361
+
}
362
+
```
363
+
364
+
### 🧠 Key Reminders
365
+
366
+
* Put permission guards in every restricted page.tsx.
367
+
* Never assume layouts are secure for guarding data.
368
+
* Validate users before any sensitive queries or rendering.
369
+
370
+
322
371
## Avoid using Dayjs if you don’t need to be strictly tz aware.
323
372
324
373
When doing logic like Dayjs.startOf(".."), you can instead use date-fns' `startOfMonth(dateObj)` / `endOfDay(dateObj)`;
0 commit comments