Deal with OAuth too many redirects (#8951)

* Deal with OAuth too many redirects

* add changeset

* Redirect to non-iframe view in case of redirect

* add changeset

* apply suggestions

* use constant for MAX_REDIRECTS

* lint

---------

Co-authored-by: gradio-pr-bot <gradio-pr-bot@users.noreply.github.com>
Co-authored-by: Abubakar Abid <abubakar@huggingface.co>
This commit is contained in:
Lucain 2024-08-15 23:07:08 +02:00 committed by GitHub
parent 8a3e1e289e
commit 6e7d9e5b84
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 35 additions and 9 deletions

View File

@ -0,0 +1,5 @@
---
"gradio": patch
---
fix:Deal with OAuth too many redirects

View File

@ -19,6 +19,8 @@ OAUTH_CLIENT_SECRET = os.environ.get("OAUTH_CLIENT_SECRET")
OAUTH_SCOPES = os.environ.get("OAUTH_SCOPES")
OPENID_PROVIDER_URL = os.environ.get("OPENID_PROVIDER_URL")
MAX_REDIRECTS = 2
def attach_oauth(app: fastapi.FastAPI):
try:
@ -105,18 +107,37 @@ def _add_oauth_routes(app: fastapi.FastAPI) -> None:
# repeatedly. Since cookies cannot get bigger than 4kb, the token will be truncated at some point - hence
# losing the state. A workaround is to delete the cookie and redirect the user to the login page again.
# See https://github.com/lepture/authlib/issues/622 for more details.
login_uri = "/login/huggingface"
if "_target_url" in request.query_params:
login_uri += (
"?"
+ urllib.parse.urlencode( # Keep same _target_url as before
{"_target_url": request.query_params["_target_url"]}
)
)
# Delete all keys that are related to the OAuth state, just in case
for key in list(request.session.keys()):
# Delete all keys that are related to the OAuth state
if key.startswith("_state_huggingface"):
request.session.pop(key)
# Parse query params
nb_redirects = int(request.query_params.get("_nb_redirects", 0))
target_url = request.query_params.get("_target_url")
# Build /login URI with the same query params as before and bump nb_redirects count
query_params: dict[str, str | int] = {"_nb_redirects": nb_redirects + 1}
if target_url:
query_params["_target_url"] = target_url
login_uri = f"/login/huggingface?{urllib.parse.urlencode(query_params)}"
# If the user is redirected more than 3 times, it is very likely that the cookie is not working properly.
# (e.g. browser is blocking third-party cookies in iframe). In this case, redirect the user in the
# non-iframe view.
if nb_redirects > MAX_REDIRECTS:
host = os.environ.get("SPACE_HOST")
if host is None: # cannot happen in a Space
raise RuntimeError(
"Gradio is not running in a Space (SPACE_HOST environment variable is not set)."
" Cannot redirect to non-iframe view."
) from None
host_url = "https://" + host.rstrip("/")
return RedirectResponse(host_url + login_uri)
# Redirect the user to the login page again
return RedirectResponse(login_uri)
# OAuth login worked => store the user info in the session and redirect