diff --git a/RUNPOD_SETUP.md b/RUNPOD_SETUP.md new file mode 100644 index 0000000..07afcdc --- /dev/null +++ b/RUNPOD_SETUP.md @@ -0,0 +1,73 @@ +# RunPod OAuth Setup Guide + +## 🚀 Quick Setup for RunPod + +The DropSend node now automatically detects RunPod environments, but for OAuth to work properly, you may need to configure your public URL. + +### Option 1: Automatic Detection (Try This First) + +The node will try to automatically detect your RunPod URL. Just run the OAuth flow and check the console for messages like: + +``` +[OAuthHandler] Detected server URL from request: https://your-runpod-url.runpod.net +``` + +### Option 2: Manual Configuration (If Auto-Detection Fails) + +If the automatic detection doesn't work, set one of these environment variables: + +#### Method A: Set PUBLIC_URL Environment Variable +```bash +export PUBLIC_URL="https://your-runpod-id.runpod.net:8188" +``` + +#### Method B: Set COMFYUI_PUBLIC_URL Environment Variable +```bash +export COMFYUI_PUBLIC_URL="https://your-runpod-id.runpod.net:8188" +``` + +#### Method C: Set RUNPOD_PUBLIC_IP (if available) +```bash +export RUNPOD_PUBLIC_IP="your-runpod-id.runpod.net" +``` + +### How to Find Your RunPod URL + +1. **From RunPod Dashboard**: Look for your pod's public URL +2. **From Browser**: Copy the URL you use to access ComfyUI +3. **From Console**: The node will log detected URLs during OAuth + +### Example URLs + +- `https://abc123-8188.proxy.runpod.net` +- `https://xyz789.runpod.net:8188` +- `https://your-custom-domain.com:8188` + +### Testing the Configuration + +1. Run the DropboxSetupNode +2. Check console output for detected URL +3. If URL looks wrong, set the environment variable and restart ComfyUI + +### Troubleshooting + +**Problem**: OAuth callback fails with "redirect_uri mismatch" +**Solution**: Check that the detected URL in the console matches how you access ComfyUI + +**Problem**: Automatic detection shows localhost +**Solution**: Set PUBLIC_URL or COMFYUI_PUBLIC_URL environment variable + +**Problem**: Still getting localhost after setting environment variables +**Solution**: Restart ComfyUI after setting environment variables + +### Storage Method Recommendations for RunPod + +1. **`keyring`**: Now works with encrypted file storage (recommended) +2. **`display_only`**: Best for temporary pods - copy credentials to environment +3. **`env_file`**: Good for persistent storage volumes + +## 💡 Tips + +- The enhanced keyring backend now works on RunPod with encrypted file storage +- Use `display_only` for maximum flexibility in cloud environments +- Set environment variables in your RunPod template for automatic configuration \ No newline at end of file diff --git a/oauth_handler.py b/oauth_handler.py index cfb2ae5..c1b4831 100644 --- a/oauth_handler.py +++ b/oauth_handler.py @@ -371,6 +371,57 @@ def create_display_only_success_page(session_id, app_key, app_secret, refresh_to """, content_type='text/html') +def get_server_base_url(request=None): + """Dynamically detect the server base URL for OAuth callbacks""" + try: + if request: + # Try to get from the incoming request + scheme = 'https' if request.secure else 'http' + host = request.host + base_url = f"{scheme}://{host}" + print(f"[OAuthHandler] Detected server URL from request: {base_url}") + return base_url + else: + # Fallback: try to detect from ComfyUI server instance + from server import PromptServer + if hasattr(PromptServer, 'instance') and PromptServer.instance: + # Get the port from ComfyUI server + port = getattr(PromptServer.instance, 'port', 8188) + + # Try to detect if we're on RunPod or similar cloud service + import socket + hostname = socket.gethostname() + + # Check for RunPod-specific hostname patterns + if 'runpod' in hostname.lower() or hostname.endswith('.runpod.net'): + # For RunPod, try to get the public URL + import os + runpod_public_ip = os.getenv('RUNPOD_PUBLIC_IP') + if runpod_public_ip: + base_url = f"https://{runpod_public_ip}:{port}" + print(f"[OAuthHandler] Detected RunPod URL: {base_url}") + return base_url + + # Check for common cloud service environment variables + public_url = os.getenv('COMFYUI_PUBLIC_URL') or os.getenv('PUBLIC_URL') + if public_url: + base_url = public_url.rstrip('/') + print(f"[OAuthHandler] Using configured PUBLIC_URL: {base_url}") + return base_url + + # Default fallback to localhost + base_url = f"http://localhost:{port}" + print(f"[OAuthHandler] Fallback to localhost: {base_url}") + return base_url + + except Exception as e: + print(f"[OAuthHandler] Error detecting server URL: {e}") + + # Final fallback + base_url = "http://localhost:8188" + print(f"[OAuthHandler] Using final fallback: {base_url}") + return base_url + # OAuth callback route handler async def handle_oauth_callback(request): """Handle incoming OAuth callback from Dropbox""" @@ -408,8 +459,9 @@ async def handle_oauth_callback(request): session_data = pending_oauth_sessions[session_id] handler = session_data['handler'] - # Process the callback with the redirect URI - callback_url = "http://localhost:8188/oauth/dropbox/callback" + # Process the callback with the dynamic redirect URI + base_url = get_server_base_url(request) + callback_url = f"{base_url}/oauth/dropbox/callback" success, message = await handler.process_callback(auth_code, redirect_uri=callback_url) # Clean up the session diff --git a/requirements.txt b/requirements.txt index edeadcd..f067d84 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,3 +3,4 @@ python-dotenv watchdog dropbox keyring +keyrings.alt diff --git a/setup_dropbox_node.py b/setup_dropbox_node.py index 4425fd8..bd62b39 100644 --- a/setup_dropbox_node.py +++ b/setup_dropbox_node.py @@ -7,7 +7,7 @@ import uuid from dotenv import load_dotenv, dotenv_values import urllib.parse from .dropbox_auth_manager import DropboxAuthManager -from .oauth_handler import OAuthCallbackHandler +from .oauth_handler import OAuthCallbackHandler, get_server_base_url class DropboxSetupNode: @@ -238,7 +238,8 @@ class DropboxSetupNode: if auto_oauth: # Automatic OAuth flow with callback session_id = str(uuid.uuid4()) - callback_url = "http://localhost:8188/oauth/dropbox/callback" + base_url = get_server_base_url() + callback_url = f"{base_url}/oauth/dropbox/callback" oauth_url = auth_temp.get_oauth_url(redirect_uri=callback_url, state=session_id) # Set up OAuth session for callback handling @@ -282,7 +283,8 @@ class DropboxSetupNode: # Get the tokens without storing them yet # Only pass redirect_uri if this was an automatic OAuth flow if auto_oauth: - callback_url = "http://localhost:8188/oauth/dropbox/callback" + base_url = get_server_base_url() + callback_url = f"{base_url}/oauth/dropbox/callback" print(f"[DropboxSetup] Using automatic OAuth with redirect_uri: {callback_url}") result = auth_manager_setup.exchange_auth_code_raw(auth_code_clean, redirect_uri=callback_url) else: