Window.huggingface is undefined when trying to reproduce client side OAuth example

Hi

Tl;Dr: I am a bit of a web dev noob and I am having issues reproducing client side HF OAuth tutorial.

The bigger picture: I am trying to do an app with fastHTML but I need some oauth.

Details: I am trying to reproduce: Client Side Oauth - a Hugging Face Space by huggingfacejs but examining the console I get an error. Culprit? window.huggingface variable is undefined. Can’t shake it, no matter what I tried.

What I did locally:

  • created a hf git repo
  • created a bare minimum app with fastHTML
  • configured readme, requirements, dockerfile, docker,
  • tested locally, it got built but window.huggingface is undefined. Fair enough, there is nobody to populate it
  • The rest of bare minimum functions are ok. (it shows stuff on the webpage)

Pushed to HF:

  • build went ok,
  • app launched,
  • in console, window.huggingface variable is undefined.
  • When clicking “Sign in with HF”, the console shows an error.

HOWEVER, the Client Side Oauth - a Hugging Face Space by huggingfacejs app has the window.huggingface happily configured, when examining its browser console.

My local output of the index.html, as it is generated by FastHTML is below:

<html><head>
    <title>C code reviewing</title>
    <script src="https://unpkg.com/es-module-shims@1.7.0/dist/es-module-shims.js"></script>
    <script type="importmap">
{
    "imports": {
        "@huggingface/hub": "https://cdn.jsdelivr.net/npm/@huggingface/hub@0.13.0/+esm"
    }
}
</script>
  </head>
  <body>
    <div>
      <p>Some content</p>
    </div>
    <pre></pre>
    <img src="https://huggingface.co/datasets/huggingface/badges/resolve/main/sign-in-with-huggingface-xl-dark.svg" alt="Sign in with Hugging Face" id="signin" style="cursor: pointer;" name="signin">
    <button id="signout" style="display: none" name="signout">Sign out</button>
    <a href="authorized">Authenticate!</a>
    <script type="module">
import { oauthLoginUrl, oauthHandleRedirectIfPresent } from "@huggingface/hub";
console.log("huggingface env", window.huggingface);
let oauthResult = localStorage.getItem("oauth");
if (oauthResult) {
  try {
    oauthResult = JSON.parse(oauthResult);
  } catch {
    oauthResult = null;
  }
}

oauthResult ||= await oauthHandleRedirectIfPresent();
if (oauthResult) {
  document.querySelector("pre").textContent = JSON.stringify(oauthResult, null, 2);
  localStorage.setItem("oauth", JSON.stringify(oauthResult));
  document.getElementById("signout").style.removeProperty("display");
  document.getElementById("signout").onclick = async function() {
    localStorage.removeItem("oauth");
    window.location.href = window.location.href.replace(/\?.*$/, '');
    window.location.reload();
  }
} else {
  document.getElementById("signin").style.removeProperty("display");
  document.getElementById("signin").onclick = async function() {
    // prompt=consent to re-trigger the consent screen instead of silently redirecting
    window.location.href = (await oauthLoginUrl({scopes: window.huggingface.variables.OAUTH_SCOPES})) + "&prompt=consent";
  }
}
</script>
  

</body></html>

Infringing line: console.log("huggingface env", window.huggingface);. It shows undefined in browser’s console.

Of course, the window.location.href = (await oauthLoginUrl({scopes: window.huggingface.variables.OAUTH_SCOPES})) + "&prompt=consent" triggers an error in the console:

TypeError: Cannot read properties of undefined (reading 'variables')
    at document.getElementById.onclick (?__sign=ey[...]__bGP-Bg:47:77)

Examining the Space html is a bit of a mess, can’t figure out how to separate it from the enclosing iframe so I attached the local output.

For reference, my code:

readme.md:

