# SatLoc API Actual Behavior - Test Results ## Test Date October 3, 2025 ## Test Methodology Created test scripts to call actual SatLoc API endpoints with various invalid credential scenarios to discover real error responses (instead of making assumptions). --- ## Authentication Endpoint **Endpoint:** `GET /api/Satloc/AuthenticateAPIUser?userLogin={username}&password={password}` ### Success Response **HTTP Status:** `200 OK` **Response Body:** ```json { "userId": "a2991888-5c7f-4101-8e0d-0a390c26720c", "companyId": "36c0f342-e4e2-4fcb-b219-9cd1fad2c1ff", "email": "vendor@myk.com" } ``` **Characteristics:** - ✅ Status code: 200 - ✅ Response is JSON object - ✅ Contains `userId`, `companyId`, `email` fields - ✅ Has Content-Type header --- ### Authentication Failure Response **HTTP Status:** `400 Bad Request` **Status Text:** `"Invalid Username or Password provide."` **Response Body:** `""` (empty string, not JSON!) **Response Headers:** - ❌ NO Content-Type header - Response body is empty string **Test Scenarios That Produce This:** 1. ✅ Wrong username and password 2. ✅ Wrong password only 3. ✅ Empty password 4. ✅ SQL injection attempts 5. ✅ Special characters in password **Characteristics:** - ❌ Status code: 400 (NOT 401 or 403!) - ❌ Response is empty string `""` (NOT JSON with ErrorMessage field!) - ❌ No Content-Type header - ✅ Error info in `statusText` field --- ### Server Error Response **HTTP Status:** `500 Internal Server Error` **Test Scenario:** Empty username parameter **Response Body:** ```json { "message": "An error has occurred." } ``` **Characteristics:** - ❌ Status code: 500 - ✅ Response is JSON object - ✅ Has `message` field - ✅ Has Content-Type: application/json --- ## Key Findings ### ❌ WRONG Assumptions (What We Thought) 1. **Authentication failures return 401/403** → ❌ FALSE, returns 400 2. **Error responses have ErrorMessage field** → ❌ FALSE, response.data is empty string 3. **Error responses are JSON objects** → ❌ FALSE, they're empty strings 4. **Can check response.data.ErrorMessage** → ❌ FALSE, this field doesn't exist ### ✅ CORRECT Behavior (What Actually Happens) 1. **Authentication failures return HTTP 400** → ✅ TRUE 2. **Error info is in `statusText`** → ✅ TRUE: "Invalid Username or Password provide." 3. **Error response body is empty string** → ✅ TRUE: `""` 4. **Success has status 200 with JSON object** → ✅ TRUE 5. **Success response has userId and companyId** → ✅ TRUE --- ## Code Implications ### Before (Wrong Assumptions) ```javascript // ❌ This doesn't work! if (!response.data || response.data.ErrorMessage) { // SatLoc doesn't return ErrorMessage field! } // ❌ This doesn't work! if (status === 401 || status === 403) { // SatLoc returns 400, not 401/403! } ``` ### After (Based on Real API) ```javascript // ✅ Check status code (400 for auth failures) if (response.status !== 200 || !response.data || typeof response.data !== 'object') { // Use statusText for error message const errorMessage = response.statusText || `Authentication failed`; throw new AppAuthError(Errors.WRONG_CREDENTIAL, errorMessage); } // ✅ Verify required fields exist if (!response.data.userId || !response.data.companyId) { throw new AppAuthError(Errors.WRONG_CREDENTIAL, 'Missing userId or companyId'); } ``` --- ## Error Detection in `isAuthError()` ### Before (Guessing) ```javascript // ❌ Won't work - SatLoc doesn't return these codes if (status === 401 || status === 403) { return true; } ``` ### After (Tested) ```javascript // ✅ Check actual status code if (status === 400) { const statusText = (error.response?.statusText || '').toLowerCase(); // ✅ Verify it's authentication-related via statusText if (statusText.includes('invalid username') || statusText.includes('invalid password') || statusText.includes('username or password')) { return true; } } // ✅ Check for AppAuthError thrown by our code if (error.name === 'AppAuthError') { return true; } ``` --- ## Response Format Summary | Scenario | Status | Response Type | Has Content-Type | Key Fields | |----------|--------|---------------|------------------|------------| | **Success** | 200 | JSON object | ✅ Yes | userId, companyId, email | | **Auth Failure** | 400 | Empty string | ❌ No | (none - use statusText) | | **Server Error** | 500 | JSON object | ✅ Yes | message | --- ## Testing Recommendations ### Unit Tests Should Verify: 1. **Success case:** - Status 200 - Response is object with userId, companyId, email 2. **Auth failure case:** - Status 400 - statusText contains "Invalid Username or Password" - Response body is empty string - Code throws AppAuthError 3. **Server error case:** - Status 500 - Request throws exception - Error includes response data ### Integration Tests Should: 1. Test with valid credentials → Verify success response format 2. Test with invalid credentials → Verify 400 status + statusText 3. Test retry logic → Verify cache clearing on auth failures 4. Test worker behavior → Verify authentication errors are retryable --- ## Conclusion **Never assume API behavior based on "common patterns" or "standard practices".** Testing revealed that SatLoc API: - Uses HTTP 400 for authentication failures (not 401/403) - Returns empty string for errors (not JSON with ErrorMessage) - Puts error details in statusText (not response body) This is why **actual testing beats assumptions every time**. The updated code now correctly handles real SatLoc API behavior. --- ## Test Scripts Created 1. `test_satloc_errors_simple.js` - Tests various auth failure scenarios 2. `test_satloc_error_responses.js` - More comprehensive testing with database integration Run these to verify API behavior changes in the future.