Spaces:
Running
Running
| // Login with Hugging Face OAuth | |
| import { oauthHandleRedirectIfPresent, oauthLoginUrl } from "@huggingface/hub"; | |
| import { InferenceClient } from "@huggingface/inference"; | |
| import { useEffect, useRef, useState } from "react"; | |
| export default function OAuthLogin({ onHFClientReady }) { | |
| const [loading, setLoading] = useState(false); | |
| const [error, setError] = useState(""); | |
| const [oauthResult, setOAuthResult] = useState(null); | |
| const [userInfo, setUserInfo] = useState(null); | |
| const oauthHandled = useRef(false); | |
| const stableOnHFClientReady = useRef(onHFClientReady); | |
| useEffect(() => { | |
| // Prevent handling OAuth twice in Strict Mode | |
| if (oauthHandled.current) return; | |
| oauthHandled.current = true; | |
| (async () => { | |
| setLoading(true); | |
| try { | |
| const result = await oauthHandleRedirectIfPresent(); | |
| if (!result) return; | |
| setOAuthResult(result); | |
| setError(""); | |
| } catch (err) { | |
| setError(err.message); | |
| } finally { | |
| setLoading(false); | |
| } | |
| })(); | |
| }, []); | |
| useEffect(() => { | |
| stableOnHFClientReady.current = onHFClientReady; | |
| }, [onHFClientReady]); | |
| useEffect(() => { | |
| if (oauthResult) { | |
| try { | |
| const client = new InferenceClient(oauthResult.accessToken); | |
| stableOnHFClientReady.current(client); | |
| setUserInfo(oauthResult.userInfo); | |
| setError(""); | |
| } catch (err) { | |
| setError(err.message); | |
| } | |
| } | |
| }, [oauthResult]); | |
| const handleLogin = async () => { | |
| if (window.location.hostname.endsWith(".hf.space")) { | |
| window.location.href = await oauthLoginUrl(); | |
| } else { | |
| window.location.href = await oauthLoginUrl({ | |
| clientId: "d9a24fb2-1e7c-4a57-ace3-c75fa6a99305", | |
| redirectUrl: window.location.origin, | |
| scopes: ["inference-api"], | |
| }); | |
| } | |
| }; | |
| return ( | |
| <div style={{ padding: "20px" }}> | |
| {userInfo ? ( | |
| <div> | |
| <p> | |
| ✅ {userInfo.name || userInfo.email} has successfully logged in! | |
| </p> | |
| </div> | |
| ) : loading ? ( | |
| <p>🔄 Authenticating with Hugging Face…</p> | |
| ) : ( | |
| <button onClick={handleLogin} style={{ padding: "10px 20px" }}> | |
| Login with Hugging Face | |
| </button> | |
| )} | |
| {error && <p style={{ color: "red" }}>{error}</p>} | |
| </div> | |
| ); | |
| } | |