cursorflow 2.7.7__tar.gz → 2.7.8__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {cursorflow-2.7.7 → cursorflow-2.7.8}/PKG-INFO +14 -1
- {cursorflow-2.7.7 → cursorflow-2.7.8}/README.md +13 -0
- {cursorflow-2.7.7 → cursorflow-2.7.8}/cursorflow/cli.py +152 -0
- {cursorflow-2.7.7 → cursorflow-2.7.8}/cursorflow/rules/cursorflow-usage.mdc +51 -0
- {cursorflow-2.7.7 → cursorflow-2.7.8}/docs/user/USAGE_GUIDE.md +168 -0
- {cursorflow-2.7.7 → cursorflow-2.7.8}/pyproject.toml +1 -1
- {cursorflow-2.7.7 → cursorflow-2.7.8}/LICENSE +0 -0
- {cursorflow-2.7.7 → cursorflow-2.7.8}/MANIFEST.in +0 -0
- {cursorflow-2.7.7 → cursorflow-2.7.8}/cursorflow/__init__.py +0 -0
- {cursorflow-2.7.7 → cursorflow-2.7.8}/cursorflow/auto_init.py +0 -0
- {cursorflow-2.7.7 → cursorflow-2.7.8}/cursorflow/auto_updater.py +0 -0
- {cursorflow-2.7.7 → cursorflow-2.7.8}/cursorflow/core/action_validator.py +0 -0
- {cursorflow-2.7.7 → cursorflow-2.7.8}/cursorflow/core/agent.py +0 -0
- {cursorflow-2.7.7 → cursorflow-2.7.8}/cursorflow/core/auth_handler.py +0 -0
- {cursorflow-2.7.7 → cursorflow-2.7.8}/cursorflow/core/browser_controller.py +0 -0
- {cursorflow-2.7.7 → cursorflow-2.7.8}/cursorflow/core/browser_engine.py +0 -0
- {cursorflow-2.7.7 → cursorflow-2.7.8}/cursorflow/core/config_validator.py +0 -0
- {cursorflow-2.7.7 → cursorflow-2.7.8}/cursorflow/core/css_iterator.py +0 -0
- {cursorflow-2.7.7 → cursorflow-2.7.8}/cursorflow/core/cursor_integration.py +0 -0
- {cursorflow-2.7.7 → cursorflow-2.7.8}/cursorflow/core/cursorflow.py +0 -0
- {cursorflow-2.7.7 → cursorflow-2.7.8}/cursorflow/core/data_presenter.py +0 -0
- {cursorflow-2.7.7 → cursorflow-2.7.8}/cursorflow/core/error_context_collector.py +0 -0
- {cursorflow-2.7.7 → cursorflow-2.7.8}/cursorflow/core/error_correlator.py +0 -0
- {cursorflow-2.7.7 → cursorflow-2.7.8}/cursorflow/core/event_correlator.py +0 -0
- {cursorflow-2.7.7 → cursorflow-2.7.8}/cursorflow/core/file_change_monitor.py +0 -0
- {cursorflow-2.7.7 → cursorflow-2.7.8}/cursorflow/core/hmr_detector.py +0 -0
- {cursorflow-2.7.7 → cursorflow-2.7.8}/cursorflow/core/json_utils.py +0 -0
- {cursorflow-2.7.7 → cursorflow-2.7.8}/cursorflow/core/log_collector.py +0 -0
- {cursorflow-2.7.7 → cursorflow-2.7.8}/cursorflow/core/log_monitor.py +0 -0
- {cursorflow-2.7.7 → cursorflow-2.7.8}/cursorflow/core/mockup_comparator.py +0 -0
- {cursorflow-2.7.7 → cursorflow-2.7.8}/cursorflow/core/output_manager.py +0 -0
- {cursorflow-2.7.7 → cursorflow-2.7.8}/cursorflow/core/persistent_session.py +0 -0
- {cursorflow-2.7.7 → cursorflow-2.7.8}/cursorflow/core/query_engine.py +0 -0
- {cursorflow-2.7.7 → cursorflow-2.7.8}/cursorflow/core/report_generator.py +0 -0
- {cursorflow-2.7.7 → cursorflow-2.7.8}/cursorflow/core/trace_manager.py +0 -0
- {cursorflow-2.7.7 → cursorflow-2.7.8}/cursorflow/install_cursorflow_rules.py +0 -0
- {cursorflow-2.7.7 → cursorflow-2.7.8}/cursorflow/log_sources/local_file.py +0 -0
- {cursorflow-2.7.7 → cursorflow-2.7.8}/cursorflow/log_sources/ssh_remote.py +0 -0
- {cursorflow-2.7.7 → cursorflow-2.7.8}/cursorflow/post_install.py +0 -0
- {cursorflow-2.7.7 → cursorflow-2.7.8}/cursorflow/rules/__init__.py +0 -0
- {cursorflow-2.7.7 → cursorflow-2.7.8}/cursorflow/rules/cursorflow-installation.mdc +0 -0
- {cursorflow-2.7.7 → cursorflow-2.7.8}/cursorflow/updater.py +0 -0
- {cursorflow-2.7.7 → cursorflow-2.7.8}/cursorflow.egg-info/SOURCES.txt +0 -0
- {cursorflow-2.7.7 → cursorflow-2.7.8}/examples/comprehensive_screenshot_example.py +0 -0
- {cursorflow-2.7.7 → cursorflow-2.7.8}/examples/element_inspection_example.py +0 -0
- {cursorflow-2.7.7 → cursorflow-2.7.8}/examples/element_measurement_example.py +0 -0
- {cursorflow-2.7.7 → cursorflow-2.7.8}/examples/enhanced_screenshot_example.py +0 -0
- {cursorflow-2.7.7 → cursorflow-2.7.8}/examples/hot_reload_css_iteration.py +0 -0
- {cursorflow-2.7.7 → cursorflow-2.7.8}/examples/mockup_comparison_example.py +0 -0
- {cursorflow-2.7.7 → cursorflow-2.7.8}/examples/opensas_example.py +0 -0
- {cursorflow-2.7.7 → cursorflow-2.7.8}/examples/react_example.py +0 -0
- {cursorflow-2.7.7 → cursorflow-2.7.8}/examples/responsive_testing_example.py +0 -0
- {cursorflow-2.7.7 → cursorflow-2.7.8}/examples/v2_comprehensive_demo.py +0 -0
- {cursorflow-2.7.7 → cursorflow-2.7.8}/setup.cfg +0 -0
- {cursorflow-2.7.7 → cursorflow-2.7.8}/setup.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: cursorflow
|
3
|
-
Version: 2.7.
|
3
|
+
Version: 2.7.8
|
4
4
|
Summary: 🔥 Complete page intelligence for AI-driven development with Hot Reload Intelligence - captures DOM, network, console, performance, HMR events, and comprehensive page analysis
|
5
5
|
Author-email: GeekWarrior Development <rbush@cooltheory.com>
|
6
6
|
License-Expression: MIT
|
@@ -177,6 +177,19 @@ cursorflow test --use-session "user" \
|
|
177
177
|
- Form authentication (username/password)
|
178
178
|
- Cookie authentication (JWT tokens, session cookies)
|
179
179
|
- Header authentication (Bearer tokens, API keys)
|
180
|
+
- SSO authentication (Google, Microsoft, Okta, Auth0)
|
181
|
+
|
182
|
+
**SSO/OAuth Quick Start:**
|
183
|
+
```bash
|
184
|
+
# Capture SSO auth (opens browser for manual login)
|
185
|
+
cursorflow capture-auth --base-url http://localhost:3000 \
|
186
|
+
--path /dashboard \
|
187
|
+
--output google-sso.json
|
188
|
+
|
189
|
+
# Use captured auth
|
190
|
+
# (Copy cookies from google-sso.json to .cursorflow/config.json)
|
191
|
+
cursorflow test --use-session "sso-user" --path /dashboard
|
192
|
+
```
|
180
193
|
|
181
194
|
**See:** [Complete Authentication Guide](docs/user/USAGE_GUIDE.md#authentication--session-management)
|
182
195
|
|
@@ -132,6 +132,19 @@ cursorflow test --use-session "user" \
|
|
132
132
|
- Form authentication (username/password)
|
133
133
|
- Cookie authentication (JWT tokens, session cookies)
|
134
134
|
- Header authentication (Bearer tokens, API keys)
|
135
|
+
- SSO authentication (Google, Microsoft, Okta, Auth0)
|
136
|
+
|
137
|
+
**SSO/OAuth Quick Start:**
|
138
|
+
```bash
|
139
|
+
# Capture SSO auth (opens browser for manual login)
|
140
|
+
cursorflow capture-auth --base-url http://localhost:3000 \
|
141
|
+
--path /dashboard \
|
142
|
+
--output google-sso.json
|
143
|
+
|
144
|
+
# Use captured auth
|
145
|
+
# (Copy cookies from google-sso.json to .cursorflow/config.json)
|
146
|
+
cursorflow test --use-session "sso-user" --path /dashboard
|
147
|
+
```
|
135
148
|
|
136
149
|
**See:** [Complete Authentication Guide](docs/user/USAGE_GUIDE.md#authentication--session-management)
|
137
150
|
|
@@ -1116,6 +1116,158 @@ def sessions(subcommand, name):
|
|
1116
1116
|
else:
|
1117
1117
|
console.print(f"[yellow]⚠️ Session not found: {name}[/yellow]")
|
1118
1118
|
|
1119
|
+
@main.command()
|
1120
|
+
@click.option('--base-url', '-u', required=True, help='Base URL of your application')
|
1121
|
+
@click.option('--path', '-p', default='/', help='Path to navigate to after login (e.g., /dashboard)')
|
1122
|
+
@click.option('--output', '-o', default='auth-capture.json', help='Output file for captured auth state')
|
1123
|
+
@click.option('--wait', type=int, default=60, help='Seconds to wait for manual login (default: 60)')
|
1124
|
+
def capture_auth(base_url, path, output, wait):
|
1125
|
+
"""
|
1126
|
+
Capture authentication state after manual SSO/OAuth login
|
1127
|
+
|
1128
|
+
Opens a browser, waits for you to complete SSO login manually,
|
1129
|
+
then captures all cookies, localStorage, and sessionStorage.
|
1130
|
+
Perfect for Google/Microsoft/Okta SSO authentication.
|
1131
|
+
|
1132
|
+
\b
|
1133
|
+
Process:
|
1134
|
+
1. Browser opens to your app
|
1135
|
+
2. Complete SSO login manually (Google, Microsoft, Okta, etc.)
|
1136
|
+
3. Navigate to a protected page (e.g., /dashboard)
|
1137
|
+
4. CursorFlow captures all auth state
|
1138
|
+
5. Auth state saved to JSON file
|
1139
|
+
6. Use in .cursorflow/config.json as cookie authentication
|
1140
|
+
|
1141
|
+
\b
|
1142
|
+
Examples:
|
1143
|
+
# Capture Google SSO auth
|
1144
|
+
cursorflow capture-auth --base-url http://localhost:3000 --path /dashboard
|
1145
|
+
|
1146
|
+
# Capture with custom wait time
|
1147
|
+
cursorflow capture-auth -u http://localhost:3000 -p /dashboard --wait 120
|
1148
|
+
|
1149
|
+
# Save to custom file
|
1150
|
+
cursorflow capture-auth -u http://localhost:3000 --output google-sso.json
|
1151
|
+
"""
|
1152
|
+
console.print(f"\n🔐 SSO Authentication Capture")
|
1153
|
+
console.print(f"📍 Base URL: [cyan]{base_url}[/cyan]")
|
1154
|
+
console.print(f"🎯 Target path: [cyan]{path}[/cyan]")
|
1155
|
+
console.print(f"⏱️ Wait time: [yellow]{wait}[/yellow] seconds")
|
1156
|
+
console.print(f"📄 Output file: [green]{output}[/green]\n")
|
1157
|
+
|
1158
|
+
console.print("📋 [bold]Instructions:[/bold]")
|
1159
|
+
console.print(" 1. Browser will open to your application")
|
1160
|
+
console.print(" 2. [yellow]Complete SSO login manually[/yellow] (Google, Microsoft, Okta, etc.)")
|
1161
|
+
console.print(" 3. Navigate to a protected page (e.g., /dashboard)")
|
1162
|
+
console.print(" 4. [green]Press Enter[/green] when fully logged in")
|
1163
|
+
console.print(" 5. CursorFlow will capture all auth state\n")
|
1164
|
+
|
1165
|
+
input("Press Enter to open browser and start capture...")
|
1166
|
+
|
1167
|
+
try:
|
1168
|
+
from playwright.async_api import async_playwright
|
1169
|
+
import json
|
1170
|
+
|
1171
|
+
async def capture_process():
|
1172
|
+
async with async_playwright() as p:
|
1173
|
+
# Launch browser in HEADED mode (user needs to interact)
|
1174
|
+
browser = await p.chromium.launch(headless=False)
|
1175
|
+
context = await browser.new_context()
|
1176
|
+
page = await context.new_page()
|
1177
|
+
|
1178
|
+
console.print(f"\n🌐 Opening browser to: [cyan]{base_url}[/cyan]")
|
1179
|
+
await page.goto(base_url)
|
1180
|
+
|
1181
|
+
console.print(f"\n⏳ [yellow]Complete your SSO login in the browser...[/yellow]")
|
1182
|
+
console.print(f" Waiting up to {wait} seconds...")
|
1183
|
+
console.print(f" [bold]Press Enter in this terminal when logged in and on {path}[/bold]\n")
|
1184
|
+
|
1185
|
+
# Wait for user to complete login
|
1186
|
+
import sys
|
1187
|
+
import select
|
1188
|
+
|
1189
|
+
# Simple blocking wait for Enter key
|
1190
|
+
input("Press Enter after completing login... ")
|
1191
|
+
|
1192
|
+
# Navigate to target path to ensure we're at the right place
|
1193
|
+
if path != '/':
|
1194
|
+
console.print(f"📍 Navigating to: [cyan]{path}[/cyan]")
|
1195
|
+
await page.goto(f"{base_url.rstrip('/')}{path}")
|
1196
|
+
await page.wait_for_load_state("networkidle")
|
1197
|
+
|
1198
|
+
console.print("\n📸 Capturing authentication state...")
|
1199
|
+
|
1200
|
+
# Capture all authentication data
|
1201
|
+
storage_state = await context.storage_state()
|
1202
|
+
|
1203
|
+
# Get localStorage
|
1204
|
+
local_storage = await page.evaluate("""
|
1205
|
+
() => {
|
1206
|
+
const storage = {};
|
1207
|
+
for (let i = 0; i < localStorage.length; i++) {
|
1208
|
+
const key = localStorage.key(i);
|
1209
|
+
storage[key] = localStorage.getItem(key);
|
1210
|
+
}
|
1211
|
+
return storage;
|
1212
|
+
}
|
1213
|
+
""")
|
1214
|
+
|
1215
|
+
# Get sessionStorage
|
1216
|
+
session_storage = await page.evaluate("""
|
1217
|
+
() => {
|
1218
|
+
const storage = {};
|
1219
|
+
for (let i = 0; i < sessionStorage.length; i++) {
|
1220
|
+
const key = sessionStorage.key(i);
|
1221
|
+
storage[key] = sessionStorage.getItem(key);
|
1222
|
+
}
|
1223
|
+
return storage;
|
1224
|
+
}
|
1225
|
+
""")
|
1226
|
+
|
1227
|
+
# Organize captured data
|
1228
|
+
auth_data = {
|
1229
|
+
"captured_at": time.strftime("%Y-%m-%d %H:%M:%S"),
|
1230
|
+
"base_url": base_url,
|
1231
|
+
"current_url": page.url,
|
1232
|
+
"method": "cookies",
|
1233
|
+
"cookies": storage_state.get("cookies", []),
|
1234
|
+
"localStorage": local_storage,
|
1235
|
+
"sessionStorage": session_storage,
|
1236
|
+
"usage_instructions": {
|
1237
|
+
"1": "Copy the 'cookies' array below",
|
1238
|
+
"2": "Add to .cursorflow/config.json under auth.cookies",
|
1239
|
+
"3": "Set auth.method to 'cookies'",
|
1240
|
+
"4": "Use with: cursorflow test --use-session <name>"
|
1241
|
+
}
|
1242
|
+
}
|
1243
|
+
|
1244
|
+
# Save to file
|
1245
|
+
output_path = Path(output)
|
1246
|
+
with open(output_path, 'w') as f:
|
1247
|
+
json.dump(auth_data, f, indent=2)
|
1248
|
+
|
1249
|
+
console.print(f"\n✅ Authentication state captured!")
|
1250
|
+
console.print(f"📄 Saved to: [green]{output_path.absolute()}[/green]")
|
1251
|
+
console.print(f"🍪 Captured {len(auth_data['cookies'])} cookies")
|
1252
|
+
console.print(f"💾 localStorage: {len(local_storage)} items")
|
1253
|
+
console.print(f"💾 sessionStorage: {len(session_storage)} items")
|
1254
|
+
|
1255
|
+
console.print(f"\n📋 [bold]Next steps:[/bold]")
|
1256
|
+
console.print(f" 1. Open: [cyan]{output}[/cyan]")
|
1257
|
+
console.print(f" 2. Copy the 'cookies' array")
|
1258
|
+
console.print(f" 3. Add to .cursorflow/config.json:")
|
1259
|
+
console.print(f'\n {{\n "auth": {{\n "method": "cookies",\n "cookies": [... paste here ...]\n }}\n }}\n')
|
1260
|
+
console.print(f" 4. Test with: [cyan]cursorflow test --use-session sso-user[/cyan]\n")
|
1261
|
+
|
1262
|
+
await browser.close()
|
1263
|
+
|
1264
|
+
asyncio.run(capture_process())
|
1265
|
+
|
1266
|
+
except KeyboardInterrupt:
|
1267
|
+
console.print("\n[yellow]⚠️ Capture cancelled by user[/yellow]")
|
1268
|
+
except Exception as e:
|
1269
|
+
console.print(f"[red]❌ Error capturing auth: {escape(str(e))}[/red]")
|
1270
|
+
|
1119
1271
|
@main.command()
|
1120
1272
|
@click.option('--base-url', '-u', required=True)
|
1121
1273
|
@click.option('--path', '-p', default='/', help='Path to navigate to')
|
@@ -1076,6 +1076,45 @@ cursorflow test --actions '[
|
|
1076
1076
|
]' --save-session "2fa-user"
|
1077
1077
|
```
|
1078
1078
|
|
1079
|
+
### **SSO Authentication (Google, Microsoft, Okta)**
|
1080
|
+
|
1081
|
+
**SSO requires manual capture** because of external identity providers:
|
1082
|
+
|
1083
|
+
```bash
|
1084
|
+
# 1. Capture SSO auth (opens browser, you login manually)
|
1085
|
+
cursorflow capture-auth --base-url http://localhost:3000 \
|
1086
|
+
--path /dashboard \
|
1087
|
+
--output google-sso.json
|
1088
|
+
|
1089
|
+
# Browser opens, you complete SSO login, CursorFlow captures cookies
|
1090
|
+
|
1091
|
+
# 2. Copy cookies from google-sso.json to .cursorflow/config.json:
|
1092
|
+
{
|
1093
|
+
"auth": {
|
1094
|
+
"method": "cookies",
|
1095
|
+
"cookies": [/* paste from google-sso.json */]
|
1096
|
+
}
|
1097
|
+
}
|
1098
|
+
|
1099
|
+
# 3. Use captured auth
|
1100
|
+
cursorflow test --use-session "sso-user" --path /dashboard
|
1101
|
+
```
|
1102
|
+
|
1103
|
+
**SSO providers supported:**
|
1104
|
+
- Google OAuth
|
1105
|
+
- Microsoft Azure AD
|
1106
|
+
- Okta
|
1107
|
+
- Auth0
|
1108
|
+
- Any OAuth/SAML provider
|
1109
|
+
|
1110
|
+
**When SSO tokens expire:**
|
1111
|
+
```bash
|
1112
|
+
# Re-capture auth (SSO tokens typically expire in 1-24 hours)
|
1113
|
+
cursorflow capture-auth --base-url http://localhost:3000 \
|
1114
|
+
--path /dashboard \
|
1115
|
+
--output sso-refreshed.json
|
1116
|
+
```
|
1117
|
+
|
1079
1118
|
### **Troubleshooting Auth**
|
1080
1119
|
|
1081
1120
|
**Auth failing?**
|
@@ -1100,6 +1139,18 @@ cat .cursorflow/sessions/user_session.json
|
|
1100
1139
|
cursorflow test --use-session "user" --fresh-session
|
1101
1140
|
```
|
1102
1141
|
|
1142
|
+
**SSO not working?**
|
1143
|
+
```bash
|
1144
|
+
# Re-capture auth state
|
1145
|
+
cursorflow capture-auth --base-url http://localhost:3000 --path /dashboard
|
1146
|
+
|
1147
|
+
# Check if localStorage has tokens (some SSO stores tokens there)
|
1148
|
+
cat auth-capture.json | grep localStorage
|
1149
|
+
|
1150
|
+
# Test immediately after capture
|
1151
|
+
cursorflow test --use-session "sso-user" --path /dashboard
|
1152
|
+
```
|
1153
|
+
|
1103
1154
|
## Best Practices
|
1104
1155
|
|
1105
1156
|
### **🔥 Hot Reload CSS Iteration Best Practices**
|
@@ -1134,6 +1134,174 @@ cursorflow test --use-session "regular-user" \
|
|
1134
1134
|
3. Look at Response Headers for `Set-Cookie`
|
1135
1135
|
4. Copy cookie details to config
|
1136
1136
|
|
1137
|
+
##### **SSO Authentication (OAuth, SAML, Google/Microsoft Login)**
|
1138
|
+
|
1139
|
+
SSO authentication is complex because it involves external identity providers and multi-step flows. CursorFlow handles this by capturing the final authenticated state.
|
1140
|
+
|
1141
|
+
**The SSO Challenge:**
|
1142
|
+
- Involves external domains (accounts.google.com, login.microsoftonline.com, etc.)
|
1143
|
+
- Complex token exchanges and redirects
|
1144
|
+
- CSRF tokens and state parameters
|
1145
|
+
- May use multiple cookies across domains
|
1146
|
+
|
1147
|
+
**Solution: Capture After Manual Login**
|
1148
|
+
|
1149
|
+
CursorFlow provides a helper to capture your authenticated state after manually logging in:
|
1150
|
+
|
1151
|
+
**Step 1: Login manually in Chrome**
|
1152
|
+
```bash
|
1153
|
+
# Open your app and complete the SSO login manually
|
1154
|
+
# This handles all the OAuth redirects, token exchanges, etc.
|
1155
|
+
```
|
1156
|
+
|
1157
|
+
**Step 2: Capture authentication state**
|
1158
|
+
```bash
|
1159
|
+
# Capture all cookies and storage from your logged-in session
|
1160
|
+
cursorflow capture-auth --base-url http://localhost:3000 \
|
1161
|
+
--path /dashboard \
|
1162
|
+
--output sso-auth.json
|
1163
|
+
|
1164
|
+
# This opens a browser, lets you login, then captures:
|
1165
|
+
# - All cookies (including third-party cookies if needed)
|
1166
|
+
# - localStorage state
|
1167
|
+
# - sessionStorage state
|
1168
|
+
# - Any tokens or auth data
|
1169
|
+
```
|
1170
|
+
|
1171
|
+
**Step 3: Use captured auth in config**
|
1172
|
+
```json
|
1173
|
+
{
|
1174
|
+
"base_url": "http://localhost:3000",
|
1175
|
+
"auth": {
|
1176
|
+
"method": "cookies",
|
1177
|
+
"cookies": [
|
1178
|
+
// Automatically populated from capture-auth
|
1179
|
+
{
|
1180
|
+
"name": "auth_token",
|
1181
|
+
"value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
|
1182
|
+
"domain": "yourapp.com",
|
1183
|
+
"path": "/",
|
1184
|
+
"httpOnly": true,
|
1185
|
+
"secure": true
|
1186
|
+
},
|
1187
|
+
{
|
1188
|
+
"name": "refresh_token",
|
1189
|
+
"value": "abc123...",
|
1190
|
+
"domain": "yourapp.com",
|
1191
|
+
"path": "/",
|
1192
|
+
"httpOnly": true,
|
1193
|
+
"secure": true
|
1194
|
+
}
|
1195
|
+
]
|
1196
|
+
}
|
1197
|
+
}
|
1198
|
+
```
|
1199
|
+
|
1200
|
+
**Alternative: Manual Cookie Extraction**
|
1201
|
+
|
1202
|
+
If `capture-auth` is not available, extract cookies manually:
|
1203
|
+
|
1204
|
+
**For Google SSO:**
|
1205
|
+
```bash
|
1206
|
+
# 1. Login via Google in Chrome
|
1207
|
+
# 2. DevTools (F12) → Application → Cookies
|
1208
|
+
# 3. Look for cookies from BOTH domains:
|
1209
|
+
# - yourapp.com (your application cookies)
|
1210
|
+
# - accounts.google.com (Google auth cookies, if needed)
|
1211
|
+
# 4. Copy all authentication-related cookies:
|
1212
|
+
```
|
1213
|
+
|
1214
|
+
**For Microsoft/Azure AD SSO:**
|
1215
|
+
```bash
|
1216
|
+
# Same process, look for:
|
1217
|
+
# - yourapp.com cookies
|
1218
|
+
# - login.microsoftonline.com cookies (if needed)
|
1219
|
+
# - Any cookies with names like: auth_token, id_token, access_token
|
1220
|
+
```
|
1221
|
+
|
1222
|
+
**For Okta/Auth0:**
|
1223
|
+
```bash
|
1224
|
+
# Look for cookies like:
|
1225
|
+
# - okta-oauth-redirect-params
|
1226
|
+
# - okta-oauth-state
|
1227
|
+
# - sid (session ID)
|
1228
|
+
# - dt (device token)
|
1229
|
+
```
|
1230
|
+
|
1231
|
+
**Complete cookie capture example:**
|
1232
|
+
```json
|
1233
|
+
{
|
1234
|
+
"auth": {
|
1235
|
+
"method": "cookies",
|
1236
|
+
"cookies": [
|
1237
|
+
{
|
1238
|
+
"name": "appSession",
|
1239
|
+
"value": "long-base64-encoded-value...",
|
1240
|
+
"domain": "yourapp.com",
|
1241
|
+
"path": "/",
|
1242
|
+
"httpOnly": true,
|
1243
|
+
"secure": true,
|
1244
|
+
"sameSite": "Lax"
|
1245
|
+
},
|
1246
|
+
{
|
1247
|
+
"name": "identity.token",
|
1248
|
+
"value": "another-long-token...",
|
1249
|
+
"domain": "yourapp.com",
|
1250
|
+
"path": "/",
|
1251
|
+
"httpOnly": false,
|
1252
|
+
"secure": true,
|
1253
|
+
"sameSite": "None"
|
1254
|
+
}
|
1255
|
+
]
|
1256
|
+
}
|
1257
|
+
}
|
1258
|
+
```
|
1259
|
+
|
1260
|
+
**SSO Best Practices:**
|
1261
|
+
|
1262
|
+
1. **Capture all cookies**: SSO often uses multiple cookies
|
1263
|
+
2. **Check localStorage**: Some SSO solutions store tokens in localStorage
|
1264
|
+
3. **Watch for expiration**: SSO tokens typically expire (1 hour - 24 hours)
|
1265
|
+
4. **Test token validity**:
|
1266
|
+
```bash
|
1267
|
+
cursorflow test --use-session "sso-user" --path /dashboard
|
1268
|
+
# If fails, capture fresh session
|
1269
|
+
```
|
1270
|
+
|
1271
|
+
5. **Multi-domain considerations**: Some SSO requires cookies on multiple domains
|
1272
|
+
```json
|
1273
|
+
{
|
1274
|
+
"auth": {
|
1275
|
+
"method": "cookies",
|
1276
|
+
"cookies": [
|
1277
|
+
{"name": "app_session", "domain": "yourapp.com", "value": "..."},
|
1278
|
+
{"name": "sso_token", "domain": "sso.yourapp.com", "value": "..."}
|
1279
|
+
]
|
1280
|
+
}
|
1281
|
+
}
|
1282
|
+
```
|
1283
|
+
|
1284
|
+
**Refreshing SSO Tokens:**
|
1285
|
+
|
1286
|
+
SSO tokens expire. When they do:
|
1287
|
+
```bash
|
1288
|
+
# 1. Clear old session
|
1289
|
+
cursorflow sessions delete "sso-user"
|
1290
|
+
|
1291
|
+
# 2. Manually login again in Chrome
|
1292
|
+
|
1293
|
+
# 3. Capture new auth state
|
1294
|
+
cursorflow capture-auth --base-url http://localhost:3000 \
|
1295
|
+
--path /dashboard \
|
1296
|
+
--output sso-auth-refreshed.json
|
1297
|
+
|
1298
|
+
# 4. Update config with new tokens
|
1299
|
+
```
|
1300
|
+
|
1301
|
+
**Programmatic SSO (Advanced):**
|
1302
|
+
|
1303
|
+
For automated SSO without manual login, you need service account credentials from your identity provider. This is complex and varies by provider - consult your SSO provider's documentation for headless authentication flows.
|
1304
|
+
|
1137
1305
|
##### **Environment-Specific Auth**
|
1138
1306
|
|
1139
1307
|
Different credentials for local/staging/production:
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
4
4
|
|
5
5
|
[project]
|
6
6
|
name = "cursorflow"
|
7
|
-
version = "2.7.
|
7
|
+
version = "2.7.8"
|
8
8
|
description = "🔥 Complete page intelligence for AI-driven development with Hot Reload Intelligence - captures DOM, network, console, performance, HMR events, and comprehensive page analysis"
|
9
9
|
authors = [
|
10
10
|
{name = "GeekWarrior Development", email = "rbush@cooltheory.com"}
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|