Actually no cookie

This commit is contained in:
shamoon
2026-09-04 14:29:52 -07:00
parent ae8e72a701
commit f4004d3b54
2 changed files with 27 additions and 30 deletions
+11 -16
View File
@@ -3,10 +3,11 @@
import { render, screen, waitFor } from "@testing-library/react";
import { beforeEach, describe, expect, it, vi } from "vitest";
const { getSettingsMock, authOptionsMock, signInMock, routerQuery } = vi.hoisted(() => ({
const { getSettingsMock, authOptionsMock, signInMock, replaceMock, routerQuery } = vi.hoisted(() => ({
getSettingsMock: vi.fn(),
authOptionsMock: vi.fn(),
signInMock: vi.fn(),
replaceMock: vi.fn(),
routerQuery: {},
}));
@@ -23,6 +24,7 @@ vi.mock("pages/api/auth/[...nextauth]", () => ({
vi.mock("next/router", () => ({
useRouter: () => ({
query: routerQuery,
replace: replaceMock,
}),
}));
@@ -37,6 +39,7 @@ describe("pages/auth/signin", () => {
beforeEach(() => {
vi.clearAllMocks();
Object.keys(routerQuery).forEach((key) => delete routerQuery[key]);
window.sessionStorage.clear();
});
it("renders an error state when no providers are configured", async () => {
@@ -106,11 +109,14 @@ describe("pages/auth/signin", () => {
expect(screen.getByRole("button", { name: /login via homepage oidc/i })).toBeInTheDocument();
});
it("renders the button when the server disabled auto-login", () => {
render(<SignInPage providers={OIDC_PROVIDERS} settings={SETTINGS} autoLogin={false} />);
it("stops auto-login and hands back the page when the session never sticks", () => {
routerQuery.callbackUrl = "/some/page";
expect(signInMock).not.toHaveBeenCalled();
expect(screen.getByRole("button", { name: /login via homepage oidc/i })).toBeInTheDocument();
render(<SignInPage providers={OIDC_PROVIDERS} settings={SETTINGS} autoLogin />);
render(<SignInPage providers={OIDC_PROVIDERS} settings={SETTINGS} autoLogin />);
expect(signInMock).toHaveBeenCalledTimes(1);
expect(replaceMock).toHaveBeenCalledWith("/auth/signin?autologin=0&callbackUrl=%2Fsome%2Fpage");
});
it("does not auto-login the password provider", () => {
@@ -173,17 +179,6 @@ describe("pages/auth/signin", () => {
vi.unstubAllEnvs();
});
it("getServerSideProps disables auto-login while an attempt is pending", async () => {
authOptionsMock.mockReturnValueOnce({ providers: [] });
getSettingsMock.mockReturnValueOnce({ theme: "dark" });
vi.stubEnv("HOMEPAGE_OIDC_AUTO_LOGIN", "true");
const res = await getServerSideProps({ req: { cookies: { "homepage-autologin-attempt": "1" } } });
expect(res.props.autoLogin).toBe(false);
vi.unstubAllEnvs();
});
it("getServerSideProps falls back to no providers when auth options fail to load", async () => {
const consoleError = vi.spyOn(console, "error").mockImplementation(() => {});
authOptionsMock.mockImplementationOnce(() => {
+16 -14
View File
@@ -7,8 +7,8 @@ import { BiShieldQuarter } from "react-icons/bi";
import { getSettings } from "utils/config/config";
const PUBLIC_SIGN_IN_SETTINGS = ["theme", "color", "title", "background", "backgroundOpacity"];
const AUTO_LOGIN_COOKIE = "homepage-autologin-attempt";
const AUTO_LOGIN_RETRY_SECONDS = 10;
const AUTO_LOGIN_KEY = "homepage-autologin-attempt";
const AUTO_LOGIN_RETRY_MS = 10000;
export default function SignIn({ providers, settings, autoLogin }) {
const router = useRouter();
@@ -33,12 +33,21 @@ export default function SignIn({ providers, settings, autoLogin }) {
useEffect(() => {
if (!redirecting) return;
// getServerSideProps drops autoLogin while this is set, so a bounce loop falls back to the button
const secure = window.location.protocol === "https:" ? "; secure" : "";
document.cookie = `${AUTO_LOGIN_COOKIE}=1; path=/auth; max-age=${AUTO_LOGIN_RETRY_SECONDS}; samesite=lax${secure}`;
let lastAttempt = 0;
try {
lastAttempt = Number(window.sessionStorage.getItem(AUTO_LOGIN_KEY)) || 0;
window.sessionStorage.setItem(AUTO_LOGIN_KEY, String(Date.now()));
} catch {
// sessionStorage throws when site data is blocked, fall through and redirect anyway
}
// Getting here quickly means the session never stuck, hand it back to the user
if (Date.now() - lastAttempt < AUTO_LOGIN_RETRY_MS) {
router.replace(`/auth/signin?autologin=0&callbackUrl=${encodeURIComponent(callbackUrl)}`);
return;
}
signIn(oidcProvider.id, { callbackUrl });
}, [redirecting, oidcProvider, callbackUrl]);
}, [redirecting, oidcProvider, callbackUrl, router]);
let backgroundImage = "";
let opacity = settings?.backgroundOpacity ?? 0;
@@ -243,14 +252,7 @@ export async function getServerSideProps(context) {
homepageSettings[key],
]),
);
// A pending attempt means the previous redirect never established a session
const autoLoginAttempted = context.req?.cookies?.[AUTO_LOGIN_COOKIE] === "1";
return {
props: {
providers,
settings,
autoLogin: process.env.HOMEPAGE_OIDC_AUTO_LOGIN === "true" && !autoLoginAttempted,
},
props: { providers, settings, autoLogin: process.env.HOMEPAGE_OIDC_AUTO_LOGIN === "true" },
};
}