Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion server/routers/external.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1338,6 +1338,12 @@ authenticated.get("/ws/round-trip-message/:messageId", checkRoundTripMessage);
// Auth routes
export const authRouter = Router();
unauthenticated.use("/auth", authRouter);

// Register setup-check BEFORE the global auth rate limiter.
// This endpoint is called on every dashboard root page load (pure boolean
// read, no secrets) and must not consume the auth rate-limit budget.
authRouter.get("/initial-setup-complete", auth.initialSetupComplete);

authRouter.use(
rateLimit({
windowMs:
Expand Down Expand Up @@ -1642,7 +1648,6 @@ authRouter.post("/idp/:idpId/oidc/generate-url", idp.generateOidcUrl);
authRouter.post("/idp/:idpId/oidc/validate-callback", idp.validateOidcCallback);

authRouter.put("/set-server-admin", auth.setServerAdmin);
authRouter.get("/initial-setup-complete", auth.initialSetupComplete);
authRouter.post("/validate-setup-token", auth.validateSetupToken);

// Security Key routes
Expand Down
11 changes: 8 additions & 3 deletions src/app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,19 @@ export default async function Page(props: {
const getUser = cache(verifySession);
const user = await getUser({ skipCheckVerifyEmail: true });

let complete = false;
let complete: boolean | null = null; // null means "unknown" (request errored)
try {
const setupRes = await internal.get<
AxiosResponse<InitialSetupCompleteResponse>
>(`/auth/initial-setup-complete`, await authCookieHeader());
complete = setupRes.data.data.complete;
} catch (e) {}
if (!complete) {
} catch (e) {
// Swallow errors (e.g. 429 rate limit, 500, network failure).
// Only redirect to initial-setup when the server *confirms* setup
// is incomplete (complete === false). If the request itself failed we
// cannot tell, so fall through to the login redirect instead.
}
if (complete === false) {
redirect("/auth/initial-setup");
}

Expand Down
Loading