react-chatbot-test / src /components /OAuthLogin.jsx
ferrywuai's picture
Replace manual token input with Hugging Face OAuth login
a9b2457
// 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>
);
}