mirror of
https://github.com/bulwarkmail/webmail.git
synced 2026-11-05 00:14:18 +00:00
The desktop login page gets "Sign in with your browser…" as its main button. On an instance it opens the instance's real login page in the system browser, with a PKCE challenge. The page checks the password or runs SSO, parks the sign-in under a one-time code, asks once, and sends the code to the app's loopback listener. This browser gets no session out of it, and the app's own page redeems the code, so SameSite=Strict is fine. Standalone runs the mail server's OAuth against the listener, with a page from main for a server with no OAuth at all. - `/api/auth/desktop-handoff/park` and `redeem`, and `sso/complete` parks tokens the same way for a loopback target - `auth.claim()`: the calls are taken once per document, in the first render, in `WindowControlsHost` - `BrowserSignIn` policy, default on, with its ADMX and samples - strings in all 30 languages, and the old button's are gone `runDesktopBrowserSignIn`'s tests changed because the code no longer goes through the callback page's address: it's redeemed where it arrives.
34 lines
1.2 KiB
TypeScript
34 lines
1.2 KiB
TypeScript
"use client";
|
|
|
|
import { useEffect, useState } from "react";
|
|
import { applyControlsArea, watchTitlebarArea, watchWindowRows, type TitlebarArea } from "@/lib/window-controls-overlay";
|
|
import { claimBrowserSignIn } from "@/lib/desktop/browser-sign-in";
|
|
|
|
/**
|
|
* The window's controls over the app, with no title bar row: see
|
|
* lib/window-controls-overlay.ts. Renders nothing, and changes nothing on the
|
|
* page, without an overlay. In the root layout, so that the pages outside [locale]
|
|
* (admin, setup) get it too; there are no messages up there.
|
|
*/
|
|
export function WindowControlsHost() {
|
|
// In the first render of every page, before any frame exists: a frame can reach the
|
|
// bridge, and whoever comes after this gets nothing.
|
|
if (typeof window !== "undefined") claimBrowserSignIn();
|
|
const [area, setArea] = useState<TitlebarArea | null>(null);
|
|
|
|
useEffect(() => watchTitlebarArea((next) => {
|
|
applyControlsArea(next);
|
|
setArea(next);
|
|
}), []);
|
|
|
|
const key = area ? `${area.x},${area.width},${area.height}` : "";
|
|
useEffect(() => {
|
|
if (!area) return;
|
|
return watchWindowRows(area);
|
|
// `key` stands for area, a new object at each change.
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
}, [key]);
|
|
|
|
return null;
|
|
}
|