feat(auth): brand the NextAuth signout confirmation page - #5390
feat(auth): brand the NextAuth signout confirmation page#5390IamCoder18 wants to merge 1 commit into
Conversation
Code Review SummaryStatus: No Issues Found | Recommendation: Merge Executive SummaryIncremental change restores a direct Files Reviewed (1 files)
Previous Review Summary (commit 3e60c57)Current summary above is authoritative. Previous snapshots are kept for context only. Previous review (commit 3e60c57)Status: 1 Issue Found | Recommendation: Address before merge Executive SummarySign-out-all-browser-sessions already rotates the web-session pepper, then routes through a second Cancel-capable confirmation page and can leave this tab with a stale NextAuth cookie. Overview
Issue Details (click to expand)WARNING
Files Reviewed (6 files)
Reviewed by grok-4.6 · Input: 29.4K · Output: 5.7K · Cached: 144.9K Review guidance: REVIEW.md from base branch |
NextAuth rendered its own unstyled confirmation page on GET
/api/auth/signout because authOptions.pages only overrode signIn and
error, so the signout flow looked off-brand even though the rest of
the app uses kilo-design tokens and AuthPageLayout.
Worse, every in-app signout entry point (sidebar dropdown, profile
sign-out-browser-sessions dialog, device-auth flow) bypassed any
confirmation by calling signOut({ callbackUrl }) from
next-auth/react, which POSTs /api/auth/signout and follows the
returned redirect directly.
Add a /users/sign_out page that reuses AuthPageLayout, the existing
Card and Button primitives, and the same revoke-web-session +
signOut({ callbackUrl }) flow used elsewhere. The page reads
callbackUrl from the query string, restricts it to same-origin paths,
and falls back to /profile when absent.
Point NextAuth pages.signOut at it, so any external or manual GET
/api/auth/signout lands on the branded page, and route the in-app
signout entry points through /users/sign_out?callbackUrl=... so they
share the same confirmation UI. Update the dev 'nuke' action to
target /users/sign_out?callbackUrl=/profile directly because
NextAuth's pages.signOut redirect drops the original query string
(see node_modules/next-auth/src/core/index.ts:199).
3e60c57 to
ce447d3
Compare
|
We do need you to do PR review before you ask for a review o f this PR. Give there are no pictures, it's unlikely a human did review. I'm going to close this. Feel free to reopen it if you bring it to review standards |
Hey @emilieschario. I do manually review every diff before opening PRs, in accordance with the guidelines. Unfortunately, I did upload a screenshot when I tested it, but it got removed when my agent fixed a formatting issue in the PR description. I apologize, and it won't happen again. Here is said screenshot:
Would it be possible to get this reopened, or would you prefer I open a new PR? |

Summary
GET /api/auth/signoutwas rendering NextAuth's built-in, unstyled confirmation page becauseauthOptions.pagesonly overrodesignInanderror, so the signout flow looked off-brand while the rest of the app useskilo-designtokens andAuthPageLayout. Worse, the in-app signout entry points (sidebar dropdown, device-auth flow) bypassed the confirmation entirely by callingsignOut({ callbackUrl })fromnext-auth/react, whichPOSTs/api/auth/signoutand follows the returned redirect without rendering a confirmation page.This change adds a branded
/users/sign_outpage that reusesAuthPageLayout, the existingCard/Buttonprimitives, and the samerevoke-web-session+signOut({ callbackUrl })flow used elsewhere. The page readscallbackUrlfrom the query string, restricts it to same-origin paths, and falls back to/profilewhen absent. NextAuthpages.signOutis pointed at it, so any external/manualGET /api/auth/signoutlands on the branded page. The sidebar and device-auth signout entry points are updated to navigate to/users/sign_out?callbackUrl=...instead of callingsignOutdirectly, so they share the same confirmation UI. The profile "sign out browser sessions" dialog is left callingsignOutdirectly because that flow runs a server-side tRPC mutation that already rotates the user's web-session pepper — routing through a Cancel-capable confirmation page afterwards would let the user dismiss it with a stale NextAuth cookie. The dev "nuke" action (apps/web/src/components/dev/actions.ts) is updated to point at/users/sign_out?callbackUrl=/profiledirectly because NextAuth'spages.signOutredirect drops the original query string (seenode_modules/next-auth/src/core/index.ts:199).Verification
http://localhost:<port>/users/sign_outand confirm it renders insideAuthPageLayoutwith brand tokens, the "Sign out" button callssignOut({ callbackUrl }), and "Cancel" returns to the previous page.http://localhost:<port>/users/sign_out?callbackUrl=/profileand confirmsignOutlands on/profile.http://localhost:<port>/api/auth/signout?callbackUrl=/profileand confirm it redirects to the branded page and lands on/profileafter confirmation././users/sign_inwithout a second confirmation step./profile.Visual Changes
GET /api/auth/signout; sidebar/device-auth signout skipped confirmation entirely./users/sign_outpage reused bypages.signOut, the sidebar dropdown, and the device-auth flow.