Dealer-Specific Access Control
Dealer-Specific Access Control
Overview
AutoElite's API implements dealer-specific access control to ensure that each dealer can only access and modify their own data. This document explains how this feature works and how to implement it in your applications.
How It Works
When an API key is associated with a specific dealer, the AutoElite API automatically enforces access control rules:
- Data Filtering: All queries are automatically filtered to only return data belonging to the associated dealer
- Access Prevention: Attempts to access data from other dealers are rejected
- Automatic Assignment: New data is automatically assigned to the correct dealer
- Modification Restrictions: Updates and deletions are restricted to data owned by the dealer
This happens transparently to the client application, requiring no changes to your API calls.
Implementation Details
API Key Association
API keys are associated with dealers through the dealer_api_keys table:
CREATE TABLE dealer_api_keys (
id INTEGER PRIMARY KEY AUTOINCREMENT,
dealer_id INTEGER NOT NULL,
api_key_id INTEGER NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (dealer_id) REFERENCES dealers(id) ON DELETE CASCADE,
FOREIGN KEY (api_key_id) REFERENCES api_keys(id) ON DELETE CASCADE,
UNIQUE(dealer_id, api_key_id)
);
Middleware Processing
The dealer access control is implemented as middleware that:
- Checks if the API key is associated with a dealer
- Modifies requests to include dealer filtering
- Validates access to specific resources
Endpoint Behavior
GET /api/vehicles
Without Dealer Association:
- Returns all vehicles in the system
- No automatic filtering
With Dealer Association:
- Automatically adds
dealer_idfilter - Only returns vehicles belonging to the associated dealer
- Example:
/api/vehiclesbecomes/api/vehicles?dealer_id=123
GET /api/vehicles/:id
Without Dealer Association:
- Can access any vehicle by ID
With Dealer Association:
- Can only access vehicles belonging to the associated dealer
- Returns 403 Forbidden if attempting to access a vehicle from another dealer
POST /api/vehicles
Without Dealer Association:
- Can create vehicles for any dealer
- Must specify
dealer_idin the request body
With Dealer Association:
- Automatically sets
dealer_idto the associated dealer - Overrides any
dealer_idprovided in the request body - Ensures all created vehicles belong to the correct dealer
PUT /api/vehicles/:id
Without Dealer Association:
- Can update any vehicle
- Can change
dealer_idto reassign vehicles
With Dealer Association:
- Can only update vehicles belonging to the associated dealer
- Cannot change
dealer_idto a different dealer - Returns 403 Forbidden if attempting to update a vehicle from another dealer
DELETE /api/vehicles/:id
Without Dealer Association:
- Can delete any vehicle
With Dealer Association:
- Can only delete vehicles belonging to the associated dealer
- Returns 403 Forbidden if attempting to delete a vehicle from another dealer
Client Implementation
The beauty of this system is that client applications don't need to implement any special logic. The same code works regardless of whether the API key is dealer-specific or not.
Example: Fetching Vehicles
// This code works the same for all API keys
const fetchVehicles = async () => {
const response = await fetch('https://api.autoelite.io/api/vehicles', {
headers: {
'X-API-Key': 'your-api-key-here',
'Content-Type': 'application/json'
}
});
return await response.json();
};
If the API key is associated with dealer ID 123:
- The server automatically filters results to only show vehicles with
dealer_id = 123 - The client receives only the vehicles it should have access to
Example: Creating a Vehicle
// This code works the same for all API keys
const createVehicle = async (vehicleData) => {
const response = await fetch('https://api.autoelite.io/api/vehicles', {
method: 'POST',
headers: {
'X-API-Key': 'your-api-key-here',
'Content-Type': 'application/json'
},
body: JSON.stringify(vehicleData)
});
return await response.json();
};
If the API key is associated with dealer ID 123:
- The server automatically sets
dealer_id = 123in the vehicle data - The vehicle is correctly assigned to the dealer, even if the client doesn't specify a dealer_id
Benefits
Security
- Prevents unauthorized access to other dealers' data
- Eliminates the risk of data leakage between dealers
- Enforces proper data ownership
Simplicity
- No need to modify client code for different dealers
- Same application works for all dealers
- No need to manually filter data by dealer
Maintainability
- Access control logic is centralized in the API
- Changes to access control rules only need to be made in one place
- Consistent enforcement across all endpoints
Testing Dealer-Specific Access
To verify that dealer-specific access control is working correctly:
-
Create two API keys, each associated with a different dealer
-
Use each API key to:
- Fetch all vehicles
- Attempt to access a vehicle belonging to the other dealer
- Create a new vehicle
- Update a vehicle
-
Verify that:
- Each API key only sees vehicles from its associated dealer
- Attempts to access other dealers' vehicles are rejected
- New vehicles are correctly assigned to the appropriate dealer
Error Responses
When dealer-specific access control prevents an operation, the API returns a 403 Forbidden response with an appropriate error message:
{
"error": "Access denied: This vehicle does not belong to your dealer"
}
Limitations
- Super Admin Override: API keys with no dealer association (super admin keys) bypass dealer-specific access control
- Bulk Operations: Some bulk operations may have different behavior - check the specific endpoint documentation
- Performance Impact: The additional filtering may have a minor performance impact on some queries
Best Practices
- Use Dealer-Specific API Keys: For dealer-facing applications, always use API keys associated with the specific dealer
- Test Access Control: Verify that your application correctly handles 403 errors when attempting to access unauthorized resources
- Don't Rely on Client-Side Filtering: The API handles all necessary filtering, so don't duplicate this logic in your client
- Handle Errors Gracefully: Provide user-friendly error messages when access is denied