An automated utility designed to bypass the 7-day expiration of Charles Schwab API Refresh Tokens. It leverages GitHub-hosted runners (ubuntu-latest) with 7GB RAM to run an official Google Chrome instance, automating the OAuth consent flow and synchronizing credentials directly to Google Cloud Secret Manager.
- GitHub-Hosted Efficiency: Runs entirely on GitHub's infrastructure (7GB RAM), eliminating the need for private VPS maintenance.
- Official Chrome Integration: Dynamically installs the retail version of Google Chrome (.deb) to ensure maximum browser trust and bypass bot detection.
- Stealth-Mode Automation: Powered by
playwright-extraandstealthplugins to emulate human-like behavior and bypass sophisticated anti-bot challenges. - Automated Virtual Display: Uses
xvfb-runwithin the CI environment to handle headed browser interactions without a physical monitor. - Secure Cloud Sync: Injects refreshed tokens directly into Google Cloud Secret Manager via memory, ensuring no sensitive data is stored in the repo.
- Isolated Logging: Success timestamps are automatically committed to a dedicated
logsbranch to keep the main commit history clean.
If you have forked this repository, follow these steps to enable the automation:
Go to Settings > Secrets and variables > Actions in your repo and add:
| Secret Name | Description |
|---|---|
SCHWAB_USERNAME |
Your Schwab account Login ID |
SCHWAB_PASSWORD |
Your Schwab account Password |
SCHWAB_TOTP_SECRET |
Your 2FA/MFA secret key (Base32) |
SCHWAB_API_KEY |
Your Schwab Developer App Client ID |
SCHWAB_APP_SECRET |
Your Schwab Developer App Client Secret |
GCP_SA_KEY |
JSON key for a GCP Service Account with Secret Manager permissions |
SCHWAB_PROXY_URL |
Optional authenticated HTTP/HTTPS proxy URL for routing Schwab browser/API traffic through your home/residential exit, e.g. http://user:pass@proxy.example.com:3128 |
These values are better stored as GitHub Variables because they are configuration, not credentials:
| Variable Name | Description |
|---|---|
GCP_PROJECT_ID |
Your Google Cloud Project ID |
GCP_SECRET_ID |
The name of the secret in Secret Manager |
SCHWAB_REDIRECT_URI |
Your app's registered redirect URI |
- Navigate to the Actions tab of your repository.
- Select Schwab Token Auto Refresher from the left sidebar.
- Click Enable workflow (GitHub disables scheduled workflows on forks by default).
- (Optional) Manually trigger the flow using Run workflow to verify the configuration.
If Schwab is more reliable from your residential network than from GitHub-hosted IP ranges, this repo can route the Schwab browser flow + token exchange request through an authenticated proxy by setting SCHWAB_PROXY_URL.
This behavior is default-off:
- if
SCHWAB_PROXY_URLis not configured, the workflow does not use a proxy - if
SCHWAB_PROXY_URLis configured, the workflow uses that proxy for Schwab traffic
Important boundary:
- Your router public IP is not a proxy by itself.
- Do not expose the OpenWrt/LuCI admin UI to the public internet.
- You need a separate HTTP/HTTPS proxy service reachable from GitHub Actions, then point
SCHWAB_PROXY_URLat that endpoint.
Typical setup options:
-
Run a small authenticated proxy inside your home network (for example on the router or a LAN machine).
-
Expose only that proxy through your preferred tunnel/reverse-proxy setup.
-
Store the final public endpoint in
SCHWAB_PROXY_URL, for example:SCHWAB_PROXY_URL=http://user:pass@proxy.example.com:3128
Notes:
- This repo currently supports HTTP/HTTPS proxy URLs for workflow mode.
- If
SCHWAB_PROXY_URLis absent, the workflow runs without the home-exit proxy. - Only the Schwab automation traffic is proxied. Package installation and GitHub/GCP housekeeping continue to use the runner's default egress.
- If you want every step to originate from home, a self-hosted runner in your LAN is usually simpler and more stable than tunneling a proxy into a GitHub-hosted runner.
- Trigger: Triggered by GitHub Actions scheduler every 3 days at 13:00 UTC.
- Environment: Spin up an
ubuntu-latestrunner, install Google Chrome stable, and initialize a virtual display viaxvfb. - Execution: Playwright-stealth navigates the OAuth flow, inputs credentials, generates TOTP, and intercepts the redirect code.
- Synchronization: The utility exchanges the code for tokens and updates GCP Secret Manager.
- Logging: Updates
last_run.txton thelogsbranch to confirm a successful refresh.
Distributed under the MIT License. See LICENSE for more information.