---
title: C Reviewer
emoji: ⚡
colorFrom: yellow
colorTo: gray
sdk: docker
pinned: false
license: mit
hf_oauth: true
hf_oauth_expiration_minutes: 480
hf_oauth_scopes:
- email
---

Dockerfile:

FROM python:3.11
RUN useradd -m -u 1000 user
WORKDIR /code
COPY --link --chown=1000 . .
RUN mkdir -p /tmp/cache/
RUN chmod a+rwx -R /tmp/cache/
ENV HF_HUB_CACHE=HF_HOME
RUN pip install --no-cache-dir -r requirements.txt
ENV PYTHONUNBUFFERED=1 PORT=7860
CMD ["python", "main.py"]

main.py:

from fasthtml.common import *

app, rt = fast_app()

js_hf_imports = \
    """
{
    "imports": {
        "@huggingface/hub": "https://cdn.jsdelivr.net/npm/@huggingface/hub@0.13.0/+esm"
    }
}
"""

js_block_hf_auth = \
    """
import { oauthLoginUrl, oauthHandleRedirectIfPresent } from "@huggingface/hub";
console.log("huggingface env", window.huggingface);
let oauthResult = localStorage.getItem("oauth");
if (oauthResult) {
  try {
    oauthResult = JSON.parse(oauthResult);
  } catch {
    oauthResult = null;
  }
}

oauthResult ||= await oauthHandleRedirectIfPresent();
if (oauthResult) {
  document.querySelector("pre").textContent = JSON.stringify(oauthResult, null, 2);
  localStorage.setItem("oauth", JSON.stringify(oauthResult));
  document.getElementById("signout").style.removeProperty("display");
  document.getElementById("signout").onclick = async function() {
    localStorage.removeItem("oauth");
    window.location.href = window.location.href.replace(/\?.*$/, '');
    window.location.reload();
  }
} else {
  document.getElementById("signin").style.removeProperty("display");
  document.getElementById("signin").onclick = async function() {
    // prompt=consent to re-trigger the consent screen instead of silently redirecting
    window.location.href = (await oauthLoginUrl({scopes: window.huggingface.variables.OAUTH_SCOPES})) + "&prompt=consent";
  }
}
"""


def get_hf_user_data():
    pass


@rt('/', methods="get")
def get():
    header = Head(Title("C code reviewing"),
                  Script(src="https://unpkg.com/es-module-shims@1.7.0/dist/es-module-shims.js"),
                  Script(js_hf_imports, type="importmap"),
                  )
    content = Body(Div(P("Some content")),
                   Pre(""),
                   Img(src="https://huggingface.co/datasets/huggingface/badges/resolve/main/sign-in-with-huggingface-xl-dark.svg",
                       alt="Sign in with Hugging Face",
                       style="cursor: pointer; display: none;",
                       _id = "signin", name=None),
                   Button("Sign out",_id="signout", style="display: none", name=None),
                   A("Authenticate!", href="authorized"),
                   Script(js_block_hf_auth, type="module"))
    full_page = Html(header, content)
    return full_page

@rt('/change')
def get(): return P('Nice to be here!')

@rt('/authorized', methods="get")
def authorized():
    content = Body(P("Do we have authenticated user?"))
    return content

serve()

Am I missing something from reproducing the index.html and I am too tired to see it?
Magic constants injection in window.huggingface does not work when served from docker?
Cut my losses and start with gradio?

Thank you!

p.s.
As a lean “preacher” I started with the riskiest things first, that is, from all the features that I want my app to have, this appears to be the messiest, even if it is not the first needed.

Magic constants injection in window.huggingface does not work when served from docker?

Probably yes:

“When called from inside a static Space with OAuth enabled, it will load the config from the space, otherwise you need to at least specify the client ID of your OAuth App.”

So, constructing the function call from backend, where I have access to OAUTH_CLIENT_ID and OAUTH_SCOPES.

Well, every day is a new day to bang head against webdev.

This topic was automatically closed 12 hours after the last reply. New replies are no longer allowed.