From de8492de345145be73f1a088ddcf7f0c2908f3ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=98=9F=E6=B5=B7?= <62863922+xinhai-ai@users.noreply.github.com> Date: Thu, 20 Feb 2025 15:06:07 +0800 Subject: [PATCH] fix: GitHub OAuth email retrieval when public email is not set --- backend/open_webui/utils/oauth.py | 32 ++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/backend/open_webui/utils/oauth.py b/backend/open_webui/utils/oauth.py index ad0a9407b..8674ad64b 100644 --- a/backend/open_webui/utils/oauth.py +++ b/backend/open_webui/utils/oauth.py @@ -246,11 +246,37 @@ class OAuthManager: raise HTTPException(400, detail=ERROR_MESSAGES.INVALID_CRED) provider_sub = f"{provider}@{sub}" email_claim = auth_manager_config.OAUTH_EMAIL_CLAIM - email = user_data.get(email_claim, "").lower() + email = user_data.get(email_claim, "") # We currently mandate that email addresses are provided if not email: - log.warning(f"OAuth callback failed, email is missing: {user_data}") - raise HTTPException(400, detail=ERROR_MESSAGES.INVALID_CRED) + # If the provider is GitHub,and public email is not provided, we can use the access token to fetch the user's email + if provider == "github": + try: + access_token = token.get("access_token") + headers = { + "Authorization": f"Bearer {access_token}" + } + async with aiohttp.ClientSession() as session: + async with session.get("https://api.github.com/user/emails", headers=headers) as resp: + if resp.ok: + emails = await resp.json() + # use the primary email as the user's email + primary_email = next((e["email"] for e in emails if e.get("primary")), None) + if primary_email: + email = primary_email + else: + log.warning("No primary email found in GitHub response") + raise HTTPException(400, detail=ERROR_MESSAGES.INVALID_CRED) + else: + log.warning("Failed to fetch GitHub email") + raise HTTPException(400, detail=ERROR_MESSAGES.INVALID_CRED) + except Exception as e: + log.warning(f"Error fetching GitHub email: {e}") + raise HTTPException(400, detail=ERROR_MESSAGES.INVALID_CRED) + else: + log.warning(f"OAuth callback failed, email is missing: {user_data}") + raise HTTPException(400, detail=ERROR_MESSAGES.INVALID_CRED) + email = email.lower() if ( "*" not in auth_manager_config.OAUTH_ALLOWED_DOMAINS and email.split("@")[-1] not in auth_manager_config.OAUTH_ALLOWED_DOMAINS