# Iframe SSO Authentication System - API Documentation ## Overview This system enables secure SSO authentication for Iframe embeds from third-party websites. It validates source domains against a whitelist and generates reusable API keys for seamless user authentication. ## Architecture ``` Frontend (Edlink Payload) ↓ Check Login Status (/auth/iframe/status) ↓ ├─ IF Logged In → Render Iframe │ └─ IF NOT Logged In: ├─ Request API Key (/auth/api-key/generate) ├─ Whitelist Validation ├─ Verify API Key (/auth/api-key/verify) ├─ Get JWT Token ├─ Set Secure Cookie └─ Render Iframe ``` ## Endpoints ### 1. Check Login Status **Endpoint:** `GET /v1/auth/iframe/status` **Description:** Check if user is already logged in via JWT token **Headers:** ``` Authorization: Bearer ``` **Response (200):** ```json { "is_logged_in": true, "user_token": "user-uuid-token", "email": "user@example.com", "name": "John Doe" } ``` **Errors:** - `401 Unauthorized` - No valid token or inactive user --- ### 2. Generate API Key **Endpoint:** `POST /v1/auth/api-key/generate` **Description:** Generate API key with whitelist validation **Request Body:** ```json { "email": "user@example.com", "username": "johndoe", "phone": "+62812345678", "name": "John Doe", "identity_number": "1234567890123456", "source_domain": "https://abdanhafidz.github.io/edlink-simulation" } ``` **Response (200):** ```json { "api_key": "generated-api-key-here", "message": "API key generated successfully" } ``` **Errors:** - `401 Unauthorized` - Source domain not whitelisted - `400 Bad Request` - Invalid payload data --- ### 3. Verify API Key & Login **Endpoint:** `POST /v1/auth/api-key/verify` **Query Parameters:** - `api_key` (string, required) - The API key from step 2 **Response (200):** ```json { "message": "Login successful", "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", "expires_at": "2024-05-20 22:50:00" } ``` **Cookies Set:** - `access_token` (HttpOnly, Secure, SameSite=Lax) **Errors:** - `401 Unauthorized` - Invalid API key --- ## Whitelist Management (Admin) ### Add Domain to Whitelist **Endpoint:** `POST /v1/auth/whitelist` **Request Body:** ```json { "source_type": "domain", "value": "https://abdanhafidz.github.io/edlink-simulation", "description": "Edlink Simulation Platform", "is_active": true } ``` **Supported Formats:** - Exact domain: `example.com`, `https://example.com` - Wildcard subdomain: `*.example.com`, `https://*.example.com` - Full URL: `https://abdanhafidz.github.io/edlink-simulation` --- ## Security Features 1. **Whitelist Validation** - All source domains must be whitelisted before API key generation - Supports exact matching, wildcard subdomains, and full URLs - Case-insensitive domain matching 2. **API Key Security** - API keys are hashed before storage (SHA-256) - Plain API key only returned once during generation - Reusable keys for convenient third-party integration - Can be revoked at any time 3. **JWT Token Security** - Tokens stored in secure HTTP-only cookies - Auto-expire after 1 hour - Validated on every protected request - Secure flag set for HTTPS-only transmission 4. **User Creation** - Auto-created users for new third-party users - Unique user_token per user - Email uniqueness enforced - Default secure password (not shared with frontend) ## Implementation Flow (Frontend Example) ```typescript // Step 1: Check if already logged in async function checkLoginStatus() { const response = await fetch('/v1/auth/iframe/status', { headers: { 'Authorization': `Bearer ${getCookie('access_token')}` } }); if (response.ok) { renderIframe(); // Already logged in return; } // Not logged in, proceed to Step 2 generateAndVerifyAPIKey(); } // Step 2: Generate API Key async function generateAndVerifyAPIKey() { const apiKeyResponse = await fetch('/v1/auth/api-key/generate', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ email: userData.email, username: userData.username, phone: userData.phone, name: userData.name, identity_number: userData.identityNumber, source_domain: window.location.origin }) }); const apiKeyData = await apiKeyResponse.json(); const apiKey = apiKeyData.api_key; // Step 3: Verify API Key & Get JWT await fetch(`/v1/auth/api-key/verify?api_key=${apiKey}`, { method: 'POST' }); // JWT token is now in secure cookie renderIframe(); } // Helper: Get cookie value function getCookie(name) { const value = `; ${document.cookie}`; const parts = value.split(`; ${name}=`); if (parts.length === 2) return parts.pop().split(';').shift(); } ``` ## Database Schema ### Whitelist Table ```sql CREATE TABLE whitelist ( id INT PRIMARY KEY AUTO_INCREMENT, created_at DATETIME, updated_at DATETIME, source_type VARCHAR(50), value VARCHAR(255) UNIQUE INDEX, description VARCHAR(255), is_active BOOLEAN DEFAULT TRUE ); ``` ### API Key Table ```sql CREATE TABLE api_key ( id INT PRIMARY KEY AUTO_INCREMENT, created_at DATETIME, updated_at DATETIME, user_token VARCHAR(255) INDEX, api_key_hash VARCHAR(255) UNIQUE, source_domain VARCHAR(255) INDEX, is_active BOOLEAN DEFAULT TRUE ); ``` ## Environment Requirements No additional environment variables needed beyond existing FastAPI setup. ## Testing Run migration: ```bash alembic upgrade head ``` Run tests: ```bash pytest tests/ ```