From 9b727ac9caf96b78322c0e1e9f24e21aadb3a50d Mon Sep 17 00:00:00 2001 From: Untone Date: Sun, 28 Sep 2025 20:34:26 +0300 Subject: [PATCH] oauth-fix --- auth/oauth.py | 63 +++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 46 insertions(+), 17 deletions(-) diff --git a/auth/oauth.py b/auth/oauth.py index e72e01cf..569c63cf 100644 --- a/auth/oauth.py +++ b/auth/oauth.py @@ -2,6 +2,7 @@ import time from secrets import token_urlsafe from typing import Any, Callable +import httpx import orjson from authlib.integrations.starlette_client import OAuth from authlib.oauth2.rfc7636 import create_s256_code_challenge @@ -686,14 +687,30 @@ async def oauth_callback_http(request: Request) -> JSONResponse | RedirectRespon logger.info(f"🔧 Using OAuth without PKCE for {provider}") logger.info(f"🔧 Callback URI: {callback_uri}") - # Используем более низкоуровневый подход для передачи redirect_uri - token = await client.fetch_token( - client.token_endpoint, - grant_type="authorization_code", - code=code, - redirect_uri=callback_uri, - client_id=client.client_id, - ) + # Используем внутренний HTTP клиент для прямого запроса к token endpoint + + token_data = { + "grant_type": "authorization_code", + "code": code, + "redirect_uri": callback_uri, + "client_id": client.client_id, + } + + # Для некоторых провайдеров может потребоваться client_secret + if hasattr(client, "client_secret") and client.client_secret: + token_data["client_secret"] = client.client_secret + + async with httpx.AsyncClient() as http_client: + response = await http_client.post( + client.token_endpoint, data=token_data, headers={"Accept": "application/json"} + ) + + if response.status_code != 200: + error_msg = f"Token request failed: {response.status_code} - {response.text}" + logger.error(f"❌ {error_msg}") + raise ValueError(error_msg) + + token = response.json() else: # Провайдеры с PKCE поддержкой code_verifier = oauth_data.get("code_verifier") @@ -705,15 +722,27 @@ async def oauth_callback_http(request: Request) -> JSONResponse | RedirectRespon logger.info(f"🔧 Code verifier length: {len(code_verifier) if code_verifier else 0}") logger.info(f"🔧 Callback URI: {callback_uri}") - # Используем более низкоуровневый подход для передачи redirect_uri - token = await client.fetch_token( - client.token_endpoint, - grant_type="authorization_code", - code=code, - redirect_uri=callback_uri, - code_verifier=code_verifier, - client_id=client.client_id, - ) + # Используем внутренний HTTP клиент для прямого запроса к token endpoint + + token_data = { + "grant_type": "authorization_code", + "code": code, + "redirect_uri": callback_uri, + "client_id": client.client_id, + "code_verifier": code_verifier, + } + + async with httpx.AsyncClient() as http_client: + response = await http_client.post( + client.token_endpoint, data=token_data, headers={"Accept": "application/json"} + ) + + if response.status_code != 200: + error_msg = f"Token request failed: {response.status_code} - {response.text}" + logger.error(f"❌ {error_msg}") + raise ValueError(error_msg) + + token = response.json() except Exception as e: logger.error(f"❌ Failed to fetch access token for {provider}: {e}", exc_info=True) logger.error(f"❌ Request URL: {request.url}")