Question presented to candidate:
"Our admin pages redirect everyone without access to /login, even users who are signed in but are not admins. How would you return proper 401 and 403 responses in the App Router, and what are forbidden() and unauthorized()?"
What a strong answer should cover:
- 401 means "we do not know who you are" (sign in); 403 means "we know you, and the answer is no".
unauthorized()andforbidden()fromnext/navigationthrow and renderunauthorized.tsx/forbidden.tsx, likenotFound()does for 404. - They are still experimental in 16.4.2: the config option
experimental.authInterrupts: trueis required; without it the call throws an error at runtime. - They work in Server Components, Server Actions and Route Handlers; they cannot be called in the root layout; both add a
noindexrobots tag. - Status codes: the real 401/403 is sent only if the call happens before streaming starts; inside a
<Suspense>boundary the status stays 200 and the fallback UI streams in. - They throw, so a
try/catchswallows them unless you useunstable_rethrow; put the checks in a Data Access Layer.
Clarifying questions expected:
- "Should a signed-out user see a sign-in page or be redirected?" β
unauthorized()renders UI in place with a 401;redirect()sends them away. - "Do crawlers or API clients depend on the status code?" β then the check must run before any streaming.
Code / implementation expected: Yes β requireUser/requireAdmin helpers, the two special files, and the authInterrupts config.