Spaces:
Runtime error
Runtime error
| # 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 <jwt_token> | |
| ``` | |
| **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/ | |
| ``` | |