("working");
+
+ useEffect(() => {
+ // React Strict Mode runs effects twice in development. Never redeem twice.
+ if (started.current) return;
+ started.current = true;
+
+ const params = new URLSearchParams(window.location.search);
+ const token = params.get("token");
+ if (!token) {
+ setState("missing");
+ return;
+ }
+
+ // Keep the credential out of browser history and subsequent Referer headers.
+ window.history.replaceState({}, "", window.location.pathname);
+
+ void fetch("/auth/link-amt/exchange/", {
+ method: "POST",
+ credentials: "include",
+ headers: { "Content-Type": "application/json" },
+ body: JSON.stringify({ token: token }),
+ })
+ .then((response) => {
+ if (!response.ok) throw new Error("Magic-link exchange failed");
+ window.location.replace("/");
+ })
+ .catch(() => setState("failed"));
+ }, []);
+
+ if (state === "missing") {
+ return This login link is missing its token.
;
+ }
+ if (state === "failed") {
+ return This login link is invalid or has expired.
;
+ }
+ return Signing you in…
;
+};
+
+export default MagicLink;
--
cgit v1.2.3