const STORAGE_KEY = "hfviewer:space-native-oauth:v2";
const START_URL = "https://hfviewer.com/api/hf_space_oauth/start";
const CONSUME_URL = "https://hfviewer.com/api/hf_space_oauth/consume";
const DESTINATION_URL = "https://hfviewer.com/api/hf_space_oauth/destination";
const POLL_INTERVAL_MS = 800;
const FLOW_TIMEOUT_MS = 5 * 60 * 1000;
const PREPARE_REFRESH_MS = 4 * 60 * 1000;
const PREPARE_RETRY_DELAYS_MS = [0, 450, 1400];
// Recovery after a failed preparation backs off and then stops: a page load
// never loops on an unreachable start endpoint (a copied Space once emitted
// ~15 failures per visitor that way). The next sign-in intent starts over.
const PREPARE_RECOVERY_DELAYS_MS = [2000, 8000, 30000, 60000];
// Hard ceiling on consecutive failed start requests that were not
// user-initiated; a successful preparation resets it.
const PREPARE_MAX_BACKGROUND_ATTEMPTS = 6;
// A user may retry by clicking, but a page reports at most this many
// user-initiated preparation failures.
const PREPARE_MAX_USER_FAILURE_REPORTS = 3;
const OFFICIAL_SPACE_URL = "https://huggingface.co/spaces/embedl/hfviewer";
const REQUEST_TIMEOUT_MS = 12 * 1000;
const AUTH_CHANGED_EVENT = "hfviewer-space-auth-changed";
const OFFICIAL_SPACE_HOSTS = new Set([
"embedl-hfviewer.static.hf.space",
"hfvwr-hfviewer-private-qa.static.hf.space",
]);
// The Space shell intercepts canonical hfviewer.com links during capture and
// treats every root-path URL as "return to the Space landing page", even when
// its query opens an account view. Use the canonicalizing www host so these
// remain ordinary external links; its 301 preserves the full query string.
const ACCOUNT_DESTINATION_ORIGIN = "https://www.hfviewer.com";
const authHost = document.getElementById("hfnx-auth");
const compactAuthHost = document.getElementById("sx-auth");
let oauthResult = readStoredResult();
let rendering = false;
let activeFlow = null;
let preparedFlow = null;
let preparePromise = null;
let prepareFailureCount = 0;
let prepareRecoveryTimer = null;
let prepareFailureEpisodeActive = false;
let prepareSuccessReported = false;
let preparePromiseTrigger = "";
let prepareIntentEscalated = false;
let backgroundPrepareAttempts = 0;
let backgroundPrepareFailureReported = false;
let userPrepareFailureReports = 0;
let preparedFlowExpiryTimer = null;
let loginContinueRequested = false;
let accountDestinationLinks = [];
let lastAnnouncedAuthIdentity = null;
let nativeLoginPopover = null;
function currentSpaceDeployment() {
const host = String(window.location.hostname || "").trim().toLowerCase();
if (host === "embedl-hfviewer.static.hf.space") return "production";
if (host === "hfvwr-hfviewer-private-qa.static.hf.space") return "qa";
if (host.endsWith(".hf.space")) return "clone";
return "local";
}
// OAuth only works on the two official Space origins (the backend trusts
// them for the handoff). A duplicated Space can copy our space_repo value,
// but it can never sign in, so it must not prepare OAuth or report failures.
function isCloneDeployment() {
return currentSpaceDeployment() === "clone";
}
function preparedFlowIsFresh() {
return !!preparedFlow && Date.now() - preparedFlow.preparedAt < PREPARE_REFRESH_MS;
}
function readStoredResult() {
try {
const value = localStorage.getItem(STORAGE_KEY);
const result = value ? JSON.parse(value) : null;
const expiresAt = Number(result?.spaceSession?.expiresAt || 0) * 1000;
if (!result || !expiresAt || expiresAt <= Date.now()) {
localStorage.removeItem(STORAGE_KEY);
return null;
}
return result;
} catch {
return null;
}
}
function writeStoredResult(value) {
try {
if (value) localStorage.setItem(STORAGE_KEY, JSON.stringify(value));
else localStorage.removeItem(STORAGE_KEY);
} catch {
// Keep the current-tab session even when durable storage is unavailable.
}
}
function randomFlowValue() {
const bytes = new Uint8Array(32);
crypto.getRandomValues(bytes);
return Array.from(bytes, (value) => value.toString(16).padStart(2, "0")).join("");
}
function userFromResult(result) {
const raw = result?.userInfo || result?.userinfo || result?.user_info || result?.user || {};
const username = String(
raw.preferred_username || raw.preferredUsername || raw.username || raw.name || ""
).trim();
if (!username) return null;
return {
username,
name: String(raw.name || username).trim(),
picture: String(raw.picture || raw.avatar_url || raw.avatarUrl || "").trim(),
profile: String(raw.profile || `https://huggingface.co/${encodeURIComponent(username)}`).trim(),
subject: String(raw.sub || raw.id || "").trim(),
email: String(raw.email || "").trim().toLowerCase(),
};
}
function trackAuthEvent(eventName, properties = {}) {
try {
const productContext =
window.HFVIEWER_PRODUCT_CONTEXT && typeof window.HFVIEWER_PRODUCT_CONTEXT === "object"
? window.HFVIEWER_PRODUCT_CONTEXT
: {};
window.hfviewerAnalyticsBridge?.capture?.(eventName, {
product_surface: "hf_space",
space_repo: String(productContext.space_repo || "unknown"),
space_revision: String(productContext.space_revision || "unknown"),
space_host: String(window.location.hostname || "unknown").toLowerCase(),
space_deployment: currentSpaceDeployment(),
auth_provider: "hugging_face",
...properties,
});
} catch {
// Authentication must remain independent of analytics availability.
}
}
function identifyAuthenticatedUser(user, source) {
if (!user?.username) return;
try {
window.hfviewerAnalyticsBridge?.identifyHfSession?.(
{
authenticated: true,
email: user.email || "",
user: {
id: user.subject || "",
username: user.username,
name: user.name || user.username,
email: user.email || "",
},
},
source || "hf_space_native_oauth"
);
} catch {
// Consent-gated identity is best effort only.
}
}
function keepReleasePills() {
if (!authHost) return [];
return Array.from(authHost.children).filter((element) =>
element.classList.contains("hfnx-auth__pill")
);
}
function makeAvatar(user) {
if (user.picture) {
const image = document.createElement("img");
image.className = "hfnx-auth__avatar";
image.src = user.picture;
image.alt = "";
image.referrerPolicy = "no-referrer";
return image;
}
const letter = document.createElement("span");
letter.className = "hfnx-auth__avatar hfnx-auth__avatar--letter";
letter.textContent = user.username.charAt(0).toUpperCase();
return letter;
}
function makeHfviewerAccountLink(label, path, target) {
const link = document.createElement("a");
link.className = "hfnx-auth__item";
link.href = new URL(path, ACCOUNT_DESTINATION_ORIGIN).href;
link.target = "_blank";
link.rel = "noopener";
link.textContent = label;
link.setAttribute("role", "menuitem");
link.dataset.accountDestination = target;
link.dataset.accountDestinationReady = "0";
accountDestinationLinks.push(link);
link.addEventListener("click", () => {
trackAuthEvent("space_hfviewer_account_destination_opened", { target });
// The clicked handoff is single-use. Mint its replacement after the
// browser has captured this anchor's current href for native navigation.
link.dataset.accountDestinationReady = "0";
window.setTimeout(() => { void prepareAccountDestination(link); }, 0);
});
return link;
}
function liveSpaceSession() {
const session = oauthResult?.spaceSession;
const expiresAt = Number(session?.expiresAt || 0) * 1000;
if (!session?.id || !session?.secret || !expiresAt || expiresAt <= Date.now()) {
return null;
}
return session;
}
function invalidAuthResponse(code) {
const error = new Error("Sign-in is temporarily unavailable. Please try again.");
error.name = "AuthResponseError";
error.code = code;
return error;
}
function validatedLoginUrl(result, destination = false) {
if (!result || typeof result.login_url !== "string" || !result.login_url.trim()) {
throw invalidAuthResponse("missing_login_url");
}
let url;
try { url = new URL(result.login_url); }
catch { throw invalidAuthResponse("invalid_login_url"); }
const allowed = destination
? ["https://hfviewer.com", "https://www.hfviewer.com"].includes(url.origin) && url.pathname === "/api/hf_space_oauth/enter"
: url.origin === "https://huggingface.co" && url.pathname === "/oauth/authorize";
if (!allowed || url.username || url.password) throw invalidAuthResponse("invalid_login_url");
return url;
}
function authFailureCategory(error) {
if (error?.name === "AuthResponseError") return "invalid_response";
if (error?.name === "AbortError" || error?.name === "TimeoutError") return "timeout";
if (Number(error?.status)) return "http";
if (error?.name === "TypeError") return "network";
return "unknown";
}
async function prepareAccountDestination(link) {
const session = liveSpaceSession();
const destination = String(link?.dataset?.accountDestination || "");
if (!session || !destination || link.dataset.accountDestinationPreparing === "1") return;
link.dataset.accountDestinationPreparing = "1";
try {
const result = await postJson(DESTINATION_URL, {
link_session_id: session.id,
link_session_secret: session.secret,
destination,
});
const loginUrl = validatedLoginUrl(result, true);
link.href = loginUrl.toString();
link.dataset.accountDestinationReady = "1";
} catch (error) {
console.warn("Hugging Face Space account handoff preparation failed", error);
link.dataset.accountDestinationReady = "0";
trackAuthEvent("space_hf_account_destination_preparation_failed", {
user_initiated: false,
failure_category: authFailureCategory(error),
error_code: error?.code,
component: "space_account_destination",
failure_stage: "destination_prepare",
destination,
error_name: String(error?.name || "Error").slice(0, 80),
});
} finally {
link.dataset.accountDestinationPreparing = "0";
}
}
function prepareAccountDestinations() {
if (!liveSpaceSession()) {
if (oauthResult) {
oauthResult = null;
writeStoredResult(null);
renderAuth();
void prepareLogin("background_session_expired");
}
return;
}
for (const link of accountDestinationLinks) void prepareAccountDestination(link);
}
function makeOfficialSpaceLink() {
const link = document.createElement("a");
link.dataset.spaceNativeAuth = "official-space";
// Reuse the login control's class: the Space stylesheet hides every other
// child of #hfnx-auth.
link.className = "space-native-auth-login space-native-auth-official";
link.href = OFFICIAL_SPACE_URL;
link.target = "_blank";
link.rel = "noopener";
link.textContent = "Open the official hfviewer Space";
link.title = "Sign-in is available in the official hfviewer Space";
link.style.fontSize = "12px";
link.style.opacity = "0.8";
link.style.whiteSpace = "nowrap";
link.addEventListener("click", () => {
trackAuthEvent("space_clone_official_space_opened", { component: "space_nav" });
});
return link;
}
// Sign-in intent (hover, keyboard focus, press) re-prepares a missing or
// stale OAuth URL so a failed background preparation recovers before the click.
function bindLoginIntentPreparation(element) {
const prepareOnIntent = (event) => { void prepareLogin(`intent_${event.type}`); };
for (const type of ["pointerenter", "focus", "pointerdown", "touchstart"]) {
element.addEventListener(type, prepareOnIntent, type === "touchstart" ? { passive: true } : undefined);
}
}
function makeLoggedOutControl() {
if (isCloneDeployment()) return makeOfficialSpaceLink();
const link = document.createElement("a");
link.dataset.spaceNativeAuth = "login";
link.className = "space-native-auth-login";
const ready = !activeFlow && preparedFlowIsFresh();
link.textContent = activeFlow ? "Signing in…" : "Log in";
// A click that had to prepare first needs a second click to open the
// native target=_blank navigation; say so instead of looking unchanged.
if (ready && loginContinueRequested) link.textContent = "Continue to Hugging Face";
link.title = activeFlow
? "Cancel this sign-in and try again"
: "Sign in with Hugging Face";
link.href = (ready && preparedFlow?.loginUrl) || "#";
link.target = "_blank";
link.rel = "noopener";
link.setAttribute("aria-disabled", ready || activeFlow ? "false" : "true");
bindLoginIntentPreparation(link);
link.addEventListener("click", (event) => {
if (activeFlow) {
event.preventDefault();
failLogin(new Error("Sign-in cancelled"), "handoff_cancelled");
return;
}
if (!preparedFlowIsFresh()) {
event.preventDefault();
loginContinueRequested = true;
void prepareLogin("user_nav_click");
return;
}
startLogin(preparedFlow, link);
});
return link;
}
function closeNativeLoginPopover() {
const popover = nativeLoginPopover;
nativeLoginPopover = null;
if (!popover) return;
window.removeEventListener("resize", popover.reposition);
window.removeEventListener("scroll", popover.reposition, true);
document.removeEventListener("pointerdown", popover.onPointerDown, true);
document.removeEventListener("keydown", popover.onKeyDown, true);
popover.element.remove();
}
function positionNativeLoginPopover() {
const popover = nativeLoginPopover;
if (!popover?.anchor?.isConnected) {
closeNativeLoginPopover();
return;
}
const rect = popover.anchor.getBoundingClientRect();
const width = popover.element.offsetWidth || 320;
const margin = 12;
const left = Math.max(
margin,
Math.min(rect.left + rect.width / 2 - width / 2, window.innerWidth - width - margin)
);
popover.element.style.left = `${Math.round(left + window.scrollX)}px`;
popover.element.style.top = `${Math.round(rect.bottom + window.scrollY + 10)}px`;
}
function requestNativeLogin(
anchor,
{
title = "Sign in with Hugging Face",
description = "Continue to use this feature in the Space.",
intent = "protected_action",
} = {}
) {
if (userFromResult(oauthResult) && liveSpaceSession()) return false;
if (!anchor?.isConnected) return false;
closeNativeLoginPopover();
const element = document.createElement("div");
element.className = "hf-watch-popover hf-login-popover space-native-login-popover";
element.setAttribute("role", "dialog");
element.setAttribute("aria-label", title);
const close = document.createElement("button");
close.type = "button";
close.className = "hf-watch-popover__close";
close.setAttribute("aria-label", "Close");
close.textContent = "×";
const titleElement = document.createElement("p");
titleElement.className = "hf-watch-popover__title";
titleElement.textContent = title;
const descriptionElement = document.createElement("p");
descriptionElement.className = "hf-watch-popover__sub";
descriptionElement.textContent = description;
const continueLink = document.createElement("a");
continueLink.className = "hf-login-popover__btn";
continueLink.target = "_blank";
continueLink.rel = "noopener";
continueLink.setAttribute("aria-disabled", "true");
continueLink.innerHTML =
'
' +
'Preparing sign in…';
element.append(close, titleElement, descriptionElement, continueLink);
const clone = isCloneDeployment();
if (clone) {
descriptionElement.textContent = "Sign-in is only available in the official hfviewer Space.";
continueLink.href = OFFICIAL_SPACE_URL;
continueLink.setAttribute("aria-disabled", "false");
const label = continueLink.querySelector("span");
if (label) label.textContent = "Open the official hfviewer Space";
} else {
bindLoginIntentPreparation(continueLink);
}
document.body.appendChild(element);
const popover = {
element,
anchor,
intent,
continueLink,
reposition: () => positionNativeLoginPopover(),
onPointerDown: (event) => {
if (!element.contains(event.target) && !anchor.contains(event.target)) {
closeNativeLoginPopover();
}
},
onKeyDown: (event) => {
if (event.key === "Escape") closeNativeLoginPopover();
},
};
nativeLoginPopover = popover;
close.addEventListener("click", closeNativeLoginPopover);
continueLink.addEventListener("click", (event) => {
if (clone) {
trackAuthEvent("space_clone_official_space_opened", {
component: "space_native_login_popover",
login_intent: intent,
});
return;
}
if (!preparedFlowIsFresh() || activeFlow) {
event.preventDefault();
if (!activeFlow) void prepareLogin("user_continue_click").then(() => refreshNativeLoginPopover());
return;
}
trackAuthEvent("space_hf_login_continue_clicked", {
component: "space_native_login_popover",
login_intent: intent,
});
startLogin(preparedFlow, continueLink);
});
window.addEventListener("resize", popover.reposition);
window.addEventListener("scroll", popover.reposition, true);
document.addEventListener("pointerdown", popover.onPointerDown, true);
document.addEventListener("keydown", popover.onKeyDown, true);
positionNativeLoginPopover();
trackAuthEvent("space_hf_login_preflight_shown", {
component: "space_native_login_popover",
login_intent: intent,
});
if (!clone) void prepareLogin("user_preflight").then(() => refreshNativeLoginPopover());
return true;
}
function refreshNativeLoginPopover() {
const popover = nativeLoginPopover;
if (!popover) return;
if (isCloneDeployment()) {
positionNativeLoginPopover();
return;
}
if (preparedFlowIsFresh() && preparedFlow.loginUrl && !activeFlow) {
popover.continueLink.href = preparedFlow.loginUrl;
popover.continueLink.setAttribute("aria-disabled", "false");
const label = popover.continueLink.querySelector("span");
if (label) label.textContent = "Continue with Hugging Face";
}
positionNativeLoginPopover();
}
function makeLoggedInControl(user, { compact = false } = {}) {
const wrap = document.createElement("div");
wrap.dataset.spaceNativeAuth = "profile";
wrap.className = "space-native-auth-wrap";
if (compact) wrap.classList.add("space-native-auth-wrap--compact");
const chip = document.createElement("button");
chip.type = "button";
chip.className = "hfnx-auth__chip";
chip.setAttribute("aria-haspopup", "menu");
chip.setAttribute("aria-expanded", "false");
chip.appendChild(makeAvatar(user));
const label = document.createElement("span");
label.textContent = user.username;
chip.appendChild(label);
const menu = document.createElement("div");
menu.className = "hfnx-auth__menu space-native-auth-menu";
menu.setAttribute("role", "menu");
const myModels = makeHfviewerAccountLink(
"My models",
"/?my_models=1&blogs_with_graphs=1&next_landing=1",
"my_models"
);
const bookmarks = makeHfviewerAccountLink(
"Bookmarks",
"/?bookmarks=1&blogs_with_graphs=1&next_landing=1",
"bookmarks"
);
const releaseWatchlist = makeHfviewerAccountLink(
"Release watchlist",
"/?release_watchlist=1&blogs_with_graphs=1&next_landing=1",
"release_watchlist"
);
const writeArticle = makeHfviewerAccountLink(
"Write article",
"/?article_picker=1&login_intent=interactive_articles&blogs_with_graphs=1&next_landing=1",
"write_article"
);
const logout = document.createElement("button");
logout.type = "button";
logout.className = "hfnx-auth__item";
logout.textContent = "Log out";
logout.setAttribute("role", "menuitem");
logout.addEventListener("click", () => {
trackAuthEvent("space_hf_logout");
oauthResult = null;
writeStoredResult(null);
renderAuth();
// Logged-in page loads intentionally do not prepare an OAuth flow. Once
// the profile is cleared, prepare one immediately so the replacement Log
// in control is a real link on the first click.
void prepareLogin("background_post_logout");
});
const setOpen = (open) => {
menu.classList.toggle("is-open", open);
chip.setAttribute("aria-expanded", open ? "true" : "false");
};
chip.addEventListener("click", (event) => {
event.stopPropagation();
setOpen(!menu.classList.contains("is-open"));
});
document.addEventListener("click", () => setOpen(false));
menu.append(myModels, bookmarks, releaseWatchlist, writeArticle, logout);
wrap.append(chip, menu);
return wrap;
}
function renderAuth() {
if ((!authHost && !compactAuthHost) || rendering) return;
rendering = true;
accountDestinationLinks = [];
const pills = keepReleasePills();
const user = userFromResult(oauthResult);
if (authHost) {
authHost.replaceChildren(...pills, user ? makeLoggedInControl(user) : makeLoggedOutControl());
}
if (compactAuthHost) {
compactAuthHost.replaceChildren();
compactAuthHost.hidden = !user;
if (user) compactAuthHost.appendChild(makeLoggedInControl(user, { compact: true }));
}
queueMicrotask(() => {
rendering = false;
prepareAccountDestinations();
announceAuthState();
});
}
function applyOauthResult(callbackResult, source) {
oauthResult = callbackResult;
writeStoredResult(callbackResult);
activeFlow = null;
renderAuth();
closeNativeLoginPopover();
const user = userFromResult(callbackResult);
identifyAuthenticatedUser(user, source);
trackAuthEvent("space_hf_login_completed", {
component: "space_nav",
username_present: !!user?.username,
subject_present: !!user?.subject,
email_present: !!user?.email,
});
}
function failLogin(error, failureStage) {
console.warn("Hugging Face Space login failed", error);
activeFlow = null;
renderAuth();
trackAuthEvent(failureStage === "handoff_cancelled" ? "space_hf_login_cancelled" : "space_hf_login_failed", {
user_initiated: true,
failure_category: authFailureCategory(error),
component: "space_nav",
failure_stage: failureStage,
error_name: String(error?.name || "Error").slice(0, 80),
error_message: String(error?.message || "Unknown error").slice(0, 240),
request_status: Number(error?.status || 0) || undefined,
});
void prepareLogin("background_after_login_failure");
}
function delay(milliseconds) {
return new Promise((resolve) => window.setTimeout(resolve, milliseconds));
}
function isUserPreparationTrigger(trigger) {
return String(trigger || "").startsWith("user_");
}
function schedulePrepareRecovery(trigger) {
if (prepareRecoveryTimer || oauthResult || activeFlow) return;
// Bounded backoff: once the schedule is exhausted this page stops trying
// until the next sign-in intent.
if (prepareFailureCount >= PREPARE_RECOVERY_DELAYS_MS.length) return;
const recoveryDelay = PREPARE_RECOVERY_DELAYS_MS[prepareFailureCount];
prepareFailureCount += 1;
prepareRecoveryTimer = window.setTimeout(() => {
prepareRecoveryTimer = null;
void prepareLogin(
isUserPreparationTrigger(trigger) ? "user_recovery" : "background_recovery"
);
}, recoveryDelay);
}
function retryableRequestError(error) {
return (
error?.name === "AuthResponseError" ||
error?.name === "TypeError" ||
error?.name === "AbortError" ||
[408, 425, 429, 500, 502, 503, 504].includes(Number(error?.status || 0))
);
}
async function postJson(url, body, { retryDelays = [0], validate = null } = {}) {
let lastError = null;
for (let attempt = 0; attempt < retryDelays.length; attempt += 1) {
if (retryDelays[attempt] > 0) await delay(retryDelays[attempt]);
const controller = new AbortController();
const timer = window.setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
try {
const response = await fetch(url, {
method: "POST",
mode: "cors",
credentials: "omit",
headers: { "content-type": "application/json" },
body: JSON.stringify(body),
signal: controller.signal,
});
let payload;
try { payload = await response.json(); }
catch {
const error = invalidAuthResponse("invalid_json");
if (!response.ok) error.status = response.status;
throw error;
}
if (!response.ok && response.status !== 202) {
const error = new Error(payload?.error || `Request failed (${response.status})`);
error.status = response.status;
throw error;
}
if (!payload || typeof payload !== "object" || Array.isArray(payload)) throw invalidAuthResponse("invalid_payload");
validate?.(payload);
return payload;
} catch (error) {
error.retryCount = attempt;
lastError = error;
if (!retryableRequestError(error) || attempt === retryDelays.length - 1) throw error;
} finally {
window.clearTimeout(timer);
}
}
throw lastError || new Error("Request failed");
}
function announceAuthState() {
const user = userFromResult(oauthResult);
const session = liveSpaceSession();
const identity = user && session ? `${user.subject || user.username}:${session.id}` : "";
if (identity === lastAnnouncedAuthIdentity) return;
lastAnnouncedAuthIdentity = identity;
window.dispatchEvent(
new CustomEvent(AUTH_CHANGED_EVENT, {
detail: {
authenticated: !!identity,
username: user?.username || "",
},
})
);
}
async function postAuthenticatedSpaceJson(url, payload) {
const session = liveSpaceSession();
if (!session) throw new Error("The Space login expired. Please sign in again.");
try {
return await postJson(url, {
...(payload || {}),
link_session_id: session.id,
link_session_secret: session.secret,
});
} catch (error) {
if (/login expired|session expired|invalid|unauthorized/i.test(String(error?.message || ""))) {
oauthResult = null;
writeStoredResult(null);
renderAuth();
void prepareLogin("background_session_expired");
}
throw error;
}
}
window.hfviewerSpaceAuth = Object.freeze({
isAuthenticated: () => !!userFromResult(oauthResult) && !!liveSpaceSession(),
postJson: postAuthenticatedSpaceJson,
requestLogin: requestNativeLogin,
});
async function pollForCompletion(flow) {
while (activeFlow === flow && Date.now() - flow.startedAt < FLOW_TIMEOUT_MS) {
try {
const result = await postJson(CONSUME_URL, {
flow_id: flow.id,
flow_secret: flow.secret,
});
if (result?.status === "complete" && userFromResult(result)) {
applyOauthResult(
{ userInfo: result.userInfo, spaceSession: result.spaceSession },
"hf_space_native_oauth_handoff"
);
return;
}
} catch (error) {
failLogin(error, "handoff_consume");
return;
}
await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS));
}
if (activeFlow === flow) failLogin(new Error("OAuth flow timed out"), "handoff_timeout");
}
function schedulePreparedFlowExpiry(flow) {
if (preparedFlowExpiryTimer) window.clearTimeout(preparedFlowExpiryTimer);
// A prepared URL is only valid for a few minutes. Replace it as it expires
// so the Log in control stays a real link: the sign-in must open from the
// user's first click (native target=_blank), which an async fetch cannot do.
preparedFlowExpiryTimer = window.setTimeout(() => {
preparedFlowExpiryTimer = null;
if (preparedFlow !== flow || activeFlow) return;
preparedFlow = null;
renderAuth();
void prepareLogin("background_scheduled").then(() => refreshNativeLoginPopover());
}, PREPARE_REFRESH_MS);
}
function startLogin(flow, link) {
flow.startedAt = Date.now();
activeFlow = flow;
preparedFlow = null;
loginContinueRequested = false;
// Keep the clicked anchor alive until the browser has performed its native
// target=_blank navigation. Replacing it synchronously can cancel the popup.
link.textContent = "Signing in…";
link.title = "Cancel this sign-in and try again";
link.setAttribute("aria-disabled", "false");
trackAuthEvent("space_hf_login_clicked", { component: "space_nav" });
void pollForCompletion(flow);
}
async function prepareLogin(trigger = "background_initial") {
if (oauthResult || activeFlow) return;
// Authentication is intentionally available only in the two official
// deployments. A fork can copy our declared space_repo value, but it cannot
// claim an official browser origin and must never generate misleading auth
// failures or receive a trusted handoff.
if (
window.location.hostname.endsWith(".hf.space") &&
!OFFICIAL_SPACE_HOSTS.has(window.location.hostname.toLowerCase())
) return;
if (preparedFlowIsFresh()) return;
if (preparePromise) {
if (isUserPreparationTrigger(trigger)) prepareIntentEscalated = true;
return preparePromise;
}
if (!isUserPreparationTrigger(trigger)) {
if (backgroundPrepareAttempts >= PREPARE_MAX_BACKGROUND_ATTEMPTS) return;
backgroundPrepareAttempts += 1;
}
const prepareStartedAt = performance.now();
preparePromiseTrigger = String(trigger || "background_initial");
prepareIntentEscalated = isUserPreparationTrigger(preparePromiseTrigger);
const flow = {
id: randomFlowValue(),
secret: randomFlowValue(),
preparedAt: Date.now(),
startedAt: 0,
loginUrl: "",
};
preparePromise = postJson(
START_URL,
{ flow_id: flow.id, flow_secret: flow.secret },
{ retryDelays: PREPARE_RETRY_DELAYS_MS, validate: validatedLoginUrl }
).then((result) => {
const loginUrl = validatedLoginUrl(result);
flow.loginUrl = loginUrl.toString();
preparedFlow = flow;
const recoveredFailureCount = prepareFailureCount;
const recoveredFromFailure = prepareFailureEpisodeActive;
if (!prepareSuccessReported || recoveredFromFailure || prepareIntentEscalated) {
trackAuthEvent("space_hf_login_prepared", {
component: "space_nav",
preparation_trigger: preparePromiseTrigger,
user_initiated: prepareIntentEscalated,
duration_ms: Math.max(0, Math.round(performance.now() - prepareStartedAt)),
recovered_from_failure: recoveredFromFailure,
recovery_count: recoveredFailureCount,
});
}
prepareSuccessReported = true;
prepareFailureEpisodeActive = false;
prepareFailureCount = 0;
backgroundPrepareAttempts = 0;
if (prepareRecoveryTimer) window.clearTimeout(prepareRecoveryTimer);
prepareRecoveryTimer = null;
schedulePreparedFlowExpiry(flow);
if (!activeFlow) renderAuth();
refreshNativeLoginPopover();
}).catch((error) => {
console.warn("Hugging Face Space login preparation failed", error);
// Background/intent preparation is operational prewarm telemetry, not a
// failed login attempt: report it at most once per page load. A user who
// explicitly asked to sign in is reported per failure, up to a small cap.
const reportFailure = prepareIntentEscalated
? userPrepareFailureReports < PREPARE_MAX_USER_FAILURE_REPORTS
: !backgroundPrepareFailureReported && !prepareFailureEpisodeActive;
if (reportFailure) {
if (prepareIntentEscalated) userPrepareFailureReports += 1;
else backgroundPrepareFailureReported = true;
trackAuthEvent("space_hf_login_preparation_failed", {
component: "space_nav",
failure_stage: "login_prepare",
preparation_trigger: preparePromiseTrigger,
user_initiated: prepareIntentEscalated,
error_name: String(error?.name || "Error").slice(0, 80),
error_message: String(error?.message || "Unknown error").slice(0, 240),
request_status: Number(error?.status || 0) || undefined,
failure_category: authFailureCategory(error),
error_code: error?.code,
retry_count: error?.retryCount || 0,
recovery_count: prepareFailureCount,
});
}
prepareFailureEpisodeActive = true;
schedulePrepareRecovery(preparePromiseTrigger);
}).finally(() => {
preparePromise = null;
preparePromiseTrigger = "";
prepareIntentEscalated = false;
});
return preparePromise;
}
async function initializeApp() {
renderAuth();
identifyAuthenticatedUser(userFromResult(oauthResult), "hf_space_native_oauth_restored");
await prepareLogin("background_initial");
}
if (authHost) {
const observer = new MutationObserver(() => {
if (!rendering && !authHost.querySelector("[data-space-native-auth]")) renderAuth();
});
observer.observe(authHost, { childList: true });
}
window.addEventListener("storage", (event) => {
if (event.key !== STORAGE_KEY) return;
oauthResult = readStoredResult();
renderAuth();
});
window.setInterval(() => {
void prepareLogin("background_scheduled");
prepareAccountDestinations();
}, PREPARE_REFRESH_MS);
void initializeApp();