Skip to content

Commit 95a3fcd

Browse files
committed
oauth fix for real??
1 parent 068ae72 commit 95a3fcd

4 files changed

Lines changed: 46 additions & 7 deletions

File tree

.env.example

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,12 @@ GOOGLE_CLIENT_SECRET=
115115
FRONTEND_URL=http://localhost:5173
116116
BACKEND_URL=http://localhost:5001
117117

118+
# API_URL is used for OAuth redirect_uri construction in production
119+
# CRITICAL: Set this to your actual production backend URL (with https://)
120+
# Example: API_URL=https://papers2code.onrender.com
121+
# If not set, defaults to http://localhost:5001
122+
API_URL=http://localhost:5001
123+
118124
# ---------------------------------------------
119125
# Email Configuration
120126
# ---------------------------------------------

papers2code_app2/services/github_oauth_service.py

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,9 @@ def prepare_github_login_redirect(self, request: Request) -> RedirectResponse:
5555

5656
# For production, use explicit environment variable
5757
# For development, construct from request
58-
if config_settings.ENV_TYPE == "production" and config_settings.API_URL and "localhost" not in config_settings.API_URL:
58+
is_production = config_settings.ENV_TYPE == "production"
59+
60+
if is_production and config_settings.API_URL and "localhost" not in config_settings.API_URL:
5961
redirect_uri = f"{config_settings.API_URL.rstrip('/')}/api/auth/github/callback"
6062
logger.info(f"GitHub OAuth (production): Using explicit API_URL: {redirect_uri}")
6163
else:
@@ -64,11 +66,16 @@ def prepare_github_login_redirect(self, request: Request) -> RedirectResponse:
6466
if not redirect_uri.startswith("http"):
6567
base_url = str(request.base_url).rstrip('/')
6668
redirect_uri = f"{base_url}/api/auth/github/callback"
67-
logger.info(f"GitHub OAuth (dev): Using request.url_for: {redirect_uri}")
69+
logger.info(f"GitHub OAuth: Using request.url_for: {redirect_uri}")
6870
except Exception as e:
6971
logger.error(f"Error constructing redirect_uri: {e}")
7072
raise OAuthException(detail="Error preparing authentication request to GitHub.")
7173

