agmission/Development/server/docs/SATLOC_API_ACTUAL_BEHAVIOR.md

223 lines
5.8 KiB
Markdown

# 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.