123 lines
4.0 KiB
Markdown
123 lines
4.0 KiB
Markdown
# SSO → OAuth Conversion via Device Auth Flow
|
|
|
|
## Overview
|
|
|
|
Converts SSO session cookies (from GrokRegister) to OAuth access tokens via x.ai's OAuth device code flow. Uses DrissionPage to automate the browser authorization step.
|
|
|
|
## Prerequisites
|
|
|
|
- Python 3.11+ with `httpx`, `sqlite3`
|
|
- DrissionPage (`pip install DrissionPage`) — run with `python -s` to avoid Hermes venv path collisions
|
|
- Chrome installed at `C:\Program Files\Google\Chrome\Application\chrome.exe`
|
|
- gw46 gateway DB at `~/Documents/grok46gw/grok46_accounts.db`
|
|
|
|
## Script Location
|
|
|
|
`C:\Users\User\tmp\grok_register\grok-register\sso2oauth.py`
|
|
|
|
## Flow Detail
|
|
|
|
### Step 1: Start Device Code Flow
|
|
```
|
|
POST https://auth.x.ai/oauth2/device/code
|
|
Content-Type: application/x-www-form-urlencoded
|
|
|
|
client_id=b1a00492-073a-47ea-816f-4c329264a828&
|
|
scope=openid+profile+email+offline_access+grok-cli:access+api:access
|
|
|
|
Response:
|
|
{
|
|
"device_code": "...",
|
|
"user_code": "ABCD-1234",
|
|
"verification_uri": "https://accounts.x.ai/oauth2/device",
|
|
"verification_uri_complete": "https://accounts.x.ai/oauth2/device?user_code=ABCD-1234",
|
|
"interval": 5,
|
|
"expires_in": 600
|
|
}
|
|
```
|
|
|
|
### Step 2: Authorize Device with SSO (DrissionPage)
|
|
```python
|
|
from DrissionPage import ChromiumPage
|
|
|
|
page = ChromiumPage()
|
|
page.get("https://accounts.x.ai/sign-in")
|
|
page.run_js(f"""
|
|
document.cookie = "sso={sso_token}; domain=.accounts.x.ai; path=/; Secure;";
|
|
document.cookie = "sso={sso_token}; domain=.x.ai; path=/; Secure;";
|
|
""")
|
|
page.get(verification_uri_complete) # includes user_code in URL
|
|
# Click "Продолжить" (Continue) to submit the code
|
|
page.ele("tag:button@@text()=Продолжить").click()
|
|
# Wait for authorization page
|
|
# Click "Authorize" / "Разрешить"
|
|
page.ele("tag:button@@text()=Разрешить").click()
|
|
```
|
|
|
|
### Step 3: Poll for Token
|
|
```
|
|
POST https://auth.x.ai/oauth2/token
|
|
Content-Type: application/x-www-form-urlencoded
|
|
|
|
grant_type=urn:ietf:params:oauth:grant-type:device_code&
|
|
device_code={device_code}&
|
|
client_id=b1a00492-073a-47ea-816f-4c329264a828
|
|
|
|
Response (200):
|
|
{
|
|
"access_token": "eyJ0eX...",
|
|
"refresh_token": "m9Vzs...",
|
|
"expires_in": 3600,
|
|
"scope": "openid profile email offline_access grok-cli:access api:access",
|
|
"id_token": "eyJ0eX..."
|
|
}
|
|
```
|
|
|
|
### Step 4: Store in SQLite
|
|
```sql
|
|
INSERT INTO accounts (email, access_token, refresh_token, expires_at, scope)
|
|
VALUES (?, ?, ?, ?, ?);
|
|
```
|
|
|
|
## Token Validation
|
|
|
|
The OAuth token JWT contains:
|
|
- `iss: https://auth.x.ai`
|
|
- `aud: b1a00492-073a-47ea-816f-4c329264a828` (correct client_id)
|
|
- `scope: openid profile email offline_access grok-cli:access api:access`
|
|
- `principal_type: User`
|
|
- `exp: <timestamp>` (6 hours from issue)
|
|
|
|
## Known Limitations
|
|
|
|
### 1. DrissionPage Concurrency (PageDisconnectedError)
|
|
DrissionPage [REDACTED-IP]b14 crashes with `PageDisconnectedError` (与页面的连接已断开) when multiple `ChromiumPage` instances are created in the same process. The background CDP event handler thread raises an unhandled exception. Cause is a shared CDP connection state across instances.
|
|
|
|
**Fix:** Force sequential processing (`--concurrent 1`). Split large batches into chunks of 10-15 with process restarts between chunks.
|
|
|
|
### 2. No API Credits
|
|
OAuth tokens are valid (authenticate correctly) but accounts have no API credits. All API calls return:
|
|
```json
|
|
{"code":"personal-team-blocked:spending-limit",
|
|
"error":"You have run out of credits or need a Grok subscription."}
|
|
```
|
|
The gw46 gateway shows `credentials: N` in health but every request fails with 402.
|
|
|
|
### 3. gw46 KeyPool Refresh
|
|
The gateway reads the DB only during startup. External DB writes (via `sso2oauth.py`) are invisible until restart:
|
|
```bash
|
|
taskkill /F /PID <PID>
|
|
cd ~/Documents/grok46gw && python gw46.py
|
|
```
|
|
|
|
## Session Performance (2026-08-13)
|
|
|
|
| Metric | Value |
|
|
|--------|-------|
|
|
| Accounts created | 171 |
|
|
| SSO → OAuth converted | 74 |
|
|
| Sequential time per account | ~10-15s |
|
|
| Total conversion time | ~12 min |
|
|
| Batch size before crash | ~10-15 |
|
|
| DrissionPage chunks | 5 (restart between) |
|
|
| Valid API tokens | 0 (all 402) | |