# Authentication API Documentation ## Overview The nostr_core_lib unified request validation system provides a comprehensive authentication and authorization framework for Nostr-based applications. It combines Nostr event validation with flexible rule-based authentication in a single API call. ## Authentication Flow and Order of Operations ### Authentication Flow Diagram ``` ┌─────────────────────┐ │ Request Received │ └──────────┬──────────┘ │ ▼ ┌─────────────┐ ╔═══════════════════╗ │ Input Valid?├─No─►║ REJECT: Invalid ║ └──────┬──────┘ ║ Input (~1μs) ║ │Yes ╚═══════════════════╝ ▼ ┌─────────────┐ ╔═══════════════════╗ │System Init? ├─No─►║ REJECT: Not ║ └──────┬──────┘ ║ Initialized ║ │Yes ╚═══════════════════╝ ▼ ┌─────────────┐ │Auth Header? │ └──────┬──────┘ │Yes ▼ ┌─────────────────────┐ ┌─────────────┐ No │ │ │Parse Header ├────────────┤ Skip Nostr │ └──────┬──────┘ │ Validation │ │ │ │ ▼ └──────────┬──────────┘ ┌─────────────┐ ╔═══════════════════╗ │ │Valid Base64?├─No─►║ REJECT: Malformed ║ │ └──────┬──────┘ ║ Header (~10μs) ║ │ │Yes ╚═══════════════════╝ │ ▼ │ ┌─────────────┐ ╔═══════════════════╗ │ │Valid JSON? ├─No─►║ REJECT: Invalid ║ │ └──────┬──────┘ ║ JSON (~50μs) ║ │ │Yes ╚═══════════════════╝ │ ▼ │ ┌─────────────┐ ╔═══════════════════╗ │ │Valid Struct?├─No─►║ REJECT: Invalid ║ │ └──────┬──────┘ ║ Structure (~100μs)║ │ │Yes ╚═══════════════════╝ │ ▼ │ ┌─────────────────┐ ╔═══════════════════╗ │ │ ECDSA Signature │No ║ REJECT: Invalid ║ │ │ Verify (~2ms) ├──►║ Signature (~2ms) ║ │ └─────────┬───────┘ ╚═══════════════════╝ │ │Yes │ ▼ │ ┌─────────────────┐ ╔═══════════════════╗ │ │Operation Match? │No ║ REJECT: Unauth. ║ | └─────────┬───────┘ ║ Operation (~200μs)║ │ │Yes ╚═══════════════════╝ │ ▼ │ ┌─────────────────┐ ╔═══════════════════╗ │ │Event Expired? │Yes║ REJECT: Expired ║ │ └─────────┬───────┘ ║ Event (~50μs) ║ │ │No ╚═══════════════════╝ │ ▼ │ ┌─────────────────┐ │ │Extract Pubkey │ │ └─────────┬───────┘ │ │ │ ▼◄───────────────────────────────────────┘ ┌─────────────────┐ ╔═══════════════════╗ │Auth Rules │ No ║ ALLOW: Rules ║ │Enabled? ├────►║ Disabled ║ └─────────┬───────┘ ╚═══════════════════╝ │Yes ▼ ┌─────────────────┐ │Generate Cache │ │Key (SHA-256) │ └─────────┬───────┘ │ ▼ ┌─────────────────┐ ╔═══════════════════╗ │Cache Hit? │ Yes ║ RETURN: Cached ║ │(~100μs lookup) ├────►║ Decision (~100μs) ║ └─────────┬───────┘ ╚═══════════════════╝ │No ▼ ╔═══════════════════════════════════════╗ ║ RULE EVALUATION ENGINE ║ ║ (Priority Order) ║ ╚═══════════════════════════════════════╝ │ ▼ ┌─────────────────┐ ╔═══════════════════╗ │1. Pubkey │ Yes ║ DENY: Pubkey ║ │ Blacklisted? ├────►║ Blocked ║ └─────────┬───────┘ ╚═══════════════════╝ │No ▼ ┌─────────────────┐ ╔═══════════════════╗ │2. Hash │ Yes ║ DENY: Hash ║ │ Blacklisted? ├────►║ Blocked ║ └─────────┬───────┘ ╚═══════════════════╝ │No ▼ ┌─────────────────┐ ╔═══════════════════╗ │3. MIME Type │ Yes ║ DENY: MIME ║ │ Blacklisted? ├────►║ Blocked ║ └─────────┬───────┘ ╚═══════════════════╝ │No ▼ ┌─────────────────┐ ╔═══════════════════╗ │4. Size Limit │ Yes ║ DENY: File ║ │ Exceeded? ├────►║ Too Large ║ └─────────┬───────┘ ╚═══════════════════╝ │No ▼ ┌─────────────────┐ ╔═══════════════════╗ │5. Pubkey │ Yes ║ ALLOW: Pubkey ║ │ Whitelisted? ├────►║ Whitelisted ║ └─────────┬───────┘ ╚═══════════════════╝ │No ▼ ┌─────────────────┐ ╔═══════════════════╗ │6. MIME Type │ Yes ║ ALLOW: MIME ║ │ Whitelisted? ├────►║ Whitelisted ║ └─────────┬───────┘ ╚═══════════════════╝ │No ▼ ┌─────────────────┐ ╔═══════════════════╗ │Whitelist Rules │ Yes ║ DENY: Not in ║ │Exist? ├────►║ Whitelist ║ └─────────┬───────┘ ╚═══════════════════╝ │No ▼ ╔═══════════════════╗ ║ ALLOW: Default ║ ║ Allow Policy ║ ╚═══════════════════╝ │ ▼ ┌─────────────────┐ │ Cache Decision │ │ (5min TTL) │ └─────────┬───────┘ │ ▼ ┌─────────────────┐ │ Return Result │ │ to Application │ └─────────────────┘ ``` ### Performance Timeline (ASCII) ``` Fast Path (Cache Hit) - Total: ~101μs ┌─────┬─────────────────────────────────────────────────────────────────┬──────┐ │ 1μs │ 100μs Cache Lookup │ 1μs │ └─────┴─────────────────────────────────────────────────────────────────┴──────┘ Input │ │ Return Valid │ SQLite SELECT │ Result Typical Path (Valid Request) - Total: ~2.4ms ┌──┬───┬────┬─────────────────────────┬────────┬────┬──┐ │1μ│50μ│100μ│ 2000μs │ 200μs │100μ│1μ│ └──┴───┴────┴─────────────────────────┴────────┴────┴──┘ │ │ │ │ │ │ │ │ │ │ │ ECDSA Signature │ Rule │Cache│Return │ │ │ │ Verification │ Eval │Store│Result │ │ │ │ (Most Expensive) │ │ │ │ │ │ │ │ JSON Parse │ Header Parse Input Validation Worst Case (Full Validation) - Total: ~2.7ms ┌──┬───┬────┬─────────────────────────┬─────────┬────┬──┐ │1μ│50μ│100μ│ 2000μs │ 500μs │100μ│1μ│ └──┴───┴────┴─────────────────────────┴─────────┴────┴──┘ │ All 6 Rule Checks (Multiple DB Queries) ``` ### Request Processing Flow (DDoS-Optimized) The authentication system is designed with **performance and DDoS protection** as primary concerns. Here's the exact order of operations: #### Phase 1: Input Validation (Immediate Rejection) 1. **Null Pointer Checks** - Reject malformed requests instantly (lines 122-128) 2. **Initialization Check** - Verify system is properly initialized 3. **Basic Structure Validation** - Ensure required fields are present #### Phase 2: Nostr Event Validation (CPU Intensive) 4. **Authorization Header Parsing** (lines 139-148) - Extract base64-encoded Nostr event from `Authorization: Nostr ` header - Decode base64 to JSON (memory allocation + decoding) - **Early exit**: Invalid base64 or malformed header rejected immediately 5. **JSON Parsing** (lines 150-156) - Parse Nostr event JSON using cJSON - **Early exit**: Invalid JSON rejected before signature verification 6. **Nostr Event Structure Validation** (lines 159-166) - Validate event has required fields (kind, pubkey, sig, etc.) - Check event kind is 24242 for Blossom operations - **Early exit**: Invalid structure rejected before expensive crypto operations 7. **Cryptographic Signature Verification** (lines 159-166) - **Most CPU-intensive operation** - ECDSA signature verification - Validates event authenticity using secp256k1 - **Early exit**: Invalid signatures rejected before database queries 8. **Operation-Specific Validation** (lines 169-178) - Verify event authorizes the requested operation (upload/delete/list) - Check required tags (t=operation, x=hash, expiration) - Validate timestamp and expiration - **Early exit**: Expired or mismatched events rejected 9. **Public Key Extraction** (lines 181-184) - Extract validated public key from event for rule evaluation #### Phase 3: Authentication Rules (Database Queries) 10. **Rules System Check** (line 191) - Quick config check if authentication rules are enabled - **Early exit**: If disabled, allow request immediately 11. **Cache Lookup** (lines 1051-1054) - Generate SHA-256 cache key from request parameters - Check SQLite cache for previous decision - **Early exit**: Cache hit returns cached decision (5-minute TTL) 12. **Rule Evaluation** (Priority Order - lines 1061-1094): - **a. Pubkey Blacklist** (highest priority) - Immediate denial if matched - **b. Hash Blacklist** - Block specific content hashes - **c. MIME Type Blacklist** - Block dangerous file types - **d. File Size Limits** - Enforce upload size restrictions - **e. Pubkey Whitelist** - Allow specific users (only if not denied above) - **f. MIME Type Whitelist** - Allow specific file types 13. **Whitelist Default Denial** (lines 1097-1121) - If whitelist rules exist but none matched, deny request - Prevents whitelist bypass attacks 14. **Cache Storage** (line 1124) - Store decision in cache for future requests (5-minute TTL) ### DDoS Protection Features #### **Fail-Fast Design** - **Input validation** happens before any expensive operations - **Authorization header parsing** fails fast on malformed data - **JSON parsing** rejects invalid data before signature verification - **Structure validation** happens before cryptographic operations #### **Expensive Operations Last** - **Signature verification** only after structure validation - **Database queries** only after successful Nostr validation - **Cache prioritized** over database queries #### **Caching Strategy** - **SHA-256 cache keys** prevent cache pollution attacks - **5-minute TTL** balances performance with rule changes - **LRU eviction** prevents memory exhaustion - **Per-request caching** includes all parameters (pubkey, operation, hash, MIME, size) #### **Resource Limits** - **JSON parsing** limited to 4KB buffer size - **Cache entries** limited to prevent memory exhaustion - **Database connection pooling** (single connection with proper cleanup) - **String length limits** on all inputs #### **Attack Mitigation** - **Base64 bombs** - Limited decode buffer size (4KB) - **JSON bombs** - cJSON library handles malformed JSON safely - **Cache poisoning** - Cryptographic cache keys prevent collisions - **Rule bypass** - Whitelist default denial prevents unauthorized access - **Replay attacks** - Timestamp and expiration validation - **Hash collision attacks** - Full SHA-256 verification ### Performance Characteristics #### **Best Case** (Cached Decision): 1. Input validation: ~1μs 2. Cache lookup: ~100μs (SQLite SELECT) 3. **Total: ~101μs** #### **Worst Case** (Full Validation + Rule Evaluation): 1. Input validation: ~1μs 2. Base64 decoding: ~50μs 3. JSON parsing: ~100μs 4. Signature verification: ~2000μs (ECDSA) 5. Database queries: ~500μs (6 rule checks) 6. Cache storage: ~100μs 7. **Total: ~2751μs (~2.7ms)** #### **Typical Case** (Valid Request, Rules Enabled): 1. Full validation: ~2200μs 2. Cache miss, 2-3 rule checks: ~200μs 3. **Total: ~2400μs (~2.4ms)** ### Security Order Rationale The rule evaluation order is specifically designed for security: 1. **Blacklists First** - Immediate denial of known bad actors 2. **Resource Limits** - Prevent resource exhaustion attacks 3. **Whitelists Last** - Only allow after passing all security checks 4. **Default Deny** - If whitelists exist but don't match, deny This ensures that even if an attacker bypasses one layer, subsequent layers will catch the attack. ## Core API ### Primary Function ```c int nostr_validate_request(nostr_request_t* request, nostr_request_result_t* result); ``` This single function handles: - Nostr event signature validation - Event structure validation (required fields, timestamps) - Authentication rule evaluation - Public key extraction and validation ### Request Structure ```c typedef struct { const char* event_json; // Raw Nostr event JSON const char* app_id; // Application identifier ("ginxsom", "c-relay") const char* operation; // Operation type ("upload", "delete", "list") const char* content_hash; // SHA-256 hash for file operations (optional) const char* mime_type; // MIME type for upload operations (optional) size_t content_size; // File size for upload operations (0 if N/A) } nostr_request_t; ``` ### Result Structure ```c typedef struct { int is_valid; // 1 if request is valid, 0 otherwise int error_code; // Specific error code (see Error Codes) char error_message[512]; // Human-readable error description char pubkey[65]; // Extracted public key (hex, null-terminated) time_t timestamp; // Event timestamp char event_id[65]; // Event ID (hex, null-terminated) } nostr_request_result_t; ``` ## Authentication Rules System The system supports priority-based authentication rules that are evaluated in order: ### Rule Types 1. **NOSTR_AUTH_RULE_PUBKEY_WHITELIST** - Allow specific public keys 2. **NOSTR_AUTH_RULE_PUBKEY_BLACKLIST** - Block specific public keys 3. **NOSTR_AUTH_RULE_HASH_BLACKLIST** - Block specific content hashes 4. **NOSTR_AUTH_RULE_MIME_RESTRICTION** - Restrict allowed MIME types 5. **NOSTR_AUTH_RULE_SIZE_LIMIT** - Enforce maximum file sizes ### Rule Evaluation - Rules are processed by priority (lower numbers = higher priority) - First matching rule determines the outcome - ALLOW rules permit the request - DENY rules reject the request - If no rules match, the default action is ALLOW ### Rule Caching The system includes an intelligent caching mechanism: - LRU (Least Recently Used) eviction policy - Configurable cache size (default: 1000 entries) - Cache keys based on pubkey + operation + content hash - Automatic cache invalidation when rules change ## Database Backend ### Pluggable Architecture The system uses a pluggable database backend interface: ```c typedef struct { int (*init)(const char* connection_string, void** context); int (*get_rules)(void* context, const char* app_id, nostr_auth_rule_t** rules, int* count); int (*cleanup)(void* context); } nostr_db_backend_t; ``` ### SQLite Implementation Default implementation uses SQLite with the following schema: ```sql -- Authentication rules table (per application) CREATE TABLE auth_rules_[APP_ID] ( id INTEGER PRIMARY KEY AUTOINCREMENT, priority INTEGER NOT NULL, rule_type INTEGER NOT NULL, action INTEGER NOT NULL, pattern TEXT, value_int INTEGER, created_at INTEGER DEFAULT (strftime('%s', 'now')), updated_at INTEGER DEFAULT (strftime('%s', 'now')) ); ``` ## Error Codes The system uses specific error codes for different failure scenarios: - **-50**: `NOSTR_AUTH_ERROR_INVALID_EVENT` - Malformed Nostr event - **-51**: `NOSTR_AUTH_ERROR_INVALID_SIGNATURE` - Invalid event signature - **-52**: `NOSTR_AUTH_ERROR_PUBKEY_BLOCKED` - Public key is blacklisted - **-53**: `NOSTR_AUTH_ERROR_HASH_BLOCKED` - Content hash is blacklisted - **-54**: `NOSTR_AUTH_ERROR_MIME_RESTRICTED` - MIME type not allowed - **-55**: `NOSTR_AUTH_ERROR_SIZE_EXCEEDED` - File size limit exceeded ## Usage Examples ### Basic Validation ```c #include "nostr_core/request_validator.h" // Initialize the system (once per application) int result = nostr_request_validator_init("db/myapp.db", "myapp"); if (result != 0) { fprintf(stderr, "Failed to initialize validator: %d\n", result); return -1; } // Validate a request nostr_request_t request = { .event_json = "{\"kind\":24242,\"pubkey\":\"abc123...\",\"sig\":\"def456...\"}", .app_id = "myapp", .operation = "upload", .content_hash = "sha256hash...", .mime_type = "text/plain", .content_size = 1024 }; nostr_request_result_t result; int status = nostr_validate_request(&request, &result); if (result.is_valid) { printf("Request authorized for pubkey: %s\n", result.pubkey); } else { printf("Request denied: %s (code: %d)\n", result.error_message, result.error_code); } ``` ### Ginxsom Integration The ginxsom application has been updated to use this system: ```c // Replace old authenticate_request_with_rules() calls with: nostr_request_t auth_request = { .event_json = event_json, .app_id = "ginxsom", .operation = "upload", // or "list", "delete" .content_hash = calculated_hash, .mime_type = detected_mime_type, .content_size = file_size }; nostr_request_result_t auth_result; int auth_status = nostr_validate_request(&auth_request, &auth_result); if (!auth_result.is_valid) { printf("Status: 403\r\n"); printf("Content-Type: application/json\r\n\r\n"); printf("{\"error\":\"Authentication failed\",\"message\":\"%s\"}\n", auth_result.error_message); return; } // Use auth_result.pubkey for the authenticated public key ```