# Design: Automated Google Login with rbw ## Overview Automate the Google login flow for cookie extraction, using rbw (Bitwarden CLI) for credential lookup. ## Current State - `selenium_cookie_extractor_json.py` opens Chrome incognito, navigates to chat.google.com - User manually logs in, presses Enter - Script extracts COMPASS, SSID, SID, OSID, HSID cookies and outputs JSON ## Proposed Changes ### 1. rbw Integration ```python def check_rbw_unlocked() -> bool: """Check if rbw vault is unlocked.""" result = subprocess.run(['rbw', 'unlocked'], capture_output=True) return result.returncode == 0 def prompt_rbw_unlock(): """Prompt user to unlock rbw vault.""" print("rbw vault is locked. Please unlock it.") subprocess.run(['rbw', 'unlock'], check=True) def get_google_credentials(entry_name: str = "google.com") -> tuple[str, str]: """Get username and password from rbw.""" username = subprocess.run( ['rbw', 'get', '-f', 'username', entry_name], capture_output=True, text=True, check=True ).stdout.strip() password = subprocess.run( ['rbw', 'get', entry_name], capture_output=True, text=True, check=True ).stdout.strip() return username, password ``` ### 2. Automated Login Flow Google's login has multiple steps: 1. **Email page**: Enter email, click Next 2. **Password page**: Enter password, click Next 3. **Potential 2FA**: May require manual intervention ```python def automate_login(driver, username: str, password: str): """Automate Google login flow.""" driver.get("https://accounts.google.com/signin") # Enter email email_input = WebDriverWait(driver, 10).until( EC.presence_of_element_located((By.ID, "identifierId")) ) email_input.send_keys(username) email_input.send_keys(Keys.RETURN) # Wait for password page and enter password password_input = WebDriverWait(driver, 10).until( EC.presence_of_element_located((By.NAME, "Passwd")) ) password_input.send_keys(password) password_input.send_keys(Keys.RETURN) # Wait for successful login (presence of chat page or 2FA prompt) # If 2FA required, prompt user to complete it manually ``` ### 3. Clipboard Support Add `wl-clipboard` and `xclip` to nix dependencies. Try Wayland first, fall back to X11: ```python def copy_to_clipboard(text: str) -> bool: """Copy text to clipboard. Tries wl-copy (Wayland) first, falls back to xclip (X11).""" try: subprocess.run(['wl-copy'], input=text.encode(), check=True) return True except FileNotFoundError: pass # Fall back to xclip (X11) process = subprocess.Popen(['xclip', '-selection', 'clipboard'], stdin=subprocess.PIPE) process.communicate(text.encode()) return process.returncode == 0 ``` ### 4. CLI Interface ``` Usage: gcr [OPTIONS] Options: --copy, -c Copy cookie JSON to clipboard (default: true) --entry NAME rbw entry name (default: "google.com") --no-auto Skip auto-login, use manual flow --help Show this message ``` ## Implementation Steps 1. Add new dependencies to `flake.nix`: `xclip` 2. Add selenium wait helpers: `WebDriverWait`, `expected_conditions` 3. Implement rbw functions: check unlocked, prompt unlock, get credentials 4. Implement automated login: email step, password step, 2FA detection 5. Implement clipboard copy 6. Add CLI argument parsing with argparse 7. Update main flow to use automation by default ## Edge Cases 1. **rbw vault locked**: Prompt to unlock, fail gracefully if user cancels 2. **Wrong credentials in rbw**: Let login fail, user can retry manually 3. **2FA required**: Detect 2FA page, prompt user to complete manually, then continue 4. **Login timeout**: Add reasonable timeouts with clear error messages 5. **Multiple Google accounts**: Use `--entry` flag to specify which rbw entry ## Security Considerations - Credentials are retrieved from rbw, never stored in script - Incognito mode prevents cookie persistence - Browser is closed promptly after extraction ## Testing Plan 1. Test with unlocked vault 2. Test with locked vault (unlock prompt) 3. Test with invalid rbw entry name 4. Test full login flow (requires real credentials) 5. Test 2FA flow (manual completion) 6. Test clipboard copy