Add AnyClip integration tools and extracted source code
- Add authentication scripts with SubtleCrypto password encryption - Add sourcemap extraction pipeline (update-urls, download-sourcemaps, extract-sources) - Add Playwright API interception script for monetization endpoints - Document two-step auth flow with JWT tokens and dual cookies - Move extracted source from root to anyclip/ directory - Add project configuration (.env.example, .gitignore, CLAUDE.md)
This commit is contained in:
168
docs/auth.md
Normal file
168
docs/auth.md
Normal file
@@ -0,0 +1,168 @@
|
||||
# AnyClip Authentication
|
||||
|
||||
## Overview
|
||||
|
||||
AnyClip uses a two-step authentication flow with JWT tokens and cookie-based session management.
|
||||
|
||||
## Password Encryption
|
||||
|
||||
Passwords are encrypted client-side using AES-256-GCM with a static salt.
|
||||
|
||||
**Salt:** `$2b$04$wwky7rvtr6BFNaCqntwyie`
|
||||
|
||||
**Output format:** `<iv_hex>:<hex_encoded_base64_ciphertext>`
|
||||
|
||||
Our implementation uses SubtleCrypto (Web Crypto API) with zero external dependencies:
|
||||
|
||||
```typescript
|
||||
import { encryptString } from './scripts/crypto-subtle';
|
||||
|
||||
const PASS_CRYPTO_SALT = '$2b$04$wwky7rvtr6BFNaCqntwyie';
|
||||
const encryptedPassword = await encryptString(password, PASS_CRYPTO_SALT);
|
||||
```
|
||||
|
||||
**Note:** The original AnyClip client uses `string-crypto@2.0.2`. Version 3.x uses different encoding (base64 vs hex) and is NOT compatible.
|
||||
|
||||
## Authentication Flow
|
||||
|
||||
### Step 1: External API Login
|
||||
|
||||
**Endpoint:** `POST https://videomanager-api.anyclip.com/public/auth/login`
|
||||
|
||||
**Request:**
|
||||
```json
|
||||
{
|
||||
"email": "user@example.com",
|
||||
"password": "<hashed_password>"
|
||||
}
|
||||
```
|
||||
|
||||
Note: Password appears to be client-side hashed before sending (format: `hash:base64data`)
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"cookieName": "anyclip_2020",
|
||||
"cookieValue": "<session_token>",
|
||||
"token": "<jwt_token>",
|
||||
"user": "<base64_encoded_user_json>"
|
||||
}
|
||||
```
|
||||
|
||||
### Step 2: Main App Login
|
||||
|
||||
**Endpoint:** `POST https://videomanager.anyclip.com/api/auth/login`
|
||||
|
||||
**Request:**
|
||||
```json
|
||||
{
|
||||
"token": "<jwt_token_from_step_1>",
|
||||
"tcname": "anyclip_2020",
|
||||
"tcvalue": "<cookie_value_from_step_1>"
|
||||
}
|
||||
```
|
||||
|
||||
**Response:** Sets `session` cookie via `Set-Cookie` header (iron-sealed format: `Fe26.2*...`)
|
||||
|
||||
**Important:** You must capture this session cookie from the response headers and include it with the `anyclip_2020` cookie in all subsequent requests.
|
||||
|
||||
## JWT Token Structure
|
||||
|
||||
The JWT token contains:
|
||||
|
||||
```json
|
||||
{
|
||||
"role": {
|
||||
"id": 15,
|
||||
"name": "publisher_admin",
|
||||
"displayName": "Account Admin",
|
||||
"type": "ACCOUNT"
|
||||
},
|
||||
"slug": "2240",
|
||||
"userId": 16086,
|
||||
"context": "<bcrypt_hash>",
|
||||
"userEmail": "user@example.com",
|
||||
"timezone": "America/New_York",
|
||||
"accountId": 1599,
|
||||
"publisherId": 2240,
|
||||
"salesforceId": "001Te000004ZYO7IAO",
|
||||
"iat": 1768891600,
|
||||
"exp": 1768920400
|
||||
}
|
||||
```
|
||||
|
||||
**Token Expiry:** ~8 hours from issuance
|
||||
|
||||
## User Object (Base64 Decoded)
|
||||
|
||||
Contains extensive user and account data:
|
||||
|
||||
- **User info:** id, firstName, lastName, email, roleId, timezone
|
||||
- **Account info:** id, name, status, type, features, publishers
|
||||
- **Permissions:** Array of permission strings (e.g., "get/analytics", "post/video")
|
||||
- **Account features:** Enabled features like watch, forms, x-ray, video targeting
|
||||
- **Account dashboards:** Available analytics dashboards (Monetization, Video Performance, etc.)
|
||||
- **Publishers:** List of publisher sites associated with the account
|
||||
|
||||
## Session Management
|
||||
|
||||
**Two cookies are required for authentication:**
|
||||
|
||||
| Cookie | Source | Format |
|
||||
|--------|--------|--------|
|
||||
| `anyclip_2020` | External API response body | Plain session token |
|
||||
| `session` | Main API `Set-Cookie` header | Iron-sealed (encrypted) |
|
||||
|
||||
Both cookies must be sent with all authenticated requests:
|
||||
|
||||
```typescript
|
||||
headers: {
|
||||
Cookie: `anyclip_2020=<token>; session=Fe26.2*...`
|
||||
}
|
||||
```
|
||||
|
||||
- **Cookie scope:** `videomanager.anyclip.com`
|
||||
- All API requests include cookies via `credentials: 'same-origin'`
|
||||
|
||||
## Logout
|
||||
|
||||
**Endpoint:** `POST https://videomanager.anyclip.com/api/auth/logout`
|
||||
|
||||
Clears the session cookie.
|
||||
|
||||
## API Request Authentication
|
||||
|
||||
After login, all requests to `videomanager.anyclip.com/api/*` are authenticated via the session cookie.
|
||||
|
||||
**GraphQL Endpoint:** `POST https://videomanager.anyclip.com/api/graphql`
|
||||
|
||||
## Permission System
|
||||
|
||||
Permissions are returned in the user object as an array of strings:
|
||||
|
||||
```
|
||||
analytics-monetization
|
||||
analytics-video-external
|
||||
analytics-custom-reports
|
||||
get/analytics
|
||||
post/video
|
||||
put/video
|
||||
...
|
||||
```
|
||||
|
||||
These control access to:
|
||||
- API endpoints (get/post/put/delete patterns)
|
||||
- UI features (analytics-*, video-*, hosted-watch-*)
|
||||
- Specific capabilities (video-embed, video-share, etc.)
|
||||
|
||||
## Role Types
|
||||
|
||||
- `publisher_admin` - Account Admin (full access)
|
||||
- Other roles with restricted permissions
|
||||
|
||||
## Two Servers
|
||||
|
||||
| Server | Purpose |
|
||||
|--------|---------|
|
||||
| `videomanager-api.anyclip.com` | External auth API (login only) |
|
||||
| `videomanager.anyclip.com` | Main application API |
|
||||
Reference in New Issue
Block a user