74+
# CRITICAL: Ensure HTTPS in production (belt-and-suspenders with proxy_headers)
75+
if is_production and redirect_uri.startswith("http://"):
76+
redirect_uri = redirect_uri.replace("http://", "https://", 1)
77+
logger.info(f"GitHub OAuth: Forced HTTPS in production: {redirect_uri}")
78+
7279
# Diagnostic logging - VERY detailed for debugging
7380
logger.info(f"[GITHUB_OAUTH_DEBUG] redirect_uri = '{redirect_uri}'")
7481
logger.info(f"[GITHUB_OAUTH_DEBUG] redirect_uri length = {len(redirect_uri)}")
@@ -146,7 +153,9 @@ async def handle_github_callback(
146153
return RedirectResponse(url=f"{frontend_url}/?login_error=github_no_code", status_code=307)
147154

148155
# Match the same construction as prepare_github_login_redirect
149-
if config_settings.ENV_TYPE == "production" and config_settings.API_URL and "localhost" not in config_settings.API_URL:
156+
is_production = config_settings.ENV_TYPE == "production"
157+
158+
if is_production and config_settings.API_URL and "localhost" not in config_settings.API_URL:
150159
actual_redirect_uri = f"{config_settings.API_URL.rstrip('/')}/api/auth/github/callback"
151160
else:
152161
try:
@@ -158,6 +167,11 @@ async def handle_github_callback(
158167
base_url = str(request.base_url).rstrip('/')
159168
actual_redirect_uri = f"{base_url}/api/auth/github/callback"
160169

170+
# CRITICAL: Ensure HTTPS in production (belt-and-suspenders with proxy_headers)
171+
if is_production and actual_redirect_uri.startswith("http://"):
172+
actual_redirect_uri = actual_redirect_uri.replace("http://", "https://", 1)
173+
logger.info(f"GitHub OAuth callback: Forced HTTPS in production: {actual_redirect_uri}")
174+
161175
# Diagnostic logging - VERY detailed for debugging callback
162176
logger.info(f"[GITHUB_CALLBACK_DEBUG] actual_redirect_uri = '{actual_redirect_uri}'")
163177
logger.info(f"[GITHUB_CALLBACK_DEBUG] actual_redirect_uri length = {len(actual_redirect_uri)}")

papers2code_app2/services/google_oauth_service.py

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,9 @@ def prepare_google_login_redirect(self, request: Request) -> RedirectResponse:
5454
raise OAuthException(detail="Authentication service is misconfigured (Google Client ID not set).")
5555

5656
# For production, use explicit environment variable
57-
if config_settings.ENV_TYPE == "production" and config_settings.API_URL and "localhost" not in config_settings.API_URL:
57+
is_production = config_settings.ENV_TYPE == "production"
58+
59+
if is_production and config_settings.API_URL and "localhost" not in config_settings.API_URL:
5860
redirect_uri = f"{config_settings.API_URL.rstrip('/')}/api/auth/google/callback"
5961
else:
6062
try:
@@ -66,6 +68,11 @@ def prepare_google_login_redirect(self, request: Request) -> RedirectResponse:
6668
logger.error(f"Error constructing redirect_uri for Google OAuth: {e}")
6769
raise OAuthException(detail="Error preparing authentication request to Google.")
6870

71+
# CRITICAL: Ensure HTTPS in production (belt-and-suspenders with proxy_headers)
72+
if is_production and redirect_uri.startswith("http://"):
73+
redirect_uri = redirect_uri.replace("http://", "https://", 1)
74+
logger.info(f"Google OAuth: Forced HTTPS in production: {redirect_uri}")
75+
6976
# Diagnostic logging - VERY detailed for debugging
7077
logger.info(f"[GOOGLE_OAUTH_DEBUG] redirect_uri = '{redirect_uri}'")
7178
logger.info(f"[GOOGLE_OAUTH_DEBUG] redirect_uri length = {len(redirect_uri)}")
@@ -148,7 +155,9 @@ async def handle_google_callback(
148155
return RedirectResponse(url=f"{frontend_url}/?login_error=google_no_code", status_code=307)
149156

150157
# Match the same construction as prepare_google_login_redirect
151-
if config_settings.ENV_TYPE == "production" and config_settings.API_URL and "localhost" not in config_settings.API_URL:
158+
is_production = config_settings.ENV_TYPE == "production"
159+
160+
if is_production and config_settings.API_URL and "localhost" not in config_settings.API_URL:
152161
actual_redirect_uri = f"{config_settings.API_URL.rstrip('/')}/api/auth/google/callback"
153162
else:
154163
try:
@@ -160,6 +169,11 @@ async def handle_google_callback(
160169
base_url = str(request.base_url).rstrip('/')
161170
actual_redirect_uri = f"{base_url}/api/auth/google/callback"
162171

172+
# CRITICAL: Ensure HTTPS in production (belt-and-suspenders with proxy_headers)
173+
if is_production and actual_redirect_uri.startswith("http://"):
174+
actual_redirect_uri = actual_redirect_uri.replace("http://", "https://", 1)
175+
logger.info(f"Google OAuth callback: Forced HTTPS in production: {actual_redirect_uri}")
176+
163177
# Diagnostic logging - VERY detailed for debugging callback
164178
logger.info(f"[GOOGLE_CALLBACK_DEBUG] actual_redirect_uri = '{actual_redirect_uri}'")
165179
logger.info(f"[GOOGLE_CALLBACK_DEBUG] actual_redirect_uri length = {len(actual_redirect_uri)}")

run.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -162,8 +162,13 @@ def get_uvicorn_config(self) -> dict:
162162
})
163163
self._log("info", "Using development configuration with hot reload")
164164
else:
165-
# Production or any other environment - simple single-worker setup
166-
self._log("info", "Using production configuration on port 5001")
165+
# Production: trust X-Forwarded headers from Render's reverse proxy
166+
# This is CRITICAL for OAuth redirect_uri to use correct https:// scheme
167+
base_config.update({
168+
"proxy_headers": True,
169+
"forwarded_allow_ips": "*",
170+
})
171+
self._log("info", "Using production configuration on port 5001 with proxy headers enabled")
167172

168173
return base_config
169174

0 commit comments

Comments
 (0)