# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Project Overview

**JWT Token Harvester v2** is a Chrome Manifest V3 extension designed for development and testing purposes. It intercepts and extracts JWT tokens from requests to QA environments (`insights.qaorch.com` and `qa-ows-grass.theorchard.io`).

## Architecture

### Core Components

#### Service Worker (background.js)

Handles message passing between content scripts and popup, stores captured tokens in `chrome.storage.local`, uses WebRequest API to intercept GraphQL requests and extract Authorization headers, and updates extension badge when tokens are captured.

#### Content Script (content.js)

Intercepts fetch and XHR requests to extract JWT tokens from Authorization headers using multiple detection strategies with periodic monitoring to ensure interceptors remain active.

#### Popup UI (popup.html + popup.js)

Displays captured token status with expiry and grants information, shows token preview (truncated for security), provides copy-to-clipboard functionality, displays timestamp for when token was captured, and allows manual page refresh when token is expired.

### Token Capture & Processing

The extension uses multiple interception strategies (layered defense approach):

1. **Fetch API Override**: Wraps `window.fetch` to intercept Authorization headers
   - Uses persistent interceptor with `Object.defineProperty` to prevent overrides
   - Periodic monitoring ensures interceptor stays in place

2. **XMLHttpRequest Override**: Intercepts `XHR.setRequestHeader` calls
   - Uses `WeakMap` to track request metadata
   - Captures Authorization headers before request is sent

3. **WebRequest API** (background.js): Browser-level request interception
   - Most reliable method - cannot be bypassed by page JavaScript
   - Intercepts requests to `qa-ows-grass.theorchard.io`
   - Direct access to request headers before transmission

### Token Analysis Features

**JWT Decoding**: Automatically decodes captured tokens to extract:

- Expiry time (`exp` claim)
- Grants/permissions (checks `grants`, `permissions`, `roles`, or `scope` claims)
- Other payload data

**Expiry Handling**:

- Automatically refreshes page if expired token is detected
- Badge changes to warning (⚠) for expired tokens
- Displays time remaining until expiry
- Manual refresh button available in popup when expired

**Grants Display**: Shows permissions/roles from token in the popup UI

### Message Passing Protocol

**Content Script → Background**:

```javascript
{
  action: 'tokenFound',
  token: string,
  url: string
}
```

**Popup → Background**:

```javascript
{ action: 'getToken' }    // Retrieve stored token
{ action: 'clearToken' }  // Clear storage
```

**Background → Popup**:

```javascript
{
  jwt_token: string,
  token_timestamp: number,
  source_url: string
}
```

### Storage Schema

Tokens are stored in `chrome.storage.local`:

```javascript
{
  jwt_token: string,          // Raw JWT token
  token_timestamp: number,    // Unix timestamp in ms
  source_url: string          // URL where token was captured
}
```

## Development

### Loading the Extension

1. Navigate to `chrome://extensions`
2. Enable "Developer mode"
3. Click "Load unpacked"
4. Select this directory

### Testing Changes

After modifying files, click the reload button for the extension in `chrome://extensions`, then reload the target webpage.

### Debugging

- **Service Worker**: Navigate to `chrome://extensions`, click "Service worker" link
- **Content Script**: Open DevTools on target page, check Console tab
- **Popup**: Right-click extension icon, select "Inspect popup"

## Code Patterns

### Adding New Token Sources

When adding new interception points, extract tokens using this pattern:

```javascript
if (authHeader && authHeader.startsWith('Bearer ')) {
  const token = authHeader.substring(7);
  chrome.runtime.sendMessage({
    action: 'tokenFound',
    token: token,
    url: requestUrl
  });
}
```

### Interceptor Persistence

The fetch interceptor uses defensive programming to prevent being overridden:

- Captures original `window.fetch` before page loads
- Uses `Object.defineProperty` with `configurable: false`
- Periodic monitoring checks if interceptor is still active
- Reinstalls if overridden by application code

### Security

This extension is for development/testing only. Tokens are stored locally in Chrome storage (not synced), never transmitted outside the extension, and only intercepted from specified QA domains.

## Manifest V3 Specific

This extension uses Manifest V3 architecture:

- `background.js` is a service worker (not persistent background page)
- Must use `chrome.storage.local` (not variables) for persistence
- Message passing requires explicit `sendResponse` callback pattern
- `return true` required for async `sendResponse` in message listeners
- Uses `tabs` permission for automatic page refresh functionality

## Target Environment

The extension is configured for:

- **Frontend**: `https://insights.qaorch.com/*`
- **GraphQL API**: `https://qa-ows-grass.theorchard.io/*`

To add new domains, update `manifest.json` (`host_permissions` and `content_scripts.matches`) and `background.js` (WebRequest listener URLs).
