dylanebert's picture
dylanebert HF Staff
initial commit
794cf6c
import { writable, get } from "svelte/store";
import {
oauthLoginUrl,
oauthHandleRedirectIfPresent,
type UserInfo,
} from "@huggingface/hub";
export interface AuthState {
isAuthenticated: boolean;
user: UserInfo | null;
accessToken: string | null;
expiresAt: number | null;
loading: boolean;
error: string | null;
}
function createAuthStore() {
const { subscribe, set, update } = writable<AuthState>({
isAuthenticated: false,
user: null,
accessToken: null,
expiresAt: null,
loading: true,
error: null,
});
const getOAuthConfig = () => {
const isProduction = window.location.hostname.includes("hf.space");
const clientId = "87f5f1d1-6e9e-4962-98f0-e5f3831ec988";
let redirectUrl: string;
if (isProduction) {
redirectUrl = `https://${window.location.hostname}/auth/callback`;
} else {
redirectUrl = `http://localhost:7860/auth/callback`;
}
return {
clientId,
redirectUrl,
scopes: "openid profile inference-api",
};
};
return {
subscribe,
async init() {
update((state) => ({ ...state, loading: true }));
try {
const oauthResult = await oauthHandleRedirectIfPresent();
if (oauthResult) {
const { accessToken, accessTokenExpiresAt, userInfo } = oauthResult;
set({
isAuthenticated: true,
user: userInfo,
accessToken,
expiresAt: accessTokenExpiresAt
? accessTokenExpiresAt.getTime()
: null,
loading: false,
error: null,
});
sessionStorage.setItem(
"hf_auth",
JSON.stringify({
accessToken,
expiresAt: accessTokenExpiresAt
? accessTokenExpiresAt.getTime()
: null,
user: userInfo,
}),
);
return true;
}
const stored = sessionStorage.getItem("hf_auth");
if (stored) {
const authData = JSON.parse(stored);
if (!authData.expiresAt || authData.expiresAt > Date.now()) {
set({
isAuthenticated: true,
user: authData.user,
accessToken: authData.accessToken,
expiresAt: authData.expiresAt,
loading: false,
error: null,
});
return true;
} else {
sessionStorage.removeItem("hf_auth");
}
}
set({
isAuthenticated: false,
user: null,
accessToken: null,
expiresAt: null,
loading: false,
error: null,
});
return false;
} catch (error) {
console.error("Auth initialization error:", error);
set({
isAuthenticated: false,
user: null,
accessToken: null,
expiresAt: null,
loading: false,
error:
error instanceof Error ? error.message : "Authentication failed",
});
return false;
}
},
async login() {
const config = getOAuthConfig();
try {
const url = await oauthLoginUrl({
clientId: config.clientId,
redirectUrl: config.redirectUrl,
scopes: config.scopes,
});
window.location.href = url;
} catch (error) {
console.error("Login error:", error);
update((state) => ({
...state,
error: error instanceof Error ? error.message : "Login failed",
}));
}
},
logout() {
sessionStorage.removeItem("hf_auth");
set({
isAuthenticated: false,
user: null,
accessToken: null,
expiresAt: null,
loading: false,
error: null,
});
},
getToken(): string | null {
const state = get({ subscribe });
return state.accessToken;
},
isTokenValid(): boolean {
const state = get({ subscribe });
if (!state.accessToken) return false;
if (!state.expiresAt) return true;
return state.expiresAt > Date.now();
},
};
}
export const authStore = createAuthStore();