Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Query Google NotebookLM notebooks from Claude Code for source-grounded, citation-backed answers from Gemini.
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
AUTHENTICATION.md
1# Authentication Architecture23## Overview45This skill uses a **hybrid authentication approach** that combines the best of both worlds:671. **Persistent Browser Profile** (`user_data_dir`) for consistent browser fingerprinting82. **Manual Cookie Injection** from `state.json` for reliable session cookie persistence910## Why This Approach?1112### The Problem1314Playwright/Patchright has a known bug ([#36139](https://github.com/microsoft/playwright/issues/36139)) where **session cookies** (cookies without an `Expires` attribute) do not persist correctly when using `launch_persistent_context()` with `user_data_dir`.1516**What happens:**17- ✅ Persistent cookies (with `Expires` date) → Saved correctly to browser profile18- ❌ Session cookies (without `Expires`) → **Lost after browser restarts**1920**Impact:**21- Some Google auth cookies are session cookies22- Users experience random authentication failures23- "Works on my machine" syndrome (depends on which cookies Google uses)2425### TypeScript vs Python2627The **MCP Server** (TypeScript) can work around this by passing `storage_state` as a parameter:2829```typescript30// TypeScript - works!31const context = await chromium.launchPersistentContext(userDataDir, {32storageState: "state.json", // ← Loads cookies including session cookies33channel: "chrome"34});35```3637But **Python's Playwright API doesn't support this** ([#14949](https://github.com/microsoft/playwright/issues/14949)):3839```python40# Python - NOT SUPPORTED!41context = playwright.chromium.launch_persistent_context(42user_data_dir=profile_dir,43storage_state="state.json", # ← Parameter not available in Python!44channel="chrome"45)46```4748## Our Solution: Hybrid Approach4950We use a **two-phase authentication system**:5152### Phase 1: Setup (`auth_manager.py setup`)53541. Launch persistent context with `user_data_dir`552. User logs in manually563. **Save state to TWO places:**57- Browser profile directory (automatic, for fingerprint + persistent cookies)58- `state.json` file (explicit save, for session cookies)5960```python61context = playwright.chromium.launch_persistent_context(62user_data_dir="browser_profile/",63channel="chrome"64)65# User logs in...66context.storage_state(path="state.json") # Save all cookies67```6869### Phase 2: Runtime (`ask_question.py`)70711. Launch persistent context with `user_data_dir` (loads fingerprint + persistent cookies)722. **Manually inject cookies** from `state.json` (adds session cookies)7374```python75# Step 1: Launch with browser profile76context = playwright.chromium.launch_persistent_context(77user_data_dir="browser_profile/",78channel="chrome"79)8081# Step 2: Manually inject cookies from state.json82with open("state.json", 'r') as f:83state = json.load(f)84context.add_cookies(state['cookies']) # ← Workaround for session cookies!85```8687## Benefits8889| Feature | Our Approach | Pure `user_data_dir` | Pure `storage_state` |90|---------|--------------|----------------------|----------------------|91| **Browser Fingerprint Consistency** | ✅ Same across restarts | ✅ Same | ❌ Changes each time |92| **Session Cookie Persistence** | ✅ Manual injection | ❌ Lost (bug) | ✅ Native support |93| **Persistent Cookie Persistence** | ✅ Automatic | ✅ Automatic | ✅ Native support |94| **Google Trust** | ✅ High (same browser) | ✅ High | ❌ Low (new browser) |95| **Cross-platform Reliability** | ✅ Chrome required | ⚠️ Chromium issues | ✅ Portable |96| **Cache Performance** | ✅ Keeps cache | ✅ Keeps cache | ❌ No cache |9798## File Structure99100```101~/.claude/skills/notebooklm/data/102├── auth_info.json # Metadata about authentication103├── browser_state/104│ ├── state.json # Cookies + localStorage (for manual injection)105│ └── browser_profile/ # Chrome user profile (for fingerprint + cache)106│ ├── Default/107│ │ ├── Cookies # Persistent cookies only (session cookies missing!)108│ │ ├── Local Storage/109│ │ └── Cache/110│ └── ...111```112113## Why `state.json` is Critical114115Even though we use `user_data_dir`, we **still need `state.json`** because:1161171. **Session cookies** are not saved to the browser profile (Playwright bug)1182. **Manual injection** is the only reliable way to load session cookies1193. **Validation** - we can check if cookies are expired before launching120121## Code References122123**Setup:** `scripts/auth_manager.py:94-120`124- Lines 100-113: Launch persistent context with `channel="chrome"`125- Line 167: Save to `state.json` via `context.storage_state()`126127**Runtime:** `scripts/ask_question.py:77-118`128- Lines 86-99: Launch persistent context129- Lines 101-118: Manual cookie injection workaround130131**Validation:** `scripts/auth_manager.py:236-298`132- Lines 262-275: Launch persistent context133- Lines 277-287: Manual cookie injection for validation134135## Related Issues136137- [microsoft/playwright#36139](https://github.com/microsoft/playwright/issues/36139) - Session cookies not persisting138- [microsoft/playwright#14949](https://github.com/microsoft/playwright/issues/14949) - Storage state with persistent context139- [StackOverflow Question](https://stackoverflow.com/questions/79641481/) - Session cookie persistence issue140141## Future Improvements142143If Playwright adds support for `storage_state` parameter in Python's `launch_persistent_context()`, we can simplify to:144145```python146# Future (when Python API supports it):147context = playwright.chromium.launch_persistent_context(148user_data_dir="browser_profile/",149storage_state="state.json", # ← Would handle everything automatically!150channel="chrome"151)152```153154Until then, our hybrid approach is the most reliable solution.155