# 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:** `:` 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": "" } ``` Note: Password appears to be client-side hashed before sending (format: `hash:base64data`) **Response:** ```json { "cookieName": "anyclip_2020", "cookieValue": "", "token": "", "user": "" } ``` ### Step 2: Main App Login **Endpoint:** `POST https://videomanager.anyclip.com/api/auth/login` **Request:** ```json { "token": "", "tcname": "anyclip_2020", "tcvalue": "" } ``` **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": "", "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=; 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